View | Details | Raw Unified | Return to bug 23354
Collapse All | Expand All

(-)a/installer/data/mysql/atomicupdate/bug_23354.perl (+68 lines)
Lines 5-10 if( CheckVersion( $DBversion ) ) { Link Here
5
        INSERT IGNORE INTO account_offset_types ( type ) VALUES ( 'Purchase' );
5
        INSERT IGNORE INTO account_offset_types ( type ) VALUES ( 'Purchase' );
6
    });
6
    });
7
7
8
    $dbh->do(q{
9
INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`, `lang`) VALUES
10
('pos', 'RECEIPT', '', 'Point of sale receipt', 0, 'Receipt', '<table>
11
[% IF ( LibraryName ) %]
12
 <tr>
13
    <th colspan="2" class="centerednames">
14
        <h3>[% LibraryName | html %]</h3>
15
    </th>
16
 </tr>
17
[% END %]
18
 <tr>
19
    <th colspan="2" class="centerednames">
20
        <h2>[% Branches.GetName( payment.branchcode ) | html %]</h2>
21
    </th>
22
 </tr>
23
<tr>
24
    <th colspan="2" class="centerednames">
25
        <h3>[% payment.date | $KohaDates %]</h3>
26
</tr>
27
<tr>
28
  <td>Transaction ID: </td>
29
  <td>[% payment.accountlines_id %]</td>
30
</tr>
31
<tr>
32
  <td>Operator ID: </td>
33
  <td>[% payment.manager_id %]</td>
34
</tr>
35
<tr>
36
  <td>Payment type: </td>
37
  <td>[% payment.payment_type %]</td>
38
</tr>
39
 <tr></tr>
40
 <tr>
41
    <th colspan="2" class="centerednames">
42
        <h2><u>Fee receipt</u></h2>
43
    </th>
44
 </tr>
45
 <tr></tr>
46
 <tr>
47
    <th>Description of charges</th>
48
    <th>Amount</th>
49
  </tr>
50
51
  [% FOREACH offset IN offsets %]
52
    <tr>
53
        <td>[% offset.debit.accounttype %]</td>
54
        <td>[% offset.amount * -1 | $Price %]</td>
55
    </tr>
56
  [% END %]
57
58
<tfoot>
59
  <tr class="highlight">
60
    <td>Total: </td>
61
    <td>[% payment.amount * -1| $Price %]</td>
62
  </tr>
63
  <tr>
64
    <td>Tendered: </td>
65
    <td>[% collected | $Price %]</td>
66
  </tr>
67
  <tr>
68
    <td>Change: </td>
69
    <td>[% change | $Price %]</td>
70
    </tr>
71
</tfoot>
72
</table>', 'print', 'default');
73
    });
74
8
    SetVersion( $DBversion );
75
    SetVersion( $DBversion );
9
    print "Upgrade to $DBversion done (Bug 23354 - Add 'Purchase' account offset type)\n";
76
    print "Upgrade to $DBversion done (Bug 23354 - Add 'Purchase' account offset type)\n";
77
    print "Upgrade to $DBversion done (Bug 23354 - Add 'RECEIPT' notice for Point of Sale)\n";
10
}
78
}
(-)a/installer/data/mysql/en/mandatory/sample_notices.sql (+65 lines)
Lines 316-318 INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, Link Here
316
316
317
INSERT INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`) VALUES
317
INSERT INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`) VALUES
318
('circulation', 'SR_SLIP', '', 'Stock rotation slip', 0, 'Stock rotation report', 'Stock rotation report for [% branch.name %]:\r\n\r\n[% IF branch.items.size %][% branch.items.size %] items to be processed for this branch.\r\n[% ELSE %]No items to be processed for this branch\r\n[% END %][% FOREACH item IN branch.items %][% IF item.reason != \'in-demand\' %]Title: [% item.title %]\r\nAuthor: [% item.author %]\r\nCallnumber: [% item.callnumber %]\r\nLocation: [% item.location %]\r\nBarcode: [% item.barcode %]\r\nOn loan?: [% item.onloan %]\r\nStatus: [% item.reason %]\r\nCurrent library: [% item.branch.branchname %] [% item.branch.branchcode %]\r\n\r\n[% END %][% END %]', 'email');
318
('circulation', 'SR_SLIP', '', 'Stock rotation slip', 0, 'Stock rotation report', 'Stock rotation report for [% branch.name %]:\r\n\r\n[% IF branch.items.size %][% branch.items.size %] items to be processed for this branch.\r\n[% ELSE %]No items to be processed for this branch\r\n[% END %][% FOREACH item IN branch.items %][% IF item.reason != \'in-demand\' %]Title: [% item.title %]\r\nAuthor: [% item.author %]\r\nCallnumber: [% item.callnumber %]\r\nLocation: [% item.location %]\r\nBarcode: [% item.barcode %]\r\nOn loan?: [% item.onloan %]\r\nStatus: [% item.reason %]\r\nCurrent library: [% item.branch.branchname %] [% item.branch.branchcode %]\r\n\r\n[% END %][% END %]', 'email');
319
320
INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`, `lang`) VALUES
321
('pos', 'RECEIPT', '', 'Point of sale receipt', 0, 'Receipt', '<table>
322
[% IF ( LibraryName ) %]
323
 <tr>
324
    <th colspan="2" class="centerednames">
325
        <h3>[% LibraryName | html %]</h3>
326
    </th>
327
 </tr>
328
[% END %]
329
 <tr>
330
    <th colspan="2" class="centerednames">
331
        <h2>[% Branches.GetName( payment.branchcode ) | html %]</h2>
332
    </th>
333
 </tr>
334
<tr>
335
    <th colspan="2" class="centerednames">
336
        <h3>[% payment.date | $KohaDates %]</h3>
337
</tr>
338
<tr>
339
  <td>Transaction ID: </td>
340
  <td>[% payment.accountlines_id %]</td>
341
</tr>
342
<tr>
343
  <td>Operator ID: </td>
344
  <td>[% payment.manager_id %]</td>
345
</tr>
346
<tr>
347
  <td>Payment type: </td>
348
  <td>[% payment.payment_type %]</td>
349
</tr>
350
 <tr></tr>
351
 <tr>
352
    <th colspan="2" class="centerednames">
353
        <h2><u>Fee receipt</u></h2>
354
    </th>
355
 </tr>
356
 <tr></tr>
357
 <tr>
358
    <th>Description of charges</th>
359
    <th>Amount</th>
360
  </tr>
361
362
  [% FOREACH offset IN offsets %]
363
    <tr>
364
        <td>[% offset.debit.accounttype %]</td>
365
        <td>[% offset.amount * -1 | $Price %]</td>
366
    </tr>
367
  [% END %]
368
369
<tfoot>
370
  <tr class="highlight">
371
    <td>Total: </td>
372
    <td>[% payment.amount * -1| $Price %]</td>
373
  </tr>
374
  <tr>
375
    <td>Tendered: </td>
376
    <td>[% collected | $Price %]</td>
377
  </tr>
378
  <tr>
379
    <td>Change: </td>
380
    <td>[% change | $Price %]</td>
381
    </tr>
382
</tfoot>
383
</table>', 'print', 'default');
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/pos/pay.tt (-22 / +71 lines)
Lines 57-71 Link Here
57
                        <ol>
57
                        <ol>
58
                            <li>
58
                            <li>
59
                                <label for="paid">Amount being paid: </label>
59
                                <label for="paid">Amount being paid: </label>
60
                                <input name="paid" id="paid" value="[% amountoutstanding | $Price on_editing => 1 %]"/>
60
                                <input type="number" min="0.00" max="10000.00" step="0.01" name="paid" id="paid" value="[% amountoutstanding | $Price on_editing => 1 %]" readonly/>
61
                            </li>
61
                            </li>
62
                            <li>
62
                            <li>
63
                                <label for="collected">Collected from patron: </label>
63
                                <label for="collected">Collected from patron: </label>
64
                                <input id="collected" value="[% amountoutstanding | $Price on_editing => 1 %]"/>
64
                                <input type="number" min="0.00" max="10000.00" step="0.01" name="collected" id="collected" value=""/>
65
                            </li>
65
                            </li>
66
                            <li>
66
                            <li>
67
                                <label>Change to give: </label>
67
                                <label>Change to give: </label>
68
                                <span id="change">0.00</span>
68
                                <span id="change">0.00</span>
69
                                <input type="hidden" name="change" value="0.00"/>
69
                            </li>
70
                            </li>
70
71
71
                            [% SET payment_types = AuthorisedValues.GetAuthValueDropbox('PAYMENT_TYPE') %]
72
                            [% SET payment_types = AuthorisedValues.GetAuthValueDropbox('PAYMENT_TYPE') %]
Lines 145-153 Link Here
145
            [% INCLUDE 'pos-menu.inc' %]
146
            [% INCLUDE 'pos-menu.inc' %]
146
        </aside>
147
        </aside>
147
    </div>
148
    </div>
148
149
</div> <!-- /.row -->
149
</div> <!-- /.row -->
150
150
151
<!-- Modal -->
152
<div id="confirm_change_form" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
153
    <div class="modal-dialog">
154
        <div class="modal-content">
155
            <div class="modal-header">
156
                <h3>The amount collected is more than the outstanding charge</h3>
157
            </div>
158
            <div class="modal-body">
159
                <p>The amount collected from the patron is higher than the amount to be paid.</p>
160
                <p>The change to give is <b><span id="modal_change">0.00</span></b>.</p>
161
                <p>Confirm this payment?</p>
162
            </div>
163
            <div class="modal-footer">
164
                <button class="btn btn-default approve" id="modal_submit" type="button"><i class="fa fa-check"></i> Yes</button>
165
                <button class="btn btn-default deny cancel" href="#" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times"></i> No</button>
166
            </div>
167
        </div>
168
    </div>
169
</div>
170
171
[% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
172
<!-- Automatic Print Reciept -->
173
      <a id="printReciept" style="display: none" href="#"></a>
174
[% END %]
175
151
[% MACRO jsinclude BLOCK %]
176
[% MACRO jsinclude BLOCK %]
152
    [% Asset.js("js/admin-menu.js") | $raw %]
177
    [% Asset.js("js/admin-menu.js") | $raw %]
153
    [% INCLUDE 'datatables.inc' %]
178
    [% INCLUDE 'datatables.inc' %]
Lines 170-176 Link Here
170
        var decFlag   = false;
195
        var decFlag   = false;
171
        var aChar     = "";
196
        var aChar     = "";
172
197
173
        for(i=0; i < newValue.length; i++) {
198
        for(var i=0; i < newValue.length; i++) {
174
            aChar = newValue.substring(i, i+1);
199
            aChar = newValue.substring(i, i+1);
175
            if (aChar >= "0" && aChar <= "9") {
200
            if (aChar >= "0" && aChar <= "9") {
176
                if(decFlag) {
201
                if(decFlag) {
Lines 222-227 Link Here
222
            moneyFormat(change);
247
            moneyFormat(change);
223
            change.innerHTML = change.value;
248
            change.innerHTML = change.value;
224
        }
249
        }
250
251
        $(':input[name="change"]').val(change.value);
225
        $('#modal_change').html(change.innerHTML);
252
        $('#modal_change').html(change.innerHTML);
226
    }
253
    }
227
254
Lines 256-262 Link Here
256
                    return value;
283
                    return value;
257
                },{
284
                },{
258
                    type    : 'text'
285
                    type    : 'text'
259
                })
286
                });
