Browse Source

Bug 23354: Add receipting to Pay page

This patch adds receipt printing to the new Point of Sale pay page.

Test plan:
1) Apply patch and run database update
2) Enable automatic receipt printing via the `` system preference.
3) Make a payment for an item via the new POS pay page.
4) Note that a receipt printing dialogue is shown automatically after
   payment.
5) Note that a new notice is available under tools where you can alter
   the content of the receipt.
6) Signoff

Sponsored-by: PTFS Europe
Sponsored-by: Cheshire Libraries Shared Services
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Josef Moravec <josef.moravec@gmail.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
20.05.x
Martin Renvoize 3 years ago
parent
commit
dd9cfda29f
Signed by: martin.renvoize GPG Key ID: 422B469130441A0F
  1. 68
      installer/data/mysql/atomicupdate/bug_23354.perl
  2. 65
      installer/data/mysql/en/mandatory/sample_notices.sql
  3. 93
      koha-tmpl/intranet-tmpl/prog/en/modules/pos/pay.tt
  4. 26
      koha-tmpl/intranet-tmpl/prog/en/modules/pos/printreceipt.tt
  5. 8
      koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt
  6. 9
      pos/pay.pl
  7. 67
      pos/printreceipt.pl

68
installer/data/mysql/atomicupdate/bug_23354.perl

