Bug 23354: Prevent negatives from being entered
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / pos / pay.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE Koha %]
4 [% USE AuthorisedValues %]
5 [% USE Price %]
6 [% SET footerjs = 1 %]
7 [% INCLUDE 'doc-head-open.inc' %]
8 <title>Koha &rsaquo; Payments</title>
9 [% INCLUDE 'doc-head-close.inc' %]
10 </head>
11
12 <body id="payments" class="pos">
13 [% INCLUDE 'header.inc' %]
14 [% INCLUDE 'circ-search.inc' %]
15
16 <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; Point of sale</div>
17
18 <div class="main container-fluid">
19     <div class="row">
20         <div class="col-sm-10 col-sm-push-2">
21
22         [% IF ( error_registers ) %]
23         <div id="error_message" class="dialog alert">
24             You must have at least one cash register associated with this branch before you can record payments.
25         </div>
26         [% ELSE %]
27         <form name="payForm" id="payForm" method="post" action="/cgi-bin/koha/pos/pay.pl">
28             <div class="row">
29
30                 <div class="col-sm-6">
31                     <fieldset class="rows">
32                         <legend>Items for purchase</legend>
33                             Please select items from below to add to this transaction:
34                             [% IF invoice_types %]
35                             <table id="invoices">
36                             <thead>
37                                 <tr>
38                                     <th>Code</th>
39                                     <th>Description</th>
40                                     <th>Cost</th>
41                                     <th>Action</th>
42                                 </tr>
43                             </thead>
44                             <tbody>
45                             [% FOREACH invoice IN invoice_types %]
46                                 <tr>
47                                     <td>[% invoice.code | html %]</td>
48                                     <td>[% invoice.description | html %]</td>
49                                     <td>[% invoice.default_amount | $Price %]</td>
50                                     <td>
51                                         <button class="add_button" data-invoice-code="[% invoice.code %]" data-invoice-title="[% invoice.description | html %]" data-invoice-price="[% invoice.default_amount | html %]"><i class="fa fa-plus"></i> Add</button>
52                                     </td>
53                                 </tr>
54                             [% END %]
55                             </table>
56                             [% ELSE %]
57                             You have no manual invoice types defined
58                             [% END %]
59                     </fieldset>
60                 </div>
61
62                 <div class="col-sm-6">
63
64                     <fieldset class="rows">
65                         <legend>This sale</legend>
66                         <p>Click to edit item cost or quantities</p>
67                         <table id="sale" class="table_sale">
68                             <thead>
69                                 <tr>
70                                     <th>Item</th>
71                                     <th>Cost</th>
72                                     <th>Quantity</th>
73                                     <th>Total</th>
74                                     <th>Action</th>
75                                     <th>CODE</th>
76                                 </tr>
77                             </thead>
78                             <tbody>
79                             </tbody>
80                             <tfoot>
81                                 <tr>
82                                     <td colspan="3">Total payable:</td>
83                                     <td></td>
84                                     <td></td>
85                                     <td></td>
86                                 </tr>
87                             </tfoot>
88                         </table>
89                     </fieldset>
90
91                     <fieldset class="rows">
92                         <legend>Collect payment</legend>
93                         <ol>
94                             <li>
95                                 <label for="paid">Amount being paid: </label>
96                                 <input type="number" min="0.00" max="10000.00" step="0.01" name="paid" id="paid" value="[% amountoutstanding | $Price on_editing => 1 %]" readonly/>
97                             </li>
98                             <li>
99                                 <label for="collected">Collected from patron: </label>
100                                 <input type="number" min="0.00" max="10000.00" step="0.01" name="collected" id="collected" value=""/>
101                             </li>
102                             <li>
103                                 <label>Change to give: </label>
104                                 <span id="change">0.00</span>
105                                 <input type="hidden" name="change" value="0.00"/>
106                             </li>
107
108                             [% SET payment_types = AuthorisedValues.GetAuthValueDropbox('PAYMENT_TYPE') %]
109                             [% IF payment_types %]
110                             <li>
111                                 <label for="payment_type">Payment type: </label>
112                                 <select name="payment_type" id="payment_type">
113                                     [% FOREACH pt IN payment_types %]
114                                         <option value="[% pt.authorised_value | html %]">[% pt.lib | html %]</option>
115                                     [% END %]
116                                 </select>
117                             </li>
118                             [% END %]
119
120                             [% IF Koha.Preference('UseCashRegisters') %]
121                             <li>
122                                 <label for="cash_register">Cash register: </label>
123                                 <select name="cash_register" id="cash_register">
124                                     [% FOREACH register IN registers %]
125                                       [% IF register.id == registerid %]
126                                     <option value="[% register.id %]" selected="selected">[% register.name | html %]</option>
127                                       [% ELSE %]
128                                     <option value="[% register.id %]">[% register.name | html %]</option>
129                                       [% END %]
130                                     [% END %]
131                                 </select>
132                             </li>
133                             [% END %]
134                         </ol>
135
136                     </fieldset>
137                 </div>
138
139                 <div class="action">
140                     <input type="submit" name="submitbutton" value="Confirm" />
141                     <a class="cancel" href="/cgi-bin/koha/pos/pay.pl">Cancel</a>
142                 </div>
143             </div>
144         </form>
145         [% END %]
146     </div>
147
148     <div class="col-sm-2 col-sm-pull-10">
149         <aside>
150             [% INCLUDE 'pos-menu.inc' %]
151         </aside>
152     </div>
153 </div> <!-- /.row -->
154
155 <!-- Modal -->
156 <div id="confirm_change_form" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
157     <div class="modal-dialog">
158         <div class="modal-content">
159             <div class="modal-header">
160                 <h3>The amount collected is more than the outstanding charge</h3>
161             </div>
162             <div class="modal-body">
163                 <p>The amount collected from the patron is higher than the amount to be paid.</p>
164                 <p>The change to give is <b><span id="modal_change">0.00</span></b>.</p>
165                 <p>Confirm this payment?</p>
166             </div>
167             <div class="modal-footer">
168                 <button class="btn btn-default approve" id="modal_submit" type="button"><i class="fa fa-check"></i> Yes</button>
169                 <button class="btn btn-default deny cancel" href="#" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times"></i> No</button>
170             </div>
171         </div>
172     </div>
173 </div>
174
175 [% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
176 <!-- Automatic Print Reciept -->
177       <a id="printReciept" style="display: none" href="#"></a>
178 [% END %]
179
180 [% MACRO jsinclude BLOCK %]
181     [% Asset.js("js/admin-menu.js") | $raw %]
182     [% INCLUDE 'format_price.inc' %]
183     [% INCLUDE 'datatables.inc' %]
184     [% Asset.js("lib/jquery/plugins/jquery.jeditable.mini.js") | $raw %]
185     <script>
186     function moneyFormat(textObj) {
187         var newValue = textObj.value;
188         var decAmount = "";
189         var dolAmount = "";
190         var decFlag   = false;
191         var aChar     = "";
192
193         for(var i=0; i < newValue.length; i++) {
194             aChar = newValue.substring(i, i+1);
195             if (aChar >= "0" && aChar <= "9") {
196                 if(decFlag) {
197                     decAmount = "" + decAmount + aChar;
198                 }
199                 else {
200                     dolAmount = "" + dolAmount + aChar;
201                 }
202             }
203             if (aChar == ".") {
204                 if (decFlag) {
205                     dolAmount = "";
206                     break;
207                 }
208                 decFlag = true;
209             }
210         }
211
212         if (dolAmount == "") {
213             dolAmount = "0";
214         }
215     // Strip leading 0s
216         if (dolAmount.length > 1) {
217             while(dolAmount.length > 1 && dolAmount.substring(0,1) == "0") {
218                 dolAmount = dolAmount.substring(1,dolAmount.length);
219             }
220         }
221         if (decAmount.length > 2) {
222             decAmount = decAmount.substring(0,2);
223         }
224     // Pad right side
225         if (decAmount.length == 1) {
226            decAmount = decAmount + "0";
227         }
228         if (decAmount.length == 0) {
229            decAmount = decAmount + "00";
230         }
231
232         textObj.value = dolAmount + "." + decAmount;
233     }
234
235     function fnClickAddRow( table, invoiceCode, invoiceTitle, invoicePrice ) {
236       var defaultPrice = { value: invoicePrice };
237       moneyFormat(defaultPrice);
238       table.fnAddData( [
239         invoiceTitle,
240         defaultPrice.value,
241         1,
242         null,
243         '<button class="drop"><i class="fa fa-trash"></i> Remove</button>',
244         invoiceCode
245         ]
246       );
247     }
248
249     function updateChangeValues() {
250         var change = $('#change')[0];
251         change.innerHTML = Math.round(($('#collected')[0].value - $('#paid')[0].value) * 100) / 100;
252         if (change.innerHTML <= 0) {
253             change.innerHTML = "0.00";
254         } else {
255             change.value = change.innerHTML;
256             moneyFormat(change);
257             change.innerHTML = change.value;
258         }
259
260         $(':input[name="change"]').val(change.value);
261         $('#modal_change').html(change.innerHTML);
262     }
263
264     $(document).ready(function() {
265         var sale_table = $("#sale").dataTable($.extend(true, {}, dataTablesDefaults, {
266             "bPaginate": false,
267             "bFilter": false,
268             "bInfo": false,
269             "bAutoWidth": false,
270             "aoColumnDefs": [{
271                 "aTargets": [-3],
272                 "bSortable": false,
273                 "bSearchable": false,
274             }, {
275                 "aTargets": [-3],
276                 "mRender": function ( data, type, full ) {
277                     var price = Number.parseFloat(data);
278                     return price.format_price();
279                 }
280             }, {
281                 "aTargets": [-5],
282                 "sClass" : "editable",
283             }, {
284                 "aTargets": [-4],
285                 "sClass" : "editable_int",
286             }, {
287                 "targets": [-1],
288                 "visible": false,
289                 "searchable": false
290             }],
291             "aaSorting": [
292                 [1, "asc"]
293             ],
294             "fnDrawCallback": function (oSettings) {
295                 var local = this;
296                 local.$('.editable').editable( function(value, settings) {
297                     var aPos = local.fnGetPosition( this );
298                     local.fnUpdate( value, aPos[0], aPos[1], true, false );
299                     return value;
300                 },{
301                     type    : 'number',
302                     step    : '0.01',
303                     min     : '0',
304                     onblur  : 'submit'
305                 });
306                 local.$('.editable_int').editable( function(value, settings) {
307                     var aPos = local.fnGetPosition( this );
308                     local.fnUpdate( value, aPos[0], aPos[1], true, false );
309                     return value;
310                 },{
311                     type    : 'number',
312                     step    : '1',
313                     min     : '0',
314                     onblur  : 'submit'
315                 });
316             },
317             "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
318                 var iTotal = aData[1] * aData[2];
319                 this.fnUpdate( iTotal.format_price(), nRow, 3, false, false );
320             },
321             "fnFooterCallback": function(nFoot, aData, iStart, iEnd, aiDisplay) {
322                 var iTotalPrice = 0;
323                 for ( var i=0 ; i<aData.length ; i++ )
324                             {
325                                     iTotalPrice += aData[i][3]*1;
326                             }
327
328                 iTotalPrice = Number.parseFloat(iTotalPrice).toFixed(2);
329                 nFoot.getElementsByTagName('td')[1].innerHTML = iTotalPrice;
330                 $('#paid').val(iTotalPrice);
331                 $('#paid').trigger('change');
332             }
333         }));
334
335         $("#sale").on("click", "button.drop", function(){
336                 sale_table.DataTable().row($(this).parents('tr')).remove().draw(false);
337         });
338
339         var items_table = $("#invoices").dataTable($.extend(true,{}, dataTablesDefaults, {
340                "aoColumnDefs": [
341                   { "aTargets": [ -1, -2 ], "bSortable": false, "bSearchable":false },
342                ],
343                "aaSorting": [[ 0, "asc" ]],
344                "paginationType": "full",
345         }));
346
347         $(".add_button").on("click", function(e) {
348             e.preventDefault();
349             fnClickAddRow(sale_table, $( this ).data('invoiceCode'), $( this ).data('invoiceTitle'), $( this ).data('invoicePrice') );
350             items_table.fnFilter( '' );
351         });
352
353         // Change calculation and modal
354         var change = $('#change')[0];
355         $("#paid, #collected").on("change",function() {
356             moneyFormat( this );
357             if (change != undefined) {
358                 updateChangeValues();
359             }
360         });
361
362         var checked = false;
363         $('#modal_submit').click(function() {
364             checked = true;
365             $('#payForm').submit();
366         });
367
368         $('#payForm').submit(function(e){
369             if (change != undefined && change.innerHTML > 0.00 && !checked) {
370                 e.preventDefault();
371                 $("#confirm_change_form").modal("show");
372             } else {
373                 var rows = sale_table.fnGetData();
374                 rows.forEach(function (row, index) {
375                     var sale = {
376                         code: row[5],
377                         price: row[1],
378                         quantity: row[2]
379                     };
380                     $('<input>').attr({
381                         type: 'hidden',
382                         name: 'sales',
383                         value: JSON.stringify(sale)
384                     }).appendTo('#payForm');
385                 });
386                 return true;
387             }
388         });
389
390         [% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
391             $("#printReciept").click(function() {
392                 var win = window.open('/cgi-bin/koha/pos/printreceipt.pl?action=print&accountlines_id=[% payment_id | uri %]&collected=[% collected | uri %]&change=[% change | uri %]', '_blank');
393                 win.focus();
394             });
395             $("#printReciept").click();
396         [% END %]
397     });
398     </script>
399 [% END %]
400
401 [% INCLUDE 'intranet-bottom.inc' %]