260
            },
287
            },
261
            "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
288
            "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
262
                var iTotal = aData[1] * aData[2];
289
                var iTotal = aData[1] * aData[2];
Lines 272-277 Link Here
272
                iTotalPrice = Number.parseFloat(iTotalPrice).toFixed(2);
299
                iTotalPrice = Number.parseFloat(iTotalPrice).toFixed(2);
273
                nFoot.getElementsByTagName('td')[1].innerHTML = iTotalPrice;
300
                nFoot.getElementsByTagName('td')[1].innerHTML = iTotalPrice;
274
                $('#paid').val(iTotalPrice);
301
                $('#paid').val(iTotalPrice);
302
                $('#paid').trigger('change');
275
            }
303
            }
276
        }));
304
        }));
277
305
Lines 283-294 Link Here
283
               "paginationType": "full",
311
               "paginationType": "full",
284
        }));
312
        }));
285
313
286
        $(".add_button").on("click", function(ev) {
314
        $(".add_button").on("click", function(e) {
287
            ev.preventDefault();
315
            e.preventDefault();
288
            fnClickAddRow(sale_table, $( this ).data('invoiceTitle'), $( this ).data('invoicePrice') );
316
            fnClickAddRow(sale_table, $( this ).data('invoiceTitle'), $( this ).data('invoicePrice') );
289
            items_table.fnFilter( '' );
317
            items_table.fnFilter( '' );
290
        });
318
        });
