Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | {* |
2 | +--------------------------------------------------------------------+ | |
819d0d41 | 3 | | CiviCRM version 4.5 | |
6a488035 | 4 | +--------------------------------------------------------------------+ |
819d0d41 | 5 | | Copyright CiviCRM LLC (c) 2004-2014 | |
6a488035 TO |
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 | ||
27 | {* Financial search component. *} | |
28 | <div id="enableDisableStatusMsg" class="crm-container" style="display:none"></div> | |
29 | <div class="crm-submit-buttons"> | |
30 | <a accesskey="N" href="{crmURL p='civicrm/financial/batch' q="reset=1&action=add&context=$batchStatus"}" id="newBatch" class="button"><span><div class="icon add-icon"></div>{ts}New Accounting Batch{/ts}</span></a> | |
31 | </div> | |
32 | <div class="crm-form-block crm-search-form-block"> | |
33 | <div class="crm-accordion-wrapper crm-activity_search-accordion"> | |
34 | <div class="crm-accordion-header"> | |
35 | {ts}Filter Results{/ts} | |
36 | </div> | |
37 | <div class="crm-accordion-body"> | |
38 | <div id="financial-search-form" class="crm-block crm-form-block"> | |
39 | <table class="form-layout-compressed"> | |
40 | {* Loop through all defined search criteria fields (defined in the buildForm() function). *} | |
41 | {foreach from=$elements item=element} | |
42 | <tr class="crm-financial-search-form-block-{$element}"> | |
43 | <td class="label">{$form.$element.label}</td> | |
44 | <td>{$form.$element.html}</td> | |
45 | </tr> | |
46 | {/foreach} | |
47 | </table> | |
48 | </div> | |
49 | </div> | |
50 | </div> | |
51 | </div> | |
52 | <div class="form-layout-compressed">{$form.batch_update.html} {$form.submit.html}</div><br/> | |
53 | <table id="crm-batch-selector" class="row-highlight"> | |
54 | <thead> | |
55 | <tr> | |
56 | <th class="crm-batch-checkbox">{$form.toggleSelect.html}</th> | |
57 | <th class="crm-batch-name">{ts}Batch Name{/ts}</th> | |
58 | <th class="crm-batch-payment_instrument">{ts}Payment Instrument{/ts}</th> | |
59 | <th class="crm-batch-item_count">{ts}Item Count{/ts}</th> | |
60 | <th class="crm-batch-total">{ts}Total Amount{/ts}</th> | |
61 | <th class="crm-batch-status">{ts}Status{/ts}</th> | |
62 | <th class="crm-batch-created_by">{ts}Created By{/ts}</th> | |
63 | <th></th> | |
64 | </tr> | |
65 | </thead> | |
66 | </table> | |
67 | {include file="CRM/Form/validate.tpl"} | |
68 | {literal} | |
69 | <script type="text/javascript"> | |
3cc60a06 | 70 | CRM.$(function($) { |
6a488035 TO |
71 | var batchSelector; |
72 | buildBatchSelector(); | |
6f9cd76f | 73 | $("#batch_update").prop('disabled', false); |
6a488035 | 74 | |
f8db8a66 CW |
75 | $('#financial-search-form :input') |
76 | .change(function() { | |
77 | if (!$(this).hasClass('crm-inline-error')) { | |
78 | batchSelector.fnDraw(); | |
79 | } | |
80 | }) | |
81 | .keypress(function(event) { | |
82 | if (event.which == 13) { | |
83 | event.preventDefault(); | |
84 | $(this).change(); | |
85 | return false; | |
86 | } | |
87 | }); | |
6a488035 TO |
88 | |
89 | var checkedRows = []; | |
90 | function buildBatchSelector() { | |
91 | var ZeroRecordText = {/literal}'<div class="status messages">{ts escape="js"}No Accounting Batches match your search criteria.{/ts}</div>'{literal}; | |
92 | var sourceUrl = {/literal}'{crmURL p="civicrm/ajax/batchlist" h=0 q="snippet=4&context=financialBatch"}'{literal}; | |
93 | ||
94 | batchSelector = $('#crm-batch-selector').dataTable({ | |
95 | "bFilter" : false, | |
96 | "bAutoWidth" : false, | |
97 | "aaSorting" : [], | |
98 | "aoColumns" : [ | |
99 | {sClass:'crm-batch-checkbox', bSortable:false}, | |
100 | {sClass:'crm-batch-name'}, | |
101 | {sClass:'crm-batch-payment_instrument'}, | |
102 | {sClass:'crm-batch-item_count right'}, | |
103 | {sClass:'crm-batch-total right'}, | |
104 | {sClass:'crm-batch-status'}, | |
105 | {sClass:'crm-batch-created_by'}, | |
106 | {sClass:'crm-batch-links', bSortable:false}, | |
107 | ], | |
108 | "bProcessing": true, | |
109 | "asStripClasses" : ["odd-row", "even-row"], | |
110 | "sPaginationType": "full_numbers", | |
111 | "sDom" : '<"crm-datatable-pager-top"lfp>rt<"crm-datatable-pager-bottom"ip>', | |
112 | "bServerSide": true, | |
113 | "bJQueryUI": true, | |
114 | "sAjaxSource": sourceUrl, | |
115 | "iDisplayLength": 25, | |
116 | "oLanguage": { | |
117 | "sZeroRecords": ZeroRecordText, | |
118 | "sProcessing": {/literal}"{ts escape='js'}Processing...{/ts}"{literal}, | |
119 | "sLengthMenu": {/literal}"{ts escape='js'}Show _MENU_ entries{/ts}"{literal}, | |
120 | "sInfo": {/literal}"{ts escape='js'}Showing _START_ to _END_ of _TOTAL_ entries{/ts}"{literal}, | |
121 | "sInfoEmpty": {/literal}"{ts escape='js'}Showing 0 to 0 of 0 entries{/ts}"{literal}, | |
122 | "sInfoFiltered": {/literal}"{ts escape='js'}(filtered from _MAX_ total entries) {/ts}"{literal}, | |
123 | "sSearch": {/literal}"{ts escape='js'}Search:{/ts}"{literal}, | |
124 | "oPaginate": { | |
125 | "sFirst": {/literal}"{ts escape='js'}First{/ts}"{literal}, | |
126 | "sPrevious": {/literal}"{ts escape='js'}Previous{/ts}"{literal}, | |
127 | "sNext": {/literal}"{ts escape='js'}Next{/ts}"{literal}, | |
128 | "sLast": {/literal}"{ts escape='js'}Last{/ts}"{literal} | |
129 | } | |
130 | }, | |
131 | "fnServerParams": function (aoData) { | |
132 | $('#financial-search-form :input').each(function() { | |
133 | if ($(this).val()) { | |
134 | aoData.push( | |
135 | {name:$(this).attr('id'), value: $(this).val()} | |
136 | ); | |
137 | } | |
138 | }); | |
139 | checkedRows = []; | |
140 | $("#crm-batch-selector input.select-row:checked").each(function() { | |
141 | checkedRows.push('#' + $(this).attr('id')); | |
142 | }); | |
143 | }, | |
144 | "fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) { | |
145 | var box = $(aData[0]); | |
146 | var id = box.attr('id').replace('check_', ''); | |
147 | $(nRow).addClass('crm-entity').attr('data-entity', 'batch').attr('data-id', id).attr('data-status_id', box.attr('data-status_id')); | |
148 | $('td:eq(1)', nRow).wrapInner('<div class="crm-editable crmf-title" />'); | |
149 | return nRow; | |
150 | }, | |
151 | "fnDrawCallback": function(oSettings) { | |
152 | $('.crm-editable', '#crm-batch-selector').crmEditable(); | |
153 | $("#toggleSelect").prop('checked', false); | |
154 | if (checkedRows.length) { | |
155 | $(checkedRows.join(',')).prop('checked', true).change(); | |
156 | } | |
157 | } | |
158 | }); | |
159 | } | |
160 | ||
161 | function editRecords(records, op) { | |
162 | records = validateOp(records, op); | |
163 | if (records.length) { | |
164 | $("#enableDisableStatusMsg").dialog({ | |
165 | title: {/literal}'{ts escape="js"}Confirm Changes{/ts}'{literal}, | |
166 | modal: true, | |
6a488035 TO |
167 | open:function() { |
168 | switch (op) {{/literal} | |
169 | case 'reopen': | |
170 | var msg = '<h3>{ts escape="js"}Are you sure you want to re-open:{/ts}</h3>'; | |
171 | break; | |
172 | case 'delete': | |
173 | var msg = '<h3>{ts escape="js"}Are you sure you want to delete:{/ts}</h3>'; | |
174 | break; | |
175 | case 'close': | |
176 | var msg = '<h3>{ts escape="js"}Are you sure you want to close:{/ts}</h3>'; | |
177 | break; | |
178 | case 'export': | |
179 | var msg = '<h3>{ts escape="js"}Export:{/ts}</h3>\ | |
180 | <div>\ | |
181 | <label>{ts escape="js"}Format:{/ts}</label>\ | |
182 | <select class="export-format">\ | |
183 | <option value="IIF">IIF</option>\ | |
184 | <option value="CSV">CSV</option>\ | |
185 | </select>\ | |
186 | </div>'; | |
187 | break; | |
188 | {literal}} | |
189 | msg += listRecords(records, op == 'close' || op == 'export'); | |
190 | $('#enableDisableStatusMsg').show().html(msg); | |
191 | }, | |
192 | buttons: { | |
193 | {/literal}"{ts escape='js'}Cancel{/ts}"{literal}: function() { | |
194 | $(this).dialog("close"); | |
195 | }, | |
196 | {/literal}"{ts escape='js'}OK{/ts}{literal}": function() { | |
197 | saveRecords(records, op); | |
198 | $(this).dialog("close"); | |
199 | } | |
200 | } | |
201 | }); | |
202 | } | |
203 | } | |
204 | ||
205 | function listRecords(records, compareValues) { | |
206 | var txt = '<ul>', | |
207 | mismatch = false; | |
208 | for (var i in records) { | |
209 | var $tr = $('tr[data-id=' + records[i] + ']'); | |
210 | txt += '<li>' + $('.crmf-title', $tr).text(); | |
211 | if (compareValues) { | |
212 | $('.actual-value.crm-error', $tr).each(function() { | |
213 | mismatch = true; | |
214 | var $th = $tr.closest('table').find('th').eq($(this).closest('td').index()); | |
215 | var $expected = $(this).siblings('.expected-value'); | |
216 | var label = $th.text(); | |
217 | var actual = $(this).text(); | |
218 | var expected = $expected.text(); | |
219 | txt += {/literal}'<div class="messages crm-error"><strong>' + | |
220 | label + ' {ts escape="js"}mismatch.{/ts}</strong><br />{ts escape="js"}Expected{/ts}: ' + expected + '<br />{ts escape="js"}Current Total{/ts}: ' + actual + '</div>'{literal}; | |
221 | }); | |
222 | } | |
223 | txt += '</li>'; | |
224 | } | |
225 | txt += '</ul>'; | |
226 | if (mismatch) { | |
227 | txt += {/literal}'<div class="messages status">{ts escape="js"}Click OK to override and update expected values.{/ts}</div>'{literal} | |
228 | } | |
229 | return txt; | |
230 | } | |
231 | ||
232 | function saveRecords(records, op) { | |
233 | if (op == 'export') { | |
234 | return exportRecords(records); | |
235 | } | |
236 | var postUrl = CRM.url('civicrm/ajax/rest', 'className=CRM_Financial_Page_AJAX&fnName=assignRemove'); | |
237 | //post request and get response | |
238 | $.post(postUrl, {records: records, recordBAO: 'CRM_Batch_BAO_Batch', op: op, key: {/literal}"{crmKey name='civicrm/ajax/ar'}"{literal}}, | |
239 | function(response) { | |
240 | //this is custom status set when record update success. | |
241 | if (response.status == 'record-updated-success') { | |
242 | CRM.alert(listRecords(records), op == 'delete' ? {/literal}'{ts escape="js"}Deleted{/ts}' : '{ts escape="js"}Updated{/ts}'{literal}, 'success'); | |
243 | batchSelector.fnDraw(); | |
244 | } | |
245 | else { | |
246 | CRM.alert({/literal}'{ts escape="js"}An error occurred while processing your request.{/ts}', $("#batch_update option[value=" + op + "]").text() + ' {ts escape="js"}Error{/ts}'{literal}, 'error'); | |
247 | } | |
248 | }, | |
249 | 'json').error(serverError); | |
250 | } | |
251 | ||
252 | function exportRecords(records) { | |
94ef27b7 | 253 | var query = {'batch_id': records, 'export_format': $('select.export-format').val()}; |
6a488035 | 254 | var exportUrl = CRM.url('civicrm/financial/batch/export', 'reset=1'); |
94ef27b7 CW |
255 | // jQuery redirect expects all query args as an object, so extract them from crm url |
256 | var urlParts = exportUrl.split('?'); | |
257 | $.each(urlParts[1].split('&'), function(key, val) { | |
258 | var q = val.split('='); | |
259 | query[q[0]] = q[1]; | |
260 | }); | |
261 | $().redirect(urlParts[0], query, 'GET'); | |
262 | setTimeout(function() {batchSelector.fnDraw();}, 4000); | |
6a488035 TO |
263 | } |
264 | ||
265 | function validateOp(records, op) { | |
266 | switch (op) { | |
267 | case 'reopen': | |
268 | var notAllowed = [1, 5]; | |
269 | break; | |
270 | case 'close': | |
271 | var notAllowed = [2, 5]; | |
272 | break; | |
273 | case 'export': | |
274 | var notAllowed = [5]; | |
275 | break; | |
276 | default: | |
277 | return records; | |
278 | } | |
279 | var len = records.length; | |
280 | var invalid = {}; | |
281 | var i = 0; | |
282 | while (i < len) { | |
283 | var status = $('tr[data-id='+records[i]+']').data('status_id'); | |
284 | if ($.inArray(status, notAllowed) >= 0) { | |
285 | $('#check_' + records[i] + ':checked').prop('checked', false).change(); | |
286 | invalid[status] = invalid[status] || []; | |
287 | invalid[status].push(records[i]); | |
288 | records.splice(i, 1); | |
289 | --len; | |
290 | } | |
291 | else { | |
292 | i++; | |
293 | } | |
294 | } | |
295 | for (status in invalid) { | |
296 | i = invalid[status]; | |
297 | var msg = (i.length == 1 ? {/literal}'{ts escape="js"}This record already has the status{/ts}' : '{ts escape="js"}The following records already have the status{/ts}'{literal}) + ' ' + $('tr[data-id='+i[0]+'] .crm-batch-status').text() + ':' + listRecords(i); | |
298 | CRM.alert(msg, {/literal}'{ts escape="js"}Cannot{/ts} '{literal} + $("#batch_update option[value=" + op + "]").text()); | |
299 | } | |
300 | return records; | |
301 | } | |
302 | ||
303 | function serverError() { | |
304 | CRM.alert({/literal}'{ts escape="js"}No response from the server. Check your internet connection and try reloading the page.{/ts}', '{ts escape="js"}Network Error{/ts}'{literal}, 'error'); | |
305 | } | |
306 | ||
307 | $('#Go').click(function() { | |
308 | var op = $("#batch_update").val(); | |
309 | if (op == "") { | |
310 | CRM.alert({/literal}'{ts escape="js"}Please select an action from the menu.{/ts}', '{ts escape="js"}No Action Selected{/ts}'{literal}); | |
311 | } | |
312 | else if (!$("input.select-row:checked").length) { | |
313 | CRM.alert({/literal}'{ts escape="js"}Please select one or more batches for this action.{/ts}', '{ts escape="js"}No Batches Selected{/ts}'{literal}); | |
314 | } | |
315 | else { | |
316 | records = []; | |
317 | $("input.select-row:checked").each(function() { | |
318 | records.push($(this).attr('id').replace('check_', '')); | |
319 | }); | |
320 | editRecords(records, op); | |
321 | } | |
322 | return false; | |
323 | }); | |
324 | ||
325 | $('#crm-container').on('click', 'a.action-item[href="#"]', function(event) { | |
326 | event.stopImmediatePropagation(); | |
327 | editRecords([$(this).closest('tr').attr('data-id')], $(this).attr('rel')); | |
328 | return false; | |
329 | }); | |
330 | ||
331 | }); | |
332 | ||
333 | </script> | |
334 | {/literal} |