Bug 23354: (follow-up) Update for bugs 23049 and 23805
[koha.git] / Koha / Charges / Sales.pm
blob71e3d9138d5dd48ad5f814f3b607724fe23ec537
1 package Koha::Charges::Sales;
3 # Copyright 2019 PTFS Europe
5 # This file is part of Koha.
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.
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.
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>.
20 use Modern::Perl;
22 use Koha::Account::Lines;
23 use Koha::Account::DebitTypes;
24 use Koha::Account::Offsets;
25 use Koha::DateUtils qw( dt_from_string );
26 use Koha::Exceptions;
28 =head1 NAME
30 Koha::Charges::Sale - Module for collecting sales in Koha
32 =head1 SYNOPSIS
34 use Koha::Charges::Sale;
36 my $sale =
37 Koha::Charges::Sale->new( { cash_register => $register, staff_id => $staff_id } );
38 $sale->add_item($item);
39 $sale->purchase( { payment_type => 'CASH' } );
41 =head2 Class methods
43 =head3 new
45 Koha::Charges::Sale->new(
47 cash_register => $cash_register,
48 staff_id => $staff_id,
49 [ payment_type => $payment_type ],
50 [ items => $items ],
51 [ patron => $patron ],
55 =cut
57 sub new {
58 my ( $class, $params ) = @_;
60 Koha::Exceptions::MissingParameter->throw(
61 "Missing mandatory parameter: cash_register")
62 unless $params->{cash_register};
64 Koha::Exceptions::MissingParameter->throw(
65 "Missing mandatory parameter: staff_id")
66 unless $params->{staff_id};
68 Carp::confess("Key 'cash_register' is not a Koha::Cash::Register object!")
69 unless $params->{cash_register}->isa('Koha::Cash::Register');
71 return bless( $params, $class );
74 =head3 payment_type
76 my $payment_type = $sale->payment_type( $payment_type );
78 A getter/setter for this instances associated payment type.
80 =cut
82 sub payment_type {
83 my ( $self, $payment_type ) = @_;
85 if ($payment_type) {
86 Koha::Exceptions::Account::UnrecognisedType->throw(
87 error => 'Type of payment not recognised' )
88 unless ( exists( $self->_get_valid_payments->{$payment_type} ) );
90 $self->{payment_type} = $payment_type;
93 return $self->{payment_type};
96 =head3 _get_valid_payments
98 my $valid_payments = $sale->_get_valid_payments;
100 A getter which returns a hashref whose keys represent valid payment types.
102 =cut
104 sub _get_valid_payments {
105 my $self = shift;
107 $self->{valid_payments} //= {
108 map { $_ => 1 } Koha::AuthorisedValues->search(
110 category => 'PAYMENT_TYPE',
111 branchcode => $self->{cash_register}->branch
113 )->get_column('authorised_value')
116 return $self->{valid_payments};
119 =head3 add_item
121 my $item = { price => 0.25, quantity => 1, code => 'COPY' };
122 $sale->add_item( $item );
124 =cut
126 sub add_item {
127 my ( $self, $item ) = @_;
129 Koha::Exceptions::MissingParameter->throw(
130 "Missing mandatory parameter: code")
131 unless $item->{code};
133 Koha::Exceptions::Account::UnrecognisedType->throw(
134 error => 'Type of debit not recognised' )
135 unless ( exists( $self->_get_valid_items->{ $item->{code} } ) );
137 Koha::Exceptions::MissingParameter->throw(
138 "Missing mandatory parameter: price")
139 unless $item->{price};
141 Koha::Exceptions::MissingParameter->throw(
142 "Missing mandatory parameter: quantity")
143 unless $item->{quantity};
145 push @{ $self->{items} }, $item;
146 return $self;
149 =head3 _get_valid_items
151 my $valid_items = $sale->_get_valid_items;
153 A getter which returns a hashref whose keys represent valid sale items.
155 =cut
157 sub _get_valid_items {
158 my $self = shift;
160 $self->{valid_items} //= {
161 map { $_ => 1 }
162 Koha::Account::DebitTypes->search_with_library_limits( {}, {},
163 $self->{cash_register}->branch )->get_column('code')
166 return $self->{valid_items};
169 =head3 purchase
171 my $credit_line = $sale->purchase;
173 =cut
175 sub purchase {
176 my ( $self, $params ) = @_;
178 if ( $params->{payment_type} ) {
179 Koha::Exceptions::Account::UnrecognisedType->throw(
180 error => 'Type of payment not recognised' )
181 unless (
182 exists( $self->_get_valid_payments->{ $params->{payment_type} } ) );
184 $self->{payment_type} = $params->{payment_type};
187 Koha::Exceptions::MissingParameter->throw(
188 "Missing mandatory parameter: payment_type")
189 unless $self->{payment_type};
191 Koha::Exceptions::NoChanges->throw(
192 "Cannot purchase before calling add_item")
193 unless $self->{items};
195 my $schema = Koha::Database->new->schema;
196 my $dt = dt_from_string();
197 my $total_owed = 0;
198 my $credit;
200 $schema->txn_do(
201 sub {
203 # Add accountlines for each item being purchased
204 my $debits;
205 for my $item ( @{ $self->{items} } ) {
207 my $amount = $item->{quantity} * $item->{price};
208 $total_owed = $total_owed + $amount;
210 # Insert the account line
211 my $debit = Koha::Account::Line->new(
213 amount => $amount,
214 debit_type_code => $item->{code},
215 amountoutstanding => 0,
216 note => $item->{quantity},
217 manager_id => $self->{staff_id},
218 interface => 'intranet',
219 branchcode => $self->{cash_register}->branch,
220 date => $dt
222 )->store();
223 push @{$debits}, $debit;
225 # Record the account offset
226 my $account_offset = Koha::Account::Offset->new(
228 debit_id => $debit->id,
229 type => 'Purchase',
230 amount => $amount
232 )->store();
235 # Add accountline for payment
236 $credit = Koha::Account::Line->new(
238 amount => 0 - $total_owed,
239 credit_type_code => 'PURCHASE',
240 payment_type => $self->{payment_type},
241 amountoutstanding => 0,
242 manager_id => $self->{staff_id},
243 interface => 'intranet',
244 branchcode => $self->{cash_register}->branch,
245 register_id => $self->{cash_register}->id,
246 date => $dt,
247 note => "POS SALE"
249 )->store();
251 # Record the account offset
252 my $credit_offset = Koha::Account::Offset->new(
254 credit_id => $credit->id,
255 type => 'Purchase',
256 amount => $credit->amount
258 )->store();
260 # Link payment to debits
261 for my $debit ( @{$debits} ) {
262 Koha::Account::Offset->new(
264 credit_id => $credit->accountlines_id,
265 debit_id => $debit->id,
266 amount => $debit->amount * -1,
267 type => 'Payment',
269 )->store();
274 return $credit;
277 =head1 AUTHOR
279 Martin Renvoize <martin.renvoize@ptfs-europe.com>
281 =cut