291
319
320
        // Change calculation and modal
321
        var change = $('#change')[0];
292
        $("#paid, #collected").on("change",function() {
322
        $("#paid, #collected").on("change",function() {
293
            moneyFormat( this );
323
            moneyFormat( this );
294
            if (change != undefined) {
324
            if (change != undefined) {
Lines 296-317 Link Here
296
            }
326
            }
297
        });
327
        });
298
328
299
        $("#payForm").submit(function(e){
329
        var checked = false;
300
            var rows = sale_table.fnGetData();
330
        $('#modal_submit').click(function() {
301
            rows.forEach(function (row, index) {
331
            checked = true;
302
                var sale = {
332
            $('#payForm').submit();
303
                    code: row[0],
304
                    price: row[1],
305
                    quantity: row[2]
306
                };
307
                $('<input>').attr({
308
                    type: 'hidden',
309
                    name: 'sales',
310
                    value: JSON.stringify(sale)
311
                }).appendTo('#payForm');
312
            });
313
            return true;
314
        });
333
        });
334
335
        $('#payForm').submit(function(e){
336
            if (change != undefined && change.innerHTML > 0.00 && !checked) {
337
                e.preventDefault();
338
                $("#confirm_change_form").modal("show");
339
            } else {
340
                var rows = sale_table.fnGetData();
341
                rows.forEach(function (row, index) {
342
                    var sale = {
343
                        code: row[0],
344
                        price: row[1],
345
                        quantity: row[2]
346
                    };
347
                    $('<input>').attr({
348
                        type: 'hidden',
349
                        name: 'sales',
350
                        value: JSON.stringify(sale)
351
                    }).appendTo('#payForm');
352
                });
353
                return true;
354
            }
355
        });