@ -5,6 +5,74 @@ if( CheckVersion( $DBversion ) ) {
INSERT IGNORE INTO account_offset_types ( type ) VALUES ( 'Purchase' );
});
$dbh->do(q{
INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`, `lang`) VALUES
('pos', 'RECEIPT', '', 'Point of sale receipt', 0, 'Receipt', '<table>
[% IF ( LibraryName ) %]
<tr>
<th colspan="2" class="centerednames">
<h3>[% LibraryName | html %]</h3>
</th>
</tr>
[% END %]
<tr>
<th colspan="2" class="centerednames">
<h2>[% Branches.GetName( payment.branchcode ) | html %]</h2>
</th>
</tr>
<tr>
<th colspan="2" class="centerednames">
<h3>[% payment.date | $KohaDates %]</h3>
</tr>
<tr>
<td>Transaction ID: </td>
<td>[% payment.accountlines_id %]</td>
</tr>
<tr>
<td>Operator ID: </td>
<td>[% payment.manager_id %]</td>
</tr>
<tr>
<td>Payment type: </td>
<td>[% payment.payment_type %]</td>
</tr>
<tr></tr>
<tr>
<th colspan="2" class="centerednames">
<h2><u>Fee receipt</u></h2>
</th>
</tr>
<tr></tr>
<tr>
<th>Description of charges</th>
<th>Amount</th>
</tr>
[% FOREACH offset IN offsets %]
<tr>
<td>[% offset.debit.accounttype %]</td>
<td>[% offset.amount * -1 | $Price %]</td>
</tr>
[% END %]
<tfoot>
<tr class="highlight">
<td>Total: </td>
<td>[% payment.amount * -1| $Price %]</td>
</tr>
<tr>
<td>Tendered: </td>
<td>[% collected | $Price %]</td>
</tr>
<tr>
<td>Change: </td>
<td>[% change | $Price %]</td>
</tr>
</tfoot>
</table>', 'print', 'default');
});
SetVersion( $DBversion );
print "Upgrade to $DBversion done (Bug 23354 - Add 'Purchase' account offset type)\n";
print "Upgrade to $DBversion done (Bug 23354 - Add 'RECEIPT' notice for Point of Sale)\n";
}

65
installer/data/mysql/en/mandatory/sample_notices.sql

@ -316,3 +316,68 @@ INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`,
INSERT INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`) VALUES
('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');
INSERT IGNORE INTO `letter` (`module`, `code`, `branchcode`, `name`, `is_html`, `title`, `content`, `message_transport_type`, `lang`) VALUES
('pos', 'RECEIPT', '', 'Point of sale receipt', 0, 'Receipt', '<table>
[% IF ( LibraryName ) %]
<tr>
<th colspan="2" class="centerednames">
<h3>[% LibraryName | html %]</h3>
</th>
</tr>
[% END %]
<tr>
<th colspan="2" class="centerednames">
<h2>[% Branches.GetName( payment.branchcode ) | html %]</h2>
</th>
</tr>
<tr>
<th colspan="2" class="centerednames">
<h3>[% payment.date | $KohaDates %]</h3>
</tr>
<tr>
<td>Transaction ID: </td>
<td>[% payment.accountlines_id %]</td>
</tr>
<tr>
<td>Operator ID: </td>
<td>[% payment.manager_id %]</td>
</tr>
<tr>
<td>Payment type: </td>
<td>[% payment.payment_type %]</td>
</tr>
<tr></tr>
<tr>
<th colspan="2" class="centerednames">
<h2><u>Fee receipt</u></h2>
</th>
</tr>
<tr></tr>
<tr>
<th>Description of charges</th>
<th>Amount</th>
</tr>
[% FOREACH offset IN offsets %]
<tr>
<td>[% offset.debit.accounttype %]</td>
<td>[% offset.amount * -1 | $Price %]</td>
</tr>
[% END %]
<tfoot>
<tr class="highlight">
<td>Total: </td>
<td>[% payment.amount * -1| $Price %]</td>
</tr>
<tr>
<td>Tendered: </td>
<td>[% collected | $Price %]</td>
</tr>
<tr>
<td>Change: </td>
<td>[% change | $Price %]</td>
</tr>
</tfoot>
</table>', 'print', 'default');

93
koha-tmpl/intranet-tmpl/prog/en/modules/pos/pay.tt

@ -57,15 +57,16 @@
<ol>
<li>
<label for="paid">Amount being paid: </label>
<input name="paid" id="paid" value="[% amountoutstanding | $Price on_editing => 1 %]"/>
<input type="number" min="0.00" max="10000.00" step="0.01" name="paid" id="paid" value="[% amountoutstanding | $Price on_editing => 1 %]" readonly/>
</li>
<li>
<label for="collected">Collected from patron: </label>
<input id="collected" value="[% amountoutstanding | $Price on_editing => 1 %]"/>
<input type="number" min="0.00" max="10000.00" step="0.01" name="collected" id="collected" value=""/>
</li>
<li>
<label>Change to give: </label>
<span id="change">0.00</span>
<input type="hidden" name="change" value="0.00"/>
</li>
[% SET payment_types = AuthorisedValues.GetAuthValueDropbox('PAYMENT_TYPE') %]
@ -145,9 +146,33 @@
[% INCLUDE 'pos-menu.inc' %]
</aside>
</div>
</div> <!-- /.row -->
<!-- Modal -->
<div id="confirm_change_form" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3>The amount collected is more than the outstanding charge</h3>
</div>
<div class="modal-body">
<p>The amount collected from the patron is higher than the amount to be paid.</p>
<p>The change to give is <b><span id="modal_change">0.00</span></b>.</p>
<p>Confirm this payment?</p>
</div>
<div class="modal-footer">
<button class="btn btn-default approve" id="modal_submit" type="button"><i class="fa fa-check"></i> Yes</button>
<button class="btn btn-default deny cancel" href="#" data-dismiss="modal" aria-hidden="true"><i class="fa fa-times"></i> No</button>
</div>
</div>
</div>
</div>
[% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
<!-- Automatic Print Reciept -->
<a id="printReciept" style="display: none" href="#"></a>
[% END %]
[% MACRO jsinclude BLOCK %]
[% Asset.js("js/admin-menu.js") | $raw %]
[% INCLUDE 'datatables.inc' %]
@ -170,7 +195,7 @@
var decFlag = false;
var aChar = "";
for(i=0; i < newValue.length; i++) {
for(var i=0; i < newValue.length; i++) {
aChar = newValue.substring(i, i+1);
if (aChar >= "0" && aChar <= "9") {
if(decFlag) {
@ -222,6 +247,8 @@
moneyFormat(change);
change.innerHTML = change.value;
}
$(':input[name="change"]').val(change.value);
$('#modal_change').html(change.innerHTML);
}
@ -256,7 +283,7 @@
return value;
},{
type : 'text'
})
});
},
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
var iTotal = aData[1] * aData[2];
@ -272,6 +299,7 @@
iTotalPrice = Number.parseFloat(iTotalPrice).toFixed(2);
nFoot.getElementsByTagName('td')[1].innerHTML = iTotalPrice;
$('#paid').val(iTotalPrice);
$('#paid').trigger('change');
}
}));
@ -283,12 +311,14 @@
"paginationType": "full",
}));
$(".add_button").on("click", function(ev) {
ev.preventDefault();
$(".add_button").on("click", function(e) {
e.preventDefault();
fnClickAddRow(sale_table, $( this ).data('invoiceTitle'), $( this ).data('invoicePrice') );
items_table.fnFilter( '' );
});
// Change calculation and modal
var change = $('#change')[0];
$("#paid, #collected").on("change",function() {
moneyFormat( this );
if (change != undefined) {
@ -296,22 +326,41 @@
}
});
$("#payForm").submit(function(e){
var rows = sale_table.fnGetData();
rows.forEach(function (row, index) {
var sale = {
code: row[0],
price: row[1],
quantity: row[2]
};
$('<input>').attr({
type: 'hidden',
name: 'sales',
value: JSON.stringify(sale)
}).appendTo('#payForm');
});
return true;
var checked = false;
$('#modal_submit').click(function() {
checked = true;
$('#payForm').submit();
});
$('#payForm').submit(function(e){
if (change != undefined && change.innerHTML > 0.00 && !checked) {
e.preventDefault();
$("#confirm_change_form").modal("show");
} else {
var rows = sale_table.fnGetData();
rows.forEach(function (row, index) {
var sale = {
code: row[0],
price: row[1],
quantity: row[2]
};
$('<input>').attr({
type: 'hidden',
name: 'sales',
value: JSON.stringify(sale)
}).appendTo('#payForm');
});
return true;
}
});
[% IF payment_id && Koha.Preference('FinePaymentAutoPopup') %]
$("#printReciept").click(function() {
var win = window.open('/cgi-bin/koha/pos/printreceipt.pl?action=print&accountlines_id=[% payment_id | uri %]&collected=[% collected | uri %]&change=[% change | uri %]', '_blank');
win.focus();
});
$("#printReciept").click();
[% END %]
});
</script>
[% END %]

26
koha-tmpl/intranet-tmpl/prog/en/modules/pos/printreceipt.tt

@ -0,0 +1,26 @@
[% USE raw %]
[% USE Asset %]
[% USE Koha %]
[% USE KohaDates %]
[% USE Branches %]
[% USE Price %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Print receipt</title>
[% INCLUDE 'doc-head-close.inc' %]
[% Asset.css("css/printreceiptinvoice.css") | $raw %]
[% INCLUDE 'blocking_errors.inc' %]
</head>
<body id="pat_printfeercpt" class="pat">
<div id="receipt">
[% letter.content | $raw | evaltt %]
</div>
[% MACRO jsinclude BLOCK %]
[% INCLUDE 'slip-print.inc' #printThenClose %]
[% END %]
[% INCLUDE 'intranet-bottom.inc' %]

8
koha-tmpl/intranet-tmpl/prog/en/modules/tools/letter.tt

@ -115,7 +115,7 @@
<li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=members">Patrons</a></li>
<li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=serial">Serials (new issue)</a></li>
<li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=suggestions">Suggestions</a></li>
<li><a href="/cgi-bin/koha/tools/letter.pl?op=add_form&amp;module=pos">Point of sale</a></li>
</ul>
</div>
</div> <!-- /#toolbar -->
@ -169,6 +169,7 @@
[% CASE 'members' %]<span>Patrons</span>
[% CASE 'serial' %]<span>Serials (new issue)</span>
[% CASE 'suggestions' %]<span>Suggestions</span>
[% CASE 'pos' %]<span>Point of sale</span>
[% CASE %]<span>[% lette.module | html %]</span>
[% END %]
</td>
@ -327,6 +328,11 @@
[% ELSE %]
<option value="suggestions">Suggestions</option>
[% END %]
[% IF ( module == "pos" ) %]
<option value="pos" selected="selected">Point of sale</option>
[% ELSE %]
<option value="pos">Point of sale</option>
[% END %]
</select>
</li>
<li>

9
pos/pay.pl

@ -55,7 +55,6 @@ else {
my $total_paid = $q->param('paid');
if ( $total_paid and $total_paid ne '0.00' ) {
warn "total_paid: $total_paid\n";
my $cash_register = Koha::Cash::Registers->find( { id => $registerid } );
my $payment_type = $q->param('payment_type');
my $sale = Koha::Charges::Sales->new(
@ -71,7 +70,13 @@ if ( $total_paid and $total_paid ne '0.00' ) {
$sale->add_item($item);
}
$sale->purchase( { payment_type => $payment_type } );
my $payment = $sale->purchase( { payment_type => $payment_type } );
$template->param(
payment_id => $payment->accountlines_id,
collected => scalar $q->param('collected'),
change => scalar $q->param('change')
);
}
output_html_with_http_headers( $q, $cookie, $template->output );

67
pos/printreceipt.pl

@ -0,0 +1,67 @@
#!/usr/bin/perl
# Copyright 2019 PTFS Europe
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use C4::Auth qw/:DEFAULT get_session/;
use C4::Output;
use CGI qw ( -utf8 );
use C4::Letters;
use Koha::Account::Lines;
use Koha::DateUtils;
my $input = CGI->new;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "pos/printreceipt.tt",
query => $input,
type => "intranet",
authnotrequired => 0,
}
);
my $action = $input->param('action') || '';
my $payment_id = $input->param('accountlines_id');
my $logged_in_user = Koha::Patrons->find($loggedinuser) or die "Not logged in";
output_and_exit_if_error(
$input, $cookie,
$template,
{
module => 'pos',
logged_in_user => $logged_in_user,
}
);
my $payment = Koha::Account::Lines->find($payment_id);
my @offsets = Koha::Account::Offsets->search( { credit_id => $payment_id } );
my $letter =
C4::Letters::getletter( 'pos', 'RECEIPT', C4::Context::mybranch, 'print' );
$template->param(
letter => $letter,
payment => $payment,
offsets => \@offsets,
collected => scalar $input->param('collected'),
change => scalar $input->param('change')
);
output_html_with_http_headers $input, $cookie, $template->output;
Loading…
Cancel
Save