Bug 34188: (QA follow-up) Fix different versions of system preference name: Force...
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / pos / pay.tt
1 [% USE raw %]
2 [% USE AdditionalContents %]
3 [% USE Asset %]
4 [% USE Branches %]
5 [% USE Koha %]
6 [% USE Price %]
7 [% USE TablesSettings %]
8 [% USE Registers %]
9 [% PROCESS 'i18n.inc' %]
10 [% SET footerjs = 1 %]
11 [% INCLUDE 'doc-head-open.inc' %]
12 [% SET registers = Registers.all( filters => { current_branch => 1 } ) %]
13 <title>[% FILTER collapse %]
14     [% t("Point of sale") | html %] &rsaquo;
15     [% t("Koha") | html %]
16 [% END %]</title>
17 [% INCLUDE 'doc-head-close.inc' %]
18 </head>
19
20 <body id="payments" class="pos">
21 [% WRAPPER 'header.inc' %]
22     [% INCLUDE 'circ-search.inc' %]
23 [% END %]
24
25 [% WRAPPER 'sub-header.inc' %]
26     [% WRAPPER breadcrumbs %]
27         [% WRAPPER breadcrumb_item bc_active= 1 %]
28             <span>Point of sale</span>
29         [% END %]
30     [% END #/ WRAPPER breadcrumbs %]
31 [% END #/ WRAPPER sub-header.inc %]
32
33 <div class="main container-fluid">
34     <div class="row">
35         <div class="col-md-10 col-md-push-2">
36
37             <h1>Point of sale</h1>
38
39         [% IF ( registers.size == 0 ) %]
40             <div id="error_message" class="dialog message">
41                 <p>
42                     You must have at least one cash register associated with the library before you can record payments.
43                 </p>
44                 [% IF ( CAN_user_parameters_manage_cash_registers ) %]
45                     <form action="/cgi-bin/koha/admin/cash_registers.pl" method="get">
46                         <input type="hidden" name="op" value="add_form" />
47                         <button class="new" type="submit"><i class="fa fa-plus"></i> Create a new cash register</button>
48                     </form>
49                 [% END %]
50             </div>
51         [% ELSE %]
52
53         [% IF payment_id && !Koha.Preference('FinePaymentAutoPopup') %]
54         <div class="dialog message audio-alert-action">
55             <p>Payment received</p>
56             <p>
57                 <a target="_blank" href="/cgi-bin/koha/pos/printreceipt.pl?action=print&accountlines_id=[% payment_id | uri %]&collected=[% collected | uri %]&change=[% change | uri %]" class="btn btn-default"><i class="fa fa-print"></i> Print receipt</a>
58                 <a href="#" data-toggle="modal" data-target="#emailReceiptModal" class="btn btn-default"><i class="fa-solid fa-envelope"></i> Email receipt</a>
59
60             </p>
61         </div>
62         [% END %]
63
64         <form name="payForm" id="payForm" method="post" action="/cgi-bin/koha/pos/pay.pl">
65             <div class="row">
66
67                 <div class="col-md-6">
68                     <fieldset class="rows">
69                         <legend>Items for purchase</legend>
70                             Please select items from below to add to this transaction:
71                             [% IF invoice_types %]
72                             <table id="invoices">
73                             <thead>
74                                 <tr>
75                                     <th>Code</th>
76                                     <th>Description</th>
77                                     <th class="NoSort">Cost</th>
78                                     <th class="NoSort">Action</th>
79                                 </tr>
80                             </thead>
81                             <tbody>
82                             [% FOREACH invoice IN invoice_types %]
83                                 <tr>
84                                     <td>[% invoice.code | html %]</td>
85                                     <td>[% invoice.description | html %]</td>
86                                     <td>[% invoice.default_amount | $Price %]</td>
87                                     <td>
88                                         <button type="button" class="btn btn-default btn-xs add_button" data-invoice-code="[% invoice.code | html %]" data-invoice-title="[% invoice.description | html %]" data-invoice-price="[% invoice.default_amount | html %]"><i class="fa fa-plus"></i> Add</button>
89                                     </td>
90                                 </tr>
91                             [% END %]
92                             </table>
93                             [% ELSE %]
94                             You have no manual invoice types defined
95                             [% END %]
96                     </fieldset>
97                 </div>
98
99                 <div class="col-md-6">
100
101                     <fieldset class="rows">
102                         <legend>This sale</legend>
103                         <p>Click to edit item cost or quantities</p>
104                         <table id="sale" class="table_sale">
105                             <thead>
106                                 <tr>
107                                     <th>Item</th>
108                                     <th>Cost</th>
109                                     <th>Quantity</th>
110                                     <th>Total</th>
111                                     <th>Action</th>
112                                     <th>CODE</th>
113                                 </tr>
114                             </thead>
115                             <tbody>
116                             </tbody>
117                             <tfoot>
118                                 <tr>
119                                     <td colspan="3">Total payable:</td>
120                                     <td></td>
121                                     <td></td>
122                                     <td></td>
123                                 </tr>
124                             </tfoot>
125                         </table>
126                     </fieldset>
127
128                     <fieldset class="rows">
129                         <legend>Collect payment</legend>
130                         <ol>
131                             <li>
132                                 <label for="paid">Amount being paid: </label>
133                                 <input type="text" inputmode="none" pattern="[0-9]*" name="paid" id="paid" value="" readonly/>
134                             </li>
135                             <li>
136                                 <label for="collected" class="required">Amount tendered: </label>
137                                 <input type="text" inputmode="numeric" pattern="[0-9]*" name="collected" id="collected" value="" class="required" required="required" />
138                                 <span class="required">Required</span>
139                             </li>
140                             <li>
141                                 <label>Change to give: </label>
142                                 <span id="change">[% 0 | $Price %]</span>
143                                 <input type="hidden" name="change" value="[% 0 | $Price %]"/>
144                             </li>
145
146                             [% INCLUDE 'transaction_types.inc' type="payment" %]
147
148                             <li>
149                                 <label for="registerid" class="required">Cash register: </label>
150                                 <select name="registerid" id="registerid" class="required" required="required">
151                                     <option id="noregister" disabled="disabled" value="">-- Select an option--</option>
152                                     [% PROCESS options_for_registers %]
153                                 </select>
154                                 <span class="required">Required</span>
155                             </li>
156                         </ol>
157
158                     </fieldset>
159
160                     <fieldset class="action">
161                         <input type="submit" id="submitbutton" name="submitbutton" class="btn btn-primary" value="Confirm" />
162                         <a class="cancel" href="/cgi-bin/koha/pos/pay.pl">Cancel</a>
163                     </fieldset>
164                 </div>
165             </div>
166         </form>
167         [% END %]
168
169         [%- SET StaffPOSHome = AdditionalContents.get( location => "StaffPOSHome", lang => lang, library => logged_in_user.branchcode ) -%]
170         [%- FOREACH block IN StaffPOSHome.content -%]
171         <div class="page-section">
172             [%- block.content | $raw -%]
173         </div>
174         [%- END -%]
175
176     </div>
177
178     <div class="col-md-2 col-md-pull-10">
179         <aside>
180             [% INCLUDE 'pos-menu.inc' %]
181         </aside>
182     </div>
183 </div> <!-- /.row -->
184
185 <!-- Email receipt modal -->
186 <div class="modal" id="emailReceiptModal" tabindex="-1" role="dialog" aria-labelledby="emailReceiptLabel">
187     <form id="email_form" action="/cgi-bin/koha/pos/pay.pl" method="get" enctype="multipart/form-data" class="validated">
188         <input type="hidden" name="payment_id" value="[% payment_id | uri %]">
189         <input type="hidden" name="collected" value="[% collected | uri %]">
190         <input type="hidden" name="change" value="[% change | uri %]">"
191         <div class="modal-dialog" role="document">
192             <div class="modal-content">
193                 <div class="modal-header">
194                     <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
195                     <h4 class="modal-title" id="emailReceiptLabel">Email receipt</h4>
196                 </div>
197                 <div class="modal-body">
198                     <fieldset class="rows">
199                         <ol>
200                             <li>
201                                 <label class="required" for="toaddr">Email address: </label>
202                                 <input type="email" id="toaddr" name="toaddr" required="required">
203                                 <span class="required">Required</span>
204                             </li>
205                         </ol>
206                     </fieldset> <!-- /.rows -->
207                 </div> <!-- /.modal-body -->
208                 <div class="modal-footer">
209                     <input type="hidden" name="action" value="send">
210                     <button type="submit" class="btn btn-default">Confirm</button>
211                     <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
212                 </div> <!-- /.modal-footer -->
213             </div> <!-- /.modal-content -->
214         </div> <!-- /.modal-dialog -->
215     </form> <!-- /#email_form -->
216 </div> <!-- /#emailReceiptModal -->
217
218 <!-- Change modal -->
219 <div id="confirm_change_form" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
220     <div class="modal-dialog">
221         <div class="modal-content">
222             <div class="modal-header">
223                 <h3>The amount collected is more than the outstanding charge</h3>
224             </div>
225             <div class="modal-body">
226                 <p>The amount collected from the patron is higher than the amount to be paid.</p>
227                 <p>The change to give is <strong><span id="modal_change">[% 0 | $Price %]</span></strong>.</p>
228                 <p>Confirm this payment?</p>
229             </div>
230             <div class="modal-footer">
231                 <button class="btn btn-default approve" id="modal_submit" type="button"><i class="fa fa-check"></i> Yes</button>
232                 <button class="btn btn-default deny cancel" data-dismiss="modal" aria-hidden="true" type="button"><i class="fa fa-times"></i> No</button>
233             </div>
234         </div>
235     </div>
236 </div>
237
238 [% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
239     <!-- Automatic Print Receipt -->
240     <a id="printReceipt" style="display: none" href="#"></a>
241 [% END %]
242
243 [% MACRO jsinclude BLOCK %]
244     [% INCLUDE 'format_price.inc' %]
245     [% INCLUDE 'datatables.inc' %]
246     [% INCLUDE 'columns_settings.inc' %]
247     [% Asset.js("lib/jquery/plugins/jquery.jeditable.mini.js") | $raw %]
248     <script>
249     function moneyFormat(textObj) {
250         var newValue = textObj.value;
251         var decAmount = "";
252         var dolAmount = "";
253         var dolFlag   = false;
254         var aChar     = "";
255
256         for(var i = newValue.length; 0 < i; i--) {
257             aChar = newValue.substring(i-1, i);
258             if ("0" <= aChar && aChar <= "9") {
259                 if(dolFlag) {
260                     dolAmount = "" + aChar + dolAmount;
261                 }
262                 else {
263                     decAmount = "" + aChar + decAmount;
264                 }
265             }
266             if (aChar == "." || aChar == ",") {
267                 dolFlag = true;
268             }
269         }
270
271         if (!dolFlag) {
272             dolAmount = decAmount;
273             decAmount = "";
274         }
275
276         if (dolAmount == "") {
277             dolAmount = "0";
278         }
279     // Strip leading 0s
280         if (dolAmount.length > 1) {
281             while(dolAmount.length > 1 && dolAmount.substring(0,1) == "0") {
282                 dolAmount = dolAmount.substring(1,dolAmount.length);
283             }
284         }
285         if (decAmount.length > 2) {
286             decAmount = decAmount.substring(0,2);
287         }
288     // Pad right side
289         if (decAmount.length == 1) {
290            decAmount = decAmount + "0";
291         }
292         if (decAmount.length == 0) {
293            decAmount = decAmount + "00";
294         }
295
296         textObj.value = dolAmount + "." + decAmount;
297     }
298
299     function fnClickAddRow( table, invoiceCode, invoiceTitle, invoicePrice ) {
300       var defaultPrice = { value: invoicePrice };
301       moneyFormat(defaultPrice);
302       table.fnAddData( [
303         invoiceTitle,
304         defaultPrice.value,
305         1,
306         null,
307         '<button class="btn btn-default btn-xs drop" type="button"><i class="fa fa-trash-can"></i> ' + _("Remove") + '</button>',
308         invoiceCode
309         ]
310       );
311     }
312
313     function updateChangeValues() {
314         var change = $('#change')[0];
315         var zero_formatted = "[% 0 | $Price %]";
316         change.innerHTML = Math.round(($('#collected')[0].value - $('#paid')[0].value) * 100) / 100;
317         if (change.innerHTML <= 0) {
318             var paid = $('#paid')[0];
319             moneyFormat(paid);
320             $('#collected').rules( "add", { min: Number(paid.value) });
321             change.innerHTML = zero_formatted;
322             $(':input[name="change"]').val(zero_formatted);
323         } else {
324             change.value = change.innerHTML;
325             moneyFormat(change);
326             change.innerHTML = change.value;
327             $(':input[name="change"]').val(change.value);
328         }
329
330         $('#modal_change').html(change.innerHTML);
331     }
332
333     $(document).ready(function() {
334         var sale_table = $("#sale").dataTable($.extend(true, {}, dataTablesDefaults, {
335             "bPaginate": false,
336             "bFilter": false,
337             "bInfo": false,
338             "aoColumnDefs": [{
339                 "aTargets": [-2],
340                 "bSortable": false,
341                 "bSearchable": false,
342             }, {
343                 "aTargets": [-3],
344                 "mRender": function ( data, type, full ) {
345                     var price = Number.parseFloat(data);
346                     return price.format_price();
347                 }
348             }, {
349                 "aTargets": [-5],
350                 "sClass" : "editable",
351             }, {
352                 "aTargets": [-4],
353                 "sClass" : "editable_int",
354             }, {
355                 "targets": [-1],
356                 "visible": false,
357                 "searchable": false
358             }],
359             "aaSorting": [],
360             "fnDrawCallback": function (oSettings) {
361                 var local = this;
362                 local.$('.editable').editable( function(value, settings) {
363                     var aPos = local.fnGetPosition( this );
364                     local.fnUpdate( value, aPos[0], aPos[1], true, false );
365                     return value;
366                 },{
367                     type    : 'text',
368                     pattern : "^\\d+(\.\\d{2})?$",
369                     onblur  : 'submit',
370                     width   : "8em",
371                     tooltip : _("Click to edit")
372                 });
373                 local.$('.editable_int').editable( function(value, settings) {
374                     var aPos = local.fnGetPosition( this );
375                     local.fnUpdate( value, aPos[0], aPos[1], true, false );
376                     return value;
377                 },{
378                     type    : 'text',
379                     pattern : "[0-9]*",
380                     onblur  : 'submit',
381                     width   : "4em",
382                     tooltip : _("Click to edit")
383                 });
384             },
385             "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
386                 var iTotal = aData[1] * aData[2];
387                 this.fnUpdate( iTotal, nRow, 3, false, false );
388             },
389             "fnFooterCallback": function(nFoot, aData, iStart, iEnd, aiDisplay) {
390                 var iTotalPrice = 0;
391                 for ( var i=0 ; i<aData.length ; i++ )
392                 {
393                     iTotalPrice += aData[i][3]*1;
394                 }
395                 iTotalPrice = iTotalPrice.format_price();
396                 nFoot.getElementsByTagName('td')[1].innerHTML = iTotalPrice;
397                 $('#paid').val(iTotalPrice);
398                 $('#paid').trigger('change');
399             },
400             "autoWidth": false
401         }));
402
403         $("#sale").on("click", "button.drop", function(){
404                 sale_table.DataTable().row($(this).parents('tr')).remove().draw(false);
405         });
406
407         var items_table_settings = [% TablesSettings.GetTableSettings('pos', 'pay', 'invoices', 'json') | $raw %];
408         var items_table = KohaTable("invoices", {
409                "sPaginationType": "full",
410                "aaSorting": [[ 0, "asc" ]],
411                "autoWidth": false
412         }, items_table_settings, false);
413
414         $("#invoices").on("click", ".add_button", function(e) {
415             e.preventDefault();
416             fnClickAddRow(sale_table, $( this ).data('invoiceCode'), $( this ).data('invoiceTitle'), $( this ).data('invoicePrice') );
417             if($('#invoices_filter').find('input[type=search]').val() !== ''){
418                 items_table.fnFilter( '' );
419             }
420         });
421
422         // Change calculation and modal
423         var change = $('#change')[0];
424         $("#paid, #collected").on("change",function() {
425             moneyFormat( this );
426             if (change != undefined) {
427                 updateChangeValues();
428             }
429         });
430
431         var checked = false;
432         $('#modal_submit').click(function() {
433             checked = true;
434             $('#payForm').submit();
435         });
436
437         $('#payForm').validate({
438             rules: {
439                 paid: {
440                     required: true
441                 },
442                 collected: {
443                     required: true
444                 },
445                 payment_type: {
446                     required: true
447                 },
448                 registerid: {
449                     required: true
450                 }
451             }
452         });
453
454         $('#payForm').submit(function(e){
455             // first, clear stale sales 'rows' from the payForm
456             if($('input[name="sales"]').length > 0) {
457                 $('input[name="sales"]').each(function() {
458                     $(this).remove();
459                 });
460             }
461
462             // now, process the current & fresh contents of the sale_table
463             if (change != undefined && change.innerHTML > 0.00 && !checked) {
464                 e.preventDefault();
465                 $("#confirm_change_form").modal("show");
466             } else {
467                 var rows = sale_table.fnGetData();
468                 rows.forEach(function (row, index) {
469                     var sale = {
470                         code: row[5],
471                         price: row[1],
472                         quantity: row[2]
473                     };
474                     $('<input>').attr({
475                         type: 'hidden',
476                         name: 'sales',
477                         value: JSON.stringify(sale)
478                     }).appendTo('#payForm');
479                 });
480                 return true;
481             }
482         });
483
484         [% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
485             $("#printReceipt").click(function() {
486                 var win = window.open('/cgi-bin/koha/pos/printreceipt.pl?action=print&accountlines_id=[% payment_id | uri %]&collected=[% collected | uri %]&change=[% change | uri %]', '_blank');
487                 win.focus();
488             });
489             $("#printReceipt").click();
490         [% END %]
491     });
492     </script>
493 [% END %]
494 [% INCLUDE 'intranet-bottom.inc' %]