356
357
        [% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
358
            $("#printReciept").click(function() {
359
                var win = window.open('/cgi-bin/koha/pos/printreceipt.pl?action=print&accountlines_id=[% payment_id | uri %]&collected=[% collected | uri %]&change=[% change | uri %]', '_blank');
360
                win.focus();
361
            });
362
            $("#printReciept").click();
363
        [% END %]
315
    });
364
    });
316
    </script>
365
    </script>
317
[% END %]
366
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/pos/printreceipt.tt (+26 lines)
Line 0 Link Here
1
[% USE raw %]
2
[% USE Asset %]
3
[% USE Koha %]
4
[% USE KohaDates %]
5
[% USE Branches %]
6
[% USE Price %]
7
[% SET footerjs = 1 %]
8
9
[% INCLUDE 'doc-head-open.inc' %]
10
<title>Print receipt</title>
11
[% INCLUDE 'doc-head-close.inc' %]
12
[% Asset.css("css/printreceiptinvoice.css") | $raw %]
13
[% INCLUDE 'blocking_errors.inc' %]
14
</head>
15
16
<body id="pat_printfeercpt" class="pat">
17
18
<div id="receipt">
19
    [% letter.content | $raw | evaltt %]
20
</div>
21
22
[% MACRO jsinclude BLOCK %]
23
    [% INCLUDE 'slip-print.inc' #printThenClose %]
24
[% END %]
25
26
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt (-1 / +7 lines)
Lines 115-121 Link Here
115
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=members">Patrons</a></li>
115
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=members">Patrons</a></li>
116
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=serial">Serials (new issue)</a></li>
116
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=serial">Serials (new issue)</a></li>
117
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=suggestions">Suggestions</a></li>
117
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=suggestions">Suggestions</a></li>
118
118
                                <li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=pos">Point of sale</a></li>
119
                            </ul>
119
                            </ul>
120
                        </div>
120
                        </div>
121
                    </div> <!-- /#toolbar -->
121
                    </div> <!-- /#toolbar -->
Lines 169-174 Link Here
169
                                                [% CASE 'members' %]<span>Patrons</span>
169
                                                [% CASE 'members' %]<span>Patrons</span>
170
                                                [% CASE 'serial' %]<span>Serials (new issue)</span>
170
                                                [% CASE 'serial' %]<span>Serials (new issue)</span>
171
                                                [% CASE 'suggestions' %]<span>Suggestions</span>
171
                                                [% CASE 'suggestions' %]<span>Suggestions</span>
172
                                                [% CASE 'pos' %]<span>Point of sale</span>
172
                                                [% CASE %]<span>[% lette.module | html %]</span>
173
                                                [% CASE %]<span>[% lette.module | html %]</span>
173
                                            [% END %]
174
                                            [% END %]
174
                                        </td>
175
                                        </td>
Lines 327-332 Link Here
327
                                    [% ELSE %]
328
                                    [% ELSE %]
328
                                        <option value="suggestions">Suggestions</option>
329
                                        <option value="suggestions">Suggestions</option>
329
                                    [% END %]
330
                                    [% END %]
331
                                    [% IF ( module == "pos" ) %]
332
                                        <option value="pos" selected="selected">Point of sale</option>
333
                                    [% ELSE %]
334
                                        <option value="pos">Point of sale</option>
335
                                    [% END %]
330
                                </select>
336
                                </select>
331
                            </li>
337
                            </li>
332
                            <li>
338
                            <li>
(-)a/pos/pay.pl (-2 / +7 lines)
Lines 55-61 else { Link Here
55
55
56
my $total_paid = $q->param('paid');
56
my $total_paid = $q->param('paid');
57
if ( $total_paid and $total_paid ne '0.00' ) {
57
if ( $total_paid and $total_paid ne '0.00' ) {
58
    warn "total_paid: $total_paid\n";
59
    my $cash_register = Koha::Cash::Registers->find( { id => $registerid } );
58
    my $cash_register = Koha::Cash::Registers->find( { id => $registerid } );
60
    my $payment_type  = $q->param('payment_type');
59
    my $payment_type  = $q->param('payment_type');
61
    my $sale          = Koha::Charges::Sales->new(
60
    my $sale          = Koha::Charges::Sales->new(
Lines 71-77 if ( $total_paid and $total_paid ne '0.00' ) { Link Here
71
        $sale->add_item($item);
70
        $sale->add_item($item);
72
    }
71
    }
73
72
74
    $sale->purchase( { payment_type => $payment_type } );
73
    my $payment = $sale->purchase( { payment_type => $payment_type } );
74
75
    $template->param(
76
        payment_id => $payment->accountlines_id,
77
        collected  => scalar $q->param('collected'),
78
        change     => scalar $q->param('change')
79
    );
75
}
80
}
76
81
77
output_html_with_http_headers( $q, $cookie, $template->output );
82
output_html_with_http_headers( $q, $cookie, $template->output );
(-)a/pos/printreceipt.pl (-1 / +67 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2019 PTFS Europe
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use C4::Auth qw/:DEFAULT get_session/;
23
use C4::Output;
24
use CGI qw ( -utf8 );
25
use C4::Letters;
26
use Koha::Account::Lines;
27
use Koha::DateUtils;
28
29
my $input = CGI->new;
30
31
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
32
    {
33
        template_name   => "pos/printreceipt.tt",
34
        query           => $input,
35
        type            => "intranet",
36
        authnotrequired => 0,
37
    }
38
);
39
40
my $action = $input->param('action') || '';
41
my $payment_id = $input->param('accountlines_id');
42
43
my $logged_in_user = Koha::Patrons->find($loggedinuser) or die "Not logged in";
44
output_and_exit_if_error(
45
    $input, $cookie,
46
    $template,
47
    {
48
        module         => 'pos',
49
        logged_in_user => $logged_in_user,
50
    }
51
);
52
53
my $payment = Koha::Account::Lines->find($payment_id);
54
my @offsets = Koha::Account::Offsets->search( { credit_id => $payment_id } );
55
56
my $letter =
57
  C4::Letters::getletter( 'pos', 'RECEIPT', C4::Context::mybranch, 'print' );
58
59
$template->param(
60
    letter    => $letter,
61
    payment   => $payment,
62
    offsets   => \@offsets,
63
    collected => scalar $input->param('collected'),
64
    change    => scalar $input->param('change')
65
);
66
67
output_html_with_http_headers $input, $cookie, $template->output;

Return to bug 23354