From 13b2671d28162a5caafe288e2da586326cb02e66 Mon Sep 17 00:00:00 2001 From: Martin Renvoize Date: Tue, 23 Jul 2019 17:23:55 +0100 Subject: [PATCH] Bug 23354: Add a Point Of Sale 'pay' screen This patch adds a new Point Of Sale module to Koha's staff client front page. The module button leads directly to a 'Pay' page giving the staff user the ability to record anonymous payments for items that would not normally require a patron to be registered at the library. Test plan: 1) Enable `UseCashRegisters` via the system preferences. 2) Ensure your user has the 'manage_cash_registers' permission. 3) Add a cash register for your current branch. 4) Add at least one 'MANUAL_INV' authorized value. 5) Navigate to the new 'POS' pay page via the main menu. 6) Add an item to the 'sale' by clicking 'add' from the right side of the screen. 7) Note that said item was added to the table of items this sale on the left. 8) At this point you should be able to 'click to edit' the quantity or price of the item in the table on the left. 9) Enter an amount greater than the price of the item into the 'amount collected from patron' box. 10) Click 'Confirm' 11) Varify that the same change to give modal from the paycollect pages appears here. 12) Click 'Confirm' 13) Payment will have been recorded (check the database) and you will be back at a fresh 'Pay' page ready for the next transaction. 14) Signoff --- Koha/Charges/Sales.pm | 251 ++++++++++++++ .../prog/en/includes/pos-menu.inc | 18 + .../prog/en/modules/intranet-main.tt | 4 + .../intranet-tmpl/prog/en/modules/pos/pay.tt | 319 ++++++++++++++++++ pos/pay.pl | 80 +++++ 5 files changed, 672 insertions(+) create mode 100644 Koha/Charges/Sales.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/pos-menu.inc create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/pos/pay.tt create mode 100755 pos/pay.pl diff --git a/Koha/Charges/Sales.pm b/Koha/Charges/Sales.pm new file mode 100644 index 0000000000..fe6a8a6526 --- /dev/null +++ b/Koha/Charges/Sales.pm @@ -0,0 +1,251 @@ +package Koha::Charges::Sales; + +# 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 . + +use Modern::Perl; + +use Koha::Account::Lines; +use Koha::Account::Offsets; +use Koha::DateUtils qw( dt_from_string ); +use Koha::Exceptions; + +=head1 NAME + +Koha::Charges::Sale - Module for collecting sales in Koha + +=head1 SYNOPSIS + + use Koha::Charges::Sale; + + my $sale = Koha::Charges::Sale->new( cash_register => $register ); + $sale->add_item($item); + $sale->purchase; + +=head2 Class methods + +=head3 new + + Koha::Charges::Sale->new( + { + cash_register => $cash_register, + user_id => $user_id, + [ payment_type => $payment_type ], + [ items => $items ], + [ patron => $patron ], + } + ); + +=cut + +sub new { + my ( $class, $params ) = @_; + + Koha::Exceptions::MissingParameter->throw( + "Missing mandatory parameter: cash_register") + unless $params->{cash_register}; + Carp::confess("Key 'cash_register' is not a Koha::Cash::Register object!") + unless $params->{cash_register}->isa('Koha::Cash::Register'); + + $params->{valid_items} = { + map { $_ => 1 } Koha::AuthorisedValues->search( + { + category => 'MANUAL_INV', + branchcode => $params->{cash_register}->branch + } + )->get_column('authorised_value') + }; + + return bless( $params, $class ); +} + +=head3 cash_register + + my $cash_register = $sales->cash_register( $cash_register ); + +=cut + +sub cash_register { + my ( $self, $cash_register ) = @_; + + $self->{cash_register} = $cash_register + if $cash_register && $cash_register->isa('Koha::Cash::Register'); + + return $self->{cash_register}; +} + +=head3 payment_type + + my $payment_type = $sale->payment_type( $payment_type ); + +=cut + +sub payment_type { + my ( $self, $payment_type ) = @_; + + $self->{payment_type} = $payment_type; + + return $self; +} + +=head3 patron + + my $patron = $sale->patron( $patron ); + +=cut + +sub patron { + my ( $self, $patron ) = @_; + + $self->{patron} = $patron if $patron && $patron->isa('Koha::Patron'); + + return $self->{patron}; +} + +=head3 items + + my $items = $sale->items; + +=cut + +sub items { + my ( $self, $item ) = @_; + + $self->{item} = $item if $item && $item->isa('Koha::Item'); + + return $self->{item}; +} + +=head3 add_item + + my $item = { price => 0.25, quantity => 1, code => 'COPY' }; + $sale->add_item( $item ); + +=cut + +sub add_item { + my ( $self, $item ) = @_; + + Koha::Exceptions::MissingParameter->throw( + "Missing mandatory parameter: code") + unless $item->{code}; + + Koha::Exceptions::Account::UnrecognisedType->throw( + error => 'Type of debit not recognised' ) + unless ( exists( $self->{valid_items}->{ $item->{code} } ) ); + + Koha::Exceptions::MissingParameter->throw( + "Missing mandatory parameter: price") + unless $item->{price}; + + Koha::Exceptions::MissingParameter->throw( + "Missing mandatory parameter: quantity") + unless $item->{quantity}; + + push @{ $self->{items} }, $item; + return $self; +} + +=head3 purchase + + my $credit_line = $sale->purchase; + +=cut + +sub purchase { + my ( $self, $params ) = @_; + + my $payment_type = + exists( $params->{payment_type} ) + ? $params->{payment_type} + : $self->{payment_type}; + + Koha::Exceptions::MissingParameter->throw( + "Missing mandatory parameter: payment_type") + unless $payment_type; + + my $schema = Koha::Database->new->schema; + my $dt = dt_from_string(); + my $total_owed = 0; + my $credit; + + $schema->txn_do( + sub { + + my $debit_offsets; + for my $item ( @{ $self->{items} } ) { + + my $amount = $item->{quantity} * $item->{price}; + $total_owed = $total_owed + $amount; + + # Insert the account line + my $line = Koha::Account::Line->new( + { + amount => $amount, + accounttype => $item->{code}, + amountoutstanding => 0, + note => $item->{quantity}, + manager_id => $self->{user_id}, + interface => 'intranet', + branchcode => $self->{cash_register}->branch, + date => $dt + } + )->store(); + + # Record the account offset + my $account_offset = Koha::Account::Offset->new( + { + debit_id => $line->id, + type => 'Payment', + amount => $amount * -1 + } + )->store(); + + push @{$debit_offsets}, $account_offset; + } + + $credit = Koha::Account::Line->new( + { + amount => 0 - $total_owed, + accounttype => 'Pay', + payment_type => $payment_type, + amountoutstanding => 0, + manager_id => $self->{user_id}, + interface => 'intranet', + branchcode => $self->{cash_register}->branch, + register_id => $self->{cash_register}->id, + date => $dt, + note => "POS SALE" + } + )->store(); + + for my $offset (@{$debit_offsets}) { + $offset->credit_id( $credit->accountlines_id )->store(); + } + } + ); + + return $credit; +} + +=head1 AUTHOR + +Martin Renvoize + +=cut + +1; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/pos-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/pos-menu.inc new file mode 100644 index 0000000000..f948f15a14 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/pos-menu.inc @@ -0,0 +1,18 @@ + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt index ab04abbcd9..9257968a09 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt @@ -80,6 +80,10 @@