Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | {* |
2 | +--------------------------------------------------------------------+ | |
3 | | CiviCRM version 4.3 | | |
4 | +--------------------------------------------------------------------+ | |
5 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
6 | +--------------------------------------------------------------------+ | |
7 | | This file is a part of CiviCRM. | | |
8 | | | | |
9 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
10 | | under the terms of the GNU Affero General Public License | | |
11 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
12 | | | | |
13 | | CiviCRM is distributed in the hope that it will be useful, but | | |
14 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
16 | | See the GNU Affero General Public License for more details. | | |
17 | | | | |
18 | | You should have received a copy of the GNU Affero General Public | | |
19 | | License and the CiviCRM Licensing Exception along | | |
20 | | with this program; if not, contact CiviCRM LLC | | |
21 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
22 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
23 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
24 | +--------------------------------------------------------------------+ | |
25 | *} | |
26 | <div class="batch-entry form-item"> | |
27 | <div id="help"> | |
28 | {ts}Click Validate & Process below when you've entered all items for the batch. You can also Save & Continue Later at any time. Go to Administer > Customize Display & Screens > Profiles > Reserved Profiles > to add, remove or change the order of columns.{/ts} | |
29 | </div> | |
30 | {if $batchAmountMismatch} | |
31 | <div class="status message status-warning"> | |
32 | <div class="icon alert-icon"></div> {ts}Total for amounts entered below does not match the expected batch total.{/ts} | |
33 | </div> | |
34 | <div class="crm-button crm-button_qf_Entry_upload_force-save"> | |
35 | {$form._qf_Entry_upload_force.html} | |
36 | </div> | |
37 | <div class="clear"></div> | |
38 | {/if} | |
39 | <table class="form-layout-compressed batch-totals"> | |
40 | <tr><td class="label">{ts}Total amount expected{/ts}</td><td class="right"><span class="batch-expected-total">{$batchTotal|crmMoney}</span></td></tr> | |
41 | <tr><td class="label">{ts}Total amount entered{/ts}</td><td class="right">{$config->defaultCurrencySymbol} <span class="batch-actual-total"></span></td></tr> | |
42 | </table> | |
43 | ||
44 | <div class="crm-copy-fields crm-grid-table" id="crm-batch-entry-table"> | |
45 | <div class="crm-grid-header"> | |
46 | <div class="crm-grid-cell"> </div> | |
47 | <div class="crm-grid-cell">{ts}Contact{/ts}</div> | |
48 | {if $batchType eq 2 } | |
49 | <div class="crm-grid-cell"> </div> | |
50 | {/if} | |
51 | {foreach from=$fields item=field key=fieldName} | |
52 | <div class="crm-grid-cell"><img src="{$config->resourceBase}i/copy.png" alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}" fname="{$field.name}" class="action-icon" title="{ts}Click here to copy the value in row one to ALL rows.{/ts}" />{$field.title}</div> | |
53 | {/foreach} | |
54 | </div> | |
55 | {section name='i' start=1 loop=$rowCount} | |
56 | {assign var='rowNumber' value=$smarty.section.i.index} | |
57 | <div class="{cycle values="odd-row,even-row"} selector-rows crm-grid-row" entity_id="{$rowNumber}"> | |
58 | <div class="compressed crm-grid-cell"><span class="batch-edit"></span></div> | |
59 | {* contact select/create option*} | |
60 | <div class="compressed crm-grid-cell"> | |
61 | {include file="CRM/Contact/Form/NewContact.tpl" blockNo = $rowNumber noLabel=true prefix="primary_" newContactCallback="updateContactInfo($rowNumber, 'primary_')"} | |
62 | </div> | |
63 | ||
64 | {if $batchType eq 2 } | |
65 | {$form.member_option.$rowNumber.html} | |
66 | {/if} | |
67 | ||
68 | {foreach from=$fields item=field key=fieldName} | |
69 | {assign var=n value=$field.name} | |
70 | {if ( $fields.$n.data_type eq 'Date') or ( in_array( $n, array( 'thankyou_date', 'cancel_date', 'receipt_date', 'receive_date', 'join_date', 'membership_start_date', 'membership_end_date' ) ) ) } | |
71 | <div class="compressed crm-grid-cell"><span class="crm-batch-{$n}-{$rowNumber}">{include file="CRM/common/jcalendar.tpl" elementName=$n elementIndex=$rowNumber batchUpdate=1}</span></div> | |
72 | {elseif $n eq 'soft_credit'} | |
5ee60152 RN |
73 | <div class="compressed crm-grid-cell">{include file="CRM/Contact/Form/NewContact.tpl" blockNo = $rowNumber noLabel=true prefix="soft_credit_"} |
74 | {$form.soft_credit_amount.$rowNumber.label} {$form.soft_credit_amount.$rowNumber.html|crmAddClass:eight}</div> | |
6a488035 TO |
75 | {elseif in_array( $fields.$n.html_type, array('Radio', 'CheckBox'))} |
76 | <div class="compressed crm-grid-cell"> {$form.field.$rowNumber.$n.html}</div> | |
77 | {else} | |
78 | <div class="compressed crm-grid-cell">{$form.field.$rowNumber.$n.html}</div> | |
79 | {/if} | |
80 | {/foreach} | |
81 | </div> | |
82 | {/section} | |
83 | </div> | |
84 | <div class="crm-submit-buttons">{if $fields}{$form._qf_Batch_refresh.html}{/if} {$form.buttons.html}</div> | |
85 | </div> | |
86 | {literal} | |
87 | <script type="text/javascript"> | |
88 | cj(function(){ | |
89 | cj('.selector-rows').change(function(){ | |
90 | var options = { | |
91 | 'url' : {/literal}"{crmURL p='civicrm/ajax/batch' h=0}"{literal} | |
92 | }; | |
93 | ||
94 | cj("#Entry").ajaxSubmit(options); | |
95 | ||
96 | // validate rows | |
97 | checkColumns( cj(this) ); | |
98 | }); | |
5ee60152 RN |
99 | |
100 | cj('input[name^="soft_credit_contact["]').change(function(){ | |
101 | var rowNum = cj(this).attr('id').replace('soft_credit_contact_',''); | |
102 | var totalAmount = Number(cj('#field_'+rowNum+'_total_amount').val().replace(',','')); | |
103 | //assign total amount as default soft credit amount | |
104 | cj('#soft_credit_amount_'+ rowNum).val(totalAmount); | |
105 | }); | |
6a488035 TO |
106 | |
107 | // validate rows | |
108 | validateRow( ); | |
109 | ||
110 | //calculate the actual total for the batch | |
111 | calculateActualTotal(); | |
112 | ||
113 | cj('input[id*="_total_amount"]').bind('keyup change', function(){ | |
114 | calculateActualTotal(); | |
115 | }); | |
116 | ||
117 | {/literal}{if $batchType eq 1 }{literal} | |
118 | // hide all dates if send receipt is checked | |
119 | hideSendReceipt(); | |
120 | ||
121 | // hide the receipt date if send receipt is checked | |
122 | cj( 'input[id*="][send_receipt]"]').change( function() { | |
123 | showHideReceipt( cj(this) ); | |
124 | }); | |
125 | ||
126 | {/literal}{else}{literal} | |
127 | cj('select[id^="member_option_"]').each( function() { | |
128 | if ( cj(this).val() == 1 ) { | |
129 | cj(this).attr('disabled', true); | |
130 | } | |
131 | }); | |
132 | ||
133 | // set payment info accord to membership type | |
134 | cj( 'select[id*="_membership_type_0"]').change( function() { | |
135 | setPaymentBlock( cj(this), null ); | |
136 | }); | |
137 | ||
138 | cj( 'select[id*="_membership_type_1"]').change( function() { | |
139 | setPaymentBlock( cj(this), cj(this).val() ); | |
140 | }); | |
141 | ||
142 | {/literal}{/if}{literal} | |
143 | ||
144 | // line breaks between radio buttons and checkboxes | |
145 | cj('input.form-radio').next().after('<br />'); | |
146 | cj('input.form-checkbox').next().after('<br />'); | |
147 | ||
148 | //set the focus on first element | |
149 | cj('#primary_contact_1').focus(); | |
150 | ||
151 | }); | |
152 | ||
153 | function setPaymentBlock( form, memType ) { | |
154 | var rowID = form.closest('div.crm-grid-row').attr('entity_id'); | |
155 | var dataUrl = {/literal}"{crmURL p='civicrm/ajax/memType' h=0}"{literal}; | |
156 | ||
157 | if ( !memType ) { | |
158 | memType = cj( 'select[id="field_'+ rowID+'_membership_type_1"]').val(); | |
159 | } | |
160 | ||
161 | cj.post( dataUrl, {mtype: memType}, function( data ) { | |
cb2036b1 | 162 | cj('#field_' + rowID + '_financial_type').val( data.financial_type_id ); |
6a488035 TO |
163 | cj('#field_' + rowID + '_total_amount').val( data.total_amount ).change(); |
164 | }, 'json'); | |
165 | } | |
166 | ||
167 | function hideSendReceipt() { | |
168 | cj( 'input[id*="][send_receipt]"]').each( function() { | |
169 | showHideReceipt( cj(this) ); | |
170 | }); | |
171 | } | |
172 | ||
173 | function showHideReceipt( elem ) { | |
174 | var rowID = elem.closest('div.crm-grid-row').attr('entity_id'); | |
175 | var element = 'field_' + rowID + '_receipt_date'; | |
176 | if ( elem.prop('checked') ) { | |
177 | cj('.crm-batch-receipt_date-'+ rowID ).hide(); | |
178 | } else { | |
179 | cj('.crm-batch-receipt_date-'+ rowID ).show(); | |
180 | } | |
181 | } | |
182 | ||
183 | function validateRow( ) { | |
184 | cj('.selector-rows').each(function(){ | |
185 | checkColumns( cj(this) ); | |
186 | }); | |
187 | } | |
188 | ||
189 | function checkColumns( parentRow ) { | |
190 | // show valid row icon if all required data is field | |
191 | var validRow = 0; | |
192 | var inValidRow = 0; | |
193 | var errorExists = false; | |
194 | parentRow.find('div .required').each(function(){ | |
195 | if ( !cj(this).val( ) ) { | |
196 | inValidRow++; | |
197 | } else if ( cj(this).hasClass('error') && !cj(this).hasClass('valid') ) { | |
198 | errorExists = true; | |
199 | } else { | |
200 | validRow++; | |
201 | } | |
202 | }); | |
203 | ||
204 | // this means use has entered some data | |
205 | if ( errorExists ) { | |
206 | parentRow.find("div:first span").prop('class', 'batch-invalid'); | |
207 | } else if ( inValidRow == 0 && validRow > 0 ) { | |
208 | parentRow.find("div:first span").prop('class', 'batch-valid'); | |
209 | } else { | |
210 | parentRow.find("div:first span").prop('class', 'batch-edit'); | |
211 | } | |
212 | } | |
213 | ||
214 | function calculateActualTotal() { | |
215 | var total = 0; | |
216 | cj('input[id*="_total_amount"]').each(function(){ | |
217 | if ( cj(this).val() ) { | |
218 | total += parseFloat(cj(this).val()); | |
219 | } | |
220 | }); | |
221 | ||
222 | cj('.batch-actual-total').html(formatMoney(total)); | |
223 | } | |
224 | ||
225 | //money formatting/localization | |
226 | function formatMoney ( amount ) { | |
227 | var c = 2; | |
228 | var t = '{/literal}{$config->monetaryThousandSeparator}{literal}'; | |
229 | var d = '{/literal}{$config->monetaryDecimalPoint}{literal}'; | |
230 | ||
231 | var n = amount, | |
232 | c = isNaN(c = Math.abs(c)) ? 2 : c, | |
233 | d = d == undefined ? "," : d, | |
234 | t = t == undefined ? "." : t, s = n < 0 ? "-" : "", | |
235 | i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", | |
236 | j = (j = i.length) > 3 ? j % 3 : 0; | |
237 | ||
238 | return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); | |
239 | } | |
240 | ||
241 | function updateContactInfo( blockNo, prefix ) { | |
242 | var contactHiddenElement = 'input[name="' + prefix + 'contact_select_id[' + blockNo +']"]'; | |
243 | var contactId = cj( contactHiddenElement ).val();; | |
244 | ||
245 | var returnProperties = ''; | |
246 | var profileFields = new Array(); | |
247 | {/literal} | |
248 | {if $contactFields} | |
249 | {foreach from=$contactFields item=val key=fldName} | |
250 | var fldName = "{$fldName}"; | |
251 | {literal} | |
252 | if ( returnProperties ) { | |
253 | returnProperties = returnProperties + ','; | |
254 | } | |
255 | var fld = fldName.split('-'); | |
256 | returnProperties = returnProperties + fld[0]; | |
257 | profileFields[fld[0]] = fldName; | |
258 | {/literal} | |
259 | {/foreach} | |
260 | {/if} | |
261 | {literal} | |
262 | ||
263 | CRM.api('Contact','get',{ | |
264 | 'sequential' :'1', | |
265 | 'contact_id': contactId, | |
266 | 'return': returnProperties }, | |
267 | { success: function (data) { | |
268 | cj.each ( data.values[0], function( key, value ) { | |
269 | // set the values | |
270 | var actualFldName = profileFields[key]; | |
271 | if ( key == 'country' || key == 'state_province' ) { | |
272 | idFldName = key + '_id'; | |
273 | value = data.values[0][idFldName]; | |
274 | } | |
275 | setFieldValue( actualFldName, value, blockNo ) | |
276 | }); | |
277 | ||
278 | // for membership batch entry based on contact we need to enable / disable | |
279 | // add membership select | |
280 | {/literal}{if $batchType eq 2}{literal} | |
281 | CRM.api('Membership','get',{ | |
282 | 'sequential' :'1', | |
283 | 'contact_id': contactId, | |
284 | }, | |
285 | { success: function (data) { | |
286 | if ( data.count > 0 ) { | |
287 | //get the information on membership type | |
288 | var membershipTypeId = data.values[0].membership_type_id; | |
289 | var membershipJoinDate = data.values[0].join_date; | |
290 | CRM.api('MembershipType','get',{ | |
291 | 'sequential' :'1', | |
292 | 'id' : membershipTypeId | |
293 | }, | |
294 | { success: function (data){ | |
295 | var memTypeContactId = data.values[0].member_of_contact_id; | |
296 | cj('select[id="member_option_' + blockNo + '"]').removeAttr('disabled').val(2); | |
297 | cj('select[id="field_' + blockNo + '_membership_type_0"]').val( memTypeContactId ).change(); | |
298 | cj('select[id="field_' + blockNo + '_membership_type_1"]').val( membershipTypeId ).change(); | |
299 | setDateFieldValue( 'join_date', membershipJoinDate, blockNo ) | |
300 | } | |
301 | }); | |
302 | } | |
303 | } | |
304 | }); | |
305 | {/literal}{/if}{literal} | |
306 | } | |
307 | }); | |
308 | } | |
309 | ||
310 | /** | |
311 | * This function is use to setdefault elements via ajax | |
312 | * | |
313 | * @param fname string field name | |
314 | * @return void | |
315 | */ | |
316 | function setFieldValue( fname, fieldValue, blockNo ) { | |
317 | var elementId = cj('[name="field['+ blockNo +']['+ fname +']"]'); | |
318 | ||
319 | if ( elementId.length == 0 ) { | |
320 | elementId = cj('input[type=checkbox][name^="field['+ blockNo +']['+ fname +']"][type!=hidden]'); | |
321 | } | |
322 | ||
323 | // if element not found than return | |
324 | if ( elementId.length == 0 ) { | |
325 | return; | |
326 | } | |
327 | ||
328 | //check if it is date element | |
329 | var isDateElement = elementId.attr('format'); | |
330 | ||
331 | // check if it is wysiwyg element | |
332 | var editor = elementId.attr('editor'); | |
333 | ||
334 | //get the element type | |
335 | var elementType = elementId.attr('type'); | |
336 | ||
337 | // set the value for all the elements, elements needs to be handled are | |
338 | // select, checkbox, radio, date fields, text, textarea, multi-select | |
339 | // wysiwyg editor, advanced multi-select ( to do ) | |
340 | if ( elementType == 'radio' ) { | |
341 | if ( fieldValue ) { | |
342 | elementId.filter("[value=" + fieldValue + "]").prop("checked",true); | |
343 | } else { | |
344 | elementId.removeProp('checked'); | |
345 | } | |
346 | } else if ( elementType == 'checkbox' ) { | |
347 | // handle checkbox | |
348 | elementId.removeProp('checked'); | |
349 | if ( fieldValue ) { | |
350 | cj.each( fieldValue, function( key, value ) { | |
351 | cj('input[name="field['+ blockNo +']['+ fname +']['+ value +']"]').prop('checked', true); | |
352 | }); | |
353 | } | |
354 | } else if ( editor ) { | |
355 | switch ( editor ) { | |
356 | case 'ckeditor': | |
357 | var elemtId = elementId.attr('id'); | |
358 | oEditor = CKEDITOR.instances[elemtId]; | |
359 | oEditor.setData( htmlContent ); | |
360 | break; | |
361 | case 'tinymce': | |
362 | var elemtId = element.attr('id'); | |
363 | tinyMCE.get( elemtId ).setContent( htmlContent ); | |
364 | break; | |
365 | case 'joomlaeditor': | |
366 | // TO DO | |
367 | case 'drupalwysiwyg': | |
368 | // TO DO | |
369 | default: | |
370 | elementId.val( fieldValue ); | |
371 | } | |
372 | } else { | |
373 | elementId.val( fieldValue ); | |
374 | } | |
375 | ||
376 | // since we use different display field for date we also need to set it. | |
377 | // also check for date time field and set the value correctly | |
378 | if ( isDateElement && fieldValue ) { | |
379 | setDateFieldValue( fname, fieldValue, blockNo ) | |
380 | } | |
381 | } | |
382 | ||
383 | function setDateFieldValue( fname, fieldValue, blockNo ) { | |
384 | var dateValues = fieldValue.split(' '); | |
385 | ||
386 | var actualDateElement = cj('#field_'+ blockNo +'_' + fname ); | |
387 | var date_format = actualDateElement.attr('format'); | |
388 | var altDateFormat = 'yy-mm-dd'; | |
389 | ||
390 | var actualDateValue = cj.datepicker.parseDate( altDateFormat, dateValues[0] ); | |
391 | ||
392 | // format date according to display field | |
393 | var hiddenDateValue = cj.datepicker.formatDate( 'mm/dd/yy', actualDateValue ); | |
394 | ||
395 | actualDateElement.val( hiddenDateValue ); | |
396 | ||
397 | var displayDateValue = actualDateElement.val(); | |
398 | if ( date_format != 'mm/dd/yy' ) { | |
399 | displayDateValue = cj.datepicker.formatDate( date_format, actualDateValue ); | |
400 | } | |
401 | ||
402 | cj('#field_'+ blockNo +'_' + fname + '_display').val( displayDateValue ); | |
403 | ||
404 | // need to fix time formatting | |
405 | if ( dateValues[1] ) { | |
406 | cj('#field_'+ blockNo +'_' + fname + '_time').val(dateValues[1].substr(0,5)); | |
407 | } | |
408 | } | |
409 | ||
410 | </script> | |
411 | {/literal} | |
412 | ||
413 | {*include batch copy js js file*} | |
414 | {include file="CRM/common/batchCopy.tpl"} |