· 7 years ago · Dec 18, 2018, 05:42 PM
1
21. Let's create the two new date fields in the database that we ultimately want to be able to edit for a contact/account relationship.
3Open metadata/accounts_contactsMetaData.php and add date_start, date_end:
4
5 , array(
6'name' =>'account_id',
7'type' =>'varchar',
8'len'=>'36'),
9 array (
10'name' => 'date_start',
11'type' => 'date'),
12 array (
13'name' => 'date_end',
14'type' => 'date'),
15 array (
16'name' => 'date_modified',
17'type' => 'datetime')
18
19Note: This has to be done in the metadata version instead of custom/metadata since the file already exists as processing of metadata does not give precedence to the custom/metadata version
20X
212. Run Admin->Repair->Quick Repair and Rebuild
22X
233. You will be prompted to run the following SQL. Execute it and the fields will be added to the database:
24ALTER TABLE accounts_contacts add column date_start date NULL , add column date_end date NULL ;
25X
264. Next we want to create the edit screen. Copy the following files in modules/Contacts to custom/modules/Contacts and rename:
27ContactOpportunityRelationshipEdit.php rename to ContactAccountRelationshipEdit.php
28SaveContactOpportunityRelationship.php rename to SaveContactAccountRelationship.php
29ContactOpportunityRelationship.php rename to ContactAccountRelationship.php
30ContactOpportunityRelationshipEdit.html rename to ContactAccountRelationshipEdit.html
31
32X
335. Replace all occurrences of ContactOpportunity with ContactAccount
34X
356. Edit ContactAccountRelationshipEdit.php and change the path at the top to point to the custom directory:
36
37 require_once('custom/modules/Contacts/ContactAccountRelationship.php');
38
39And further below:
40
41 $xtpl=new XTemplate('custom/modules/Contacts/ContactAccountRelationshipEdit.html');
42X
437. Now do the same with SaveContactOpportunityRelationship.php:
44
45 require_once('custom/modules/Contacts/ContactAccountRelationship.php');
46X
478. Edit ContactAccountRelationship.php to remove all mentions of the opportunity and contact role fields and include our account and date start/end fields. Top section:
48
49 // Stored fields
50 var $id;
51 var $contact_id;
52 var $date_start;
53 var $date_end;
54 var $account_id;
55
56 // Related fields
57 var $contact_name;
58 var $account_name;
59
60 var $table_name = "accounts_contacts";
61 var $object_name = "ContactAccountRelationship";
62
63 var $column_fields = Array(
64"id",
65 "contact_id" ,
66 "account_id" ,
67 "date_start" ,
68 "date_end",
69 'date_modified'
70 );
71
72Field Defs array:
73
74var $field_defs = array (
75'id'=>array(
76'name' =>'id',
77'type' =>'char',
78'len'=>'36',
79'default'=>''),
80'contact_id'=>array(
81'name' =>'contact_id',
82'type' =>'char',
83'len'=>'36', ),
84'account_id'=>array(
85'name' =>'account_id',
86'type' =>'char',
87'len'=>'36',),
88'date_start'=>array(
89'name' =>'date_start',
90'type' =>'datetime'),
91'date_end'=>array(
92'name' =>'date_end',
93'type' =>'datetime'),
94'date_modified'=>array (
95'name' => 'date_modified',
96'type' => 'datetime'),
97'deleted'=>array(
98'name' =>'deleted',
99'type' =>'bool',
100'len'=>'1',
101'default'=>'0',
102'required'=>true)
103 );
104
105In the fill_in_additional_detail_fields() function replace the opportunity section with:
106
107 if(isset($this->account_id) && $this->account_id != "")
108 {
109 $query = "SELECT name from accounts where id='$this->account_id' AND deleted=0";
110 $result =$this->db->query($query,true," Error filling in additional detail fields: ");
111 // Get the name.
112 $row = $this->db->fetchByAssoc($result);
113
114 if($row != null)
115 {
116 $this->account_name = $row['name'];
117 }
118 }
119X
1209. Now we need to add the start/end dates to the subpanel and alter the edit button so that it goes to the edit relationship screen. Lets see how Opportunities does it by opening modules/Opportunities/metadata/subpaneldefs.php
121X
12210. In subpaneldefs.php notice that for the Contacts subpanel it uses the ForOpportunities subpanel:
123
124 'contacts' => array(
125 'order' => 30,
126 'module' => 'Contacts',
127 'sort_order' => 'asc',
128 'sort_by' => 'last_name, first_name',
129 'subpanel_name' => 'ForOpportunities',
130 'get_subpanel_data' => 'contacts',
131 'add_subpanel_data' => 'contact_id',
132 'title_key' => 'LBL_CONTACTS_SUBPANEL_TITLE',
133 'top_buttons' => array(
134 array('widget_class' => 'SubPanelTopCreateAccountNameButton'),
135 array('widget_class' => 'SubPanelTopSelectButton',
136 'popup_module' => 'Opportunities',
137 'mode' => 'MultiSelect',
138 'initial_filter_fields' => array(
139'account_id' => 'account_id',
140'account_name' => 'account_name'
141),
142 ),
143 ),
144 ),
145X
14611. Open modules/Contacts/metadata/subpanels/ForOpportunities.php and you'll see the following:
147
148......
149 'opportunity_role_fields'=>array(
150 'usage' => 'query_only',
151 ),
152 'opportunity_role_id'=>array(
153 'usage' => 'query_only',
154 ),
155 'opportunity_role'=>array(
156 'name'=>'opportunity_role',
157 'vname' => 'LBL_LIST_CONTACT_ROLE',
158 'width' => '10%',
159 'sortable'=>false,
160 ),
161......
162 //kbrill Bug#17483
163 'edit_button'=>array(
164 'vname' => 'LBL_EDIT_BUTTON',
165 'widget_class' => 'SubPanelEditRoleButton',
166 'role_id'=>'opportunity_role_id',
167 'module' => 'Contacts',
168 'width' => '5%',
169 ),
170......
171
172There are some query only fields that help get the relationship fields passed through.
173Below that is the edit button with a custom widget class that passes the relationship id through to the edit screen.
174We will need to create our own widget as well.
175X
17612. The goal is to add the start/end dates to the Contacts subpanel of an Account record. We need to find out which subpanel layout to alter.
177Open modules/Accounts/metadata/subpaneldefs.php.
178
179Notice that for the Contacts subpanel which subpanel layout it uses:
180
181......
182 'subpanel_name' => 'ForAccounts',
183.....
184X
18514. Copy modules/Contacts/metadata/subpanels/ForAccounts.php to custom/modules/Contacts/metadata/subpanels/
186Note: Create the directory structure if it does not exist yet
187X
18815. Change the edit_button definition to:
189
190 'edit_button'=>array(
191 'vname' => 'LBL_EDIT_BUTTON',
192'widget_class' => 'SubPanelEditAccountContactButton',
193'account_contact_id'=>'account_contact_id',
194 'module' => 'Contacts',
195 'width' => '5%',
196 ),
197
198Notice our widget_class – we'll get back to that
199
200
20116. Above the edit button add our eventual start/end dates along with some needed fields to pass the ID of the relationship to our edit screen:
202
203 'account_contact_fields'=>array(
204 'usage' => 'query_only',
205 ),
206 'account_contact_id'=>array(
207 'usage' => 'query_only',
208 ),
209 'account_contact_date_start'=>array(
210 'name'=>'account_contact_date_start',
211 'vname' => 'LBL_ACCOUNT_CONTACT_DATE_START',
212 'width' => '10%',
213 'sortable'=>false,
214 ),
215 'account_contact_date_end'=>array(
216 'name'=>'account_contact_date_end',
217 'vname' => 'LBL_ACCOUNT_CONTACT_DATE_END',
218 'width' => '10%',
219 'sortable'=>false,
220 ),
221Notice the account_contact_id. This tells Sugar to send over additional info to the widget.
222We need to setup the field to get the contact ID to pass over.
223X
22417. Create a custom/Extension/modules/Contacts/Ext/Vardefs/accounts_contactsVardefs.php
225Note: Create the directory structure if it does not exist yet
226X
22718. Paste the following code in and run a Quick Repair & Rebuild:
228
229<?php
230$dictionary['Contact']['fields']['account_contact_fields'] = array (
231 'name' => 'account_contact_fields',
232 'rname' => 'id',
233 'relationship_fields'=>array(
234'id' => 'account_contact_id',
235'date_start' => 'account_contact_date_start',
236'date_end' => 'account_contact_date_end'
237),
238 'vname' => 'LBL_ACCOUNT_CONTACT_FIELDS',
239 'type' => 'relate',
240 'link' => 'accounts',
241 'link_type' => 'relationship_info',
242 'join_link_name' => 'accounts_contacts',
243 'source' => 'non-db',
244 'importable' => false,
245 'duplicate_merge'=> 'disabled',
246 'studio' => array('listview' => false),
247 'join_primary' => false, //this is key! See SugarBean.php & search for join_primary for more info
248);
249
250$dictionary['Contact']['fields']['account_contact_id'] = array (
251 'name' => 'account_contact_id',
252 'type' => 'varchar',
253 'source' => 'non-db',
254 'vname' => 'LBL_ACCOUNT_CONTACT_ID',
255 'studio' => array('listview' => false),
256);
257
258$dictionary['Contact']['fields']['account_contact_date_start'] = array (
259 'name' => 'account_contact_date_start',
260 'type' => 'date',
261 'source' => 'non-db',
262 'vname' => 'LBL_ACCOUNT_CONTACT_DATE_START',
263);
264
265$dictionary['Contact']['fields']['account_contact_date_end'] = array (
266 'name' => 'account_contact_date_end',
267 'type' => 'date',
268 'source' => 'non-db',
269 'vname' => 'LBL_ACCOUNT_CONTACT_DATE_END',
270);
271
272Note: relationship_fields helps map the query result to the ContactAccountRelationship bean
273X
27419. Now we need to create our own widget class based on the SubPanelEditRoleButton class.
275Copy include/generic/SugarWidgets/SugarWidgetSubPanelEditRoleButton.php to custom/include/generic/SugarWidgets
276and rename to SugarWidgetSubPanelEditAccountContactButton.php
277
278Rename the class name contained in the file SugarWidgetSubPanelEditRoleButton to SugarWidgetSubPanelEditAccountContactButton
279Note: Create the directory structure if it does not exist yet
280X
28120. Edit SugarWidgetSubPanelEditAccountContactButton.php and change these 2 lines:
282
283 . '&action=' . 'ContactOpportunityRelationshipEdit'
284 . '&record=' . $layout_def['fields']['OPPORTUNITY_ROLE_ID']
285
286To:
287
288 . '&action=' . 'ContactAccountRelationshipEdit'
289 . '&record=' . $layout_def['fields']['ACCOUNT_CONTACT_ID']
290X
29121. Open an Account record in SugarCRM and scroll down to the Contacts subpanel.
292Notice that we now have those pesky labels that need to be translated.
293
294
29522. Create and add the following code to custom/Extension/modules/Contacts/Ext/Language/en_us.Accounts_Contacts_StartEnd.php
296Note: Create the directory structure if it does not exist yet. Prepend with the language code of your choice.
297
298<?php
299$mod_strings['LBL_CONTACT_ACCOUNT_FORM_TITLE'] = 'Contact-Account';
300$mod_strings['LBL_ACCOUNT_CONTACT_DATE_START'] = 'Start Date';
301$mod_strings['LBL_ACCOUNT_CONTACT_DATE_END'] = 'End Date';
302X
30323. Run Repair & Rebuild and refresh the Account screen. The labels should now be translated correctly.
304X
30524. For a Contact in the subpanel click on the edit button. We have an edit screen! But there is work to be done yet.
306Note: If the contact name doesn't show on the edit screen go back and hover over the edit link.
307You should see a record= followed by a guid. If not, something in from a previous step was done incorrectly.
308X
30925. To get the Account to show up correctly edit custom/modules/Contacts/ContactAccountRelationshipEdit.html
310Change {MOD.LBL_OPP_NAME} to {MOD.LBL_ACCOUNT_NAME} and remove the opportunity select and replace with {ACCOUNT.NAME}. So it looks like the following:
311
312Before:
313
314 <td width="15%" scope="row"><span>{MOD.LBL_OPP_NAME}</span></td>
315 <td width="35%" ><span>
316 <input type="text" class='sqsEnabled' id='opportunity_name' name='opportunity_name' rows="2" cols="30" value="{OPPORTUNITY.NAME}" />
317 <input id='opportunity_id' name='opportunity_id' type="hidden" value='{OPPORTUNITY.ID}'>
318 <input type="button" name="btn1" class="button"
319 title="{APP.LBL_SELECT_BUTTON_TITLE}"
320 accesskey="{APP.LBL_SELECT_BUTTON_KEY}"
321 value='{APP.LBL_SELECT_BUTTON_LABEL}'
322 onclick='open_popup("Opportunities",600,400,"",true,false,{"call_back_function":"set_return","form_name":"EditView","field_to_name_array":{"id":"opportunity_id","name":"opportunity_name"}});' />
323 </span></td>
324
325After:
326
327 <td width="15%" scope="row"><span>{MOD.LBL_ACCOUNT_NAME}</span></td>
328 <td width="35%" ><span>{ACCOUNT.NAME}</span></td>
329
330Note: Yes, we are removing the ability to change the actual relationship. It will save trouble down the road if we do not allow the Contact or Account to be changed.
331
332
33326. Edit custom/modules/ContactAccountRelationshipEdit.php and change
334
335 safe_map('opportunity_name', $focus);
336 safe_map('opportunity_id', $focus);
337To:
338
339 safe_map('account_name', $focus);
340 safe_map('account_id', $focus);
341
342As well as:
343
344$xtpl->assign("OPPORTUNITY",$oppName = Array("NAME" => $focus->opportunity_name, "ID" => $focus->opportunity_id));
345
346To:
347
348$xtpl->assign("ACCOUNT",$accName = Array("NAME" => $focus->account_name));
349
350Also remove:
351safe_map('contact_role', $focus);
352X
35327. Refresh the edit screen and the Account name now shows.
354X
35528. Edit ContactAccountRelationshipEdit.html, remove the contact select, and replace with {CONTACT.NAME}. So it looks like the following:
356
357Before:
358
359 <td width="15%" scope="row"><span>{MOD.LBL_CONTACT_NAME}</span></td>
360 <td width="35%" ><span>
361 <input type="text" name='contact_name' rows="1" cols="30" value="{CONTACT.NAME}" readonly="readonly" />
362 <input type="hidden" name='contact_id' value='{CONTACT.ID}'>
363 <input type="button" name="btn1" class="button"
364 title="{APP.LBL_SELECT_BUTTON_TITLE}"
365 value='{APP.LBL_SELECT_BUTTON_LABEL}'
366 onclick='open_popup("Contacts",600,400,"",true,false,{"call_back_function":"set_return","form_name":"EditView","field_to_name_array":{"id":"contact_id","name":"contact_name"}});' />
367 </span></td>
368
369After:
370
371 <td width="15%" scope="row"><span>{MOD.LBL_CONTACT_NAME}</span></td>
372 <td width="35%" ><span>{CONTACT.NAME}</span></td>
373
374Refresh the edit screen and the Contact name now shows without the select box.
375
376
37729. Time to fix the title at the top of the edit page. Edit ContactAccountRelationshipEdit.php.
378Change $oppName['NAME'] to $accName['NAME']
379Change $mod_strings['LBL_CONTACT_OPP_FORM_TITLE']." " to $mod_strings['LBL_CONTACT_ACCOUNT_FORM_TITLE'].": "
380Refresh the edit screen and the title bar should now display correctly.
381X
38230. Now add our start/end dates. Edit ContactAccountRelationshipEdit.html
383Change Role field from:
384
385 <tr>
386 <td scope="row"><span>{MOD.LBL_CONTACT_ROLE}</span></td>
387 <td ><span><select name='contact_role'>{CONTACT_ROLE_OPTIONS}</select></span></td>
388 <td scope="row"><span> </span></td>
389 <td ><span> </span></td>
390 </tr>
391To:
392
393 <tr>
394 <td scope="row"><slot>{MOD.LBL_ACCOUNT_CONTACT_DATE_START}:</slot></td>
395 <td ><slot><input name='date_start' id='jscal_start_date' onblur="parseDate(this, '{CALENDAR_DATEFORMAT}');" tabindex='8' size='11' maxlength='10' type="text" value="{DATE_START}"> <img src="index.php?entryPoint=getImage&themeName={THEME}&imageName=jscalendar.gif" alt="{CALENDAR_DATEFORMAT}" id="start_date_jscal_trigger" align="absmiddle"> <span class="dateFormat">{USER_DATEFORMAT}</span></slot></td>
396 <td scope="row"><slot>{MOD.LBL_ACCOUNT_CONTACT_DATE_END}:</slot></td>
397 <td ><slot><input name='date_end' id='jscal_end_date' onblur="parseDate(this, '{CALENDAR_DATEFORMAT}');" tabindex='8' size='11' maxlength='10' type="text" value="{DATE_END}"> <img src="index.php?entryPoint=getImage&themeName={THEME}&imageName=jscalendar.gif" alt="{CALENDAR_DATEFORMAT}" id="end_date_jscal_trigger" align="absmiddle"> <span class="dateFormat">{USER_DATEFORMAT}</span></slot></td>
398 </tr>
399
400
40131. In the same file right below the closing form tag add following script to get the calendar popup to work correctly:
402
403<script>
404 Calendar.setup ({
405 inputField : "jscal_start_date", ifFormat : "{CALENDAR_DATEFORMAT}", showsTime : false, button : "start_date_jscal_trigger", singleClick : true, step : 1
406 });
407
408 Calendar.setup ({
409 inputField : "jscal_end_date", ifFormat : "{CALENDAR_DATEFORMAT}", showsTime : false, button : "end_date_jscal_trigger", singleClick : true, step : 1
410 });
411</script>
412
413
41432. Edit ContactAccountRelationshipEdit.php and remove the following code that references the contact role field:
415
416$xtpl->assign("CONTACT_ROLE_OPTIONS", get_select_options_with_id($app_list_strings['opportunity_relationship_type_dom'], $focus->contact_role));
417
418And replace with:
419
420global $timedate;
421$xtpl->assign('THEME', SugarThemeRegistry::current()->__toString());
422$xtpl->assign('USER_DATEFORMAT', '('.$timedate->get_user_date_format().')');
423$xtpl->assign("CALENDAR_DATEFORMAT", $timedate->get_cal_date_format());
424$xtpl->assign("DATE_START", $timedate->to_display_date($focus->date_start, false));
425$xtpl->assign("DATE_END", $timedate->to_display_date($focus->date_end, false));
426
427
42833. While in this file remove the following two blocks of code:
429
430require_once('include/QuickSearchDefaults.php');
431$qsd = QuickSearchDefaults::getQuickSearchDefaults();
432$sqs_objects = array('opportunity_name' => $qsd->getQSParent());
433$sqs_objects['opportunity_name']['populate_list'] = array('opportunity_name', 'opportunity_id');
434$quicksearch_js = '<script type="text/javascript" language="javascript">sqs_objects = ' . $json->encode($sqs_objects) . '</script>';
435echo $quicksearch_js;
436
437
438And:
439
440$javascript = new javascript();
441$javascript->setFormName('EditView');
442$javascript->setSugarBean($focus);
443$javascript->addToValidateBinaryDependency('opportunity_name', 'alpha', $app_strings['ERR_SQS_NO_MATCH_FIELD'] . $mod_strings['LBL_OPP_NAME'], 'false', '', 'opportunity_id');
444echo $javascript->getScript();