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::DebitTypes; 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, staff_id => $staff_id } ); $sale->add_item($item); $sale->purchase( { payment_type => 'CASH' } ); =head2 Class methods =head3 new Koha::Charges::Sale->new( { cash_register => $cash_register, staff_id => $staff_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}; Koha::Exceptions::MissingParameter->throw( "Missing mandatory parameter: staff_id") unless $params->{staff_id}; Carp::confess("Key 'cash_register' is not a Koha::Cash::Register object!") unless $params->{cash_register}->isa('Koha::Cash::Register'); return bless( $params, $class ); } =head3 payment_type my $payment_type = $sale->payment_type( $payment_type ); A getter/setter for this instances associated payment type. =cut sub payment_type { my ( $self, $payment_type ) = @_; if ($payment_type) { Koha::Exceptions::Account::UnrecognisedType->throw( error => 'Type of payment not recognised' ) unless ( exists( $self->_get_valid_payments->{$payment_type} ) ); $self->{payment_type} = $payment_type; } return $self->{payment_type}; } =head3 _get_valid_payments my $valid_payments = $sale->_get_valid_payments; A getter which returns a hashref whose keys represent valid payment types. =cut sub _get_valid_payments { my $self = shift; $self->{valid_payments} //= { map { $_ => 1 } Koha::AuthorisedValues->search_with_library_limits( { category => 'PAYMENT_TYPE' }, {}, $self->{cash_register}->branch # filter by cash_register branch )->get_column('authorised_value') }; return $self->{valid_payments}; } =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->_get_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 _get_valid_items my $valid_items = $sale->_get_valid_items; A getter which returns a hashref whose keys represent valid sale items. =cut sub _get_valid_items { my $self = shift; $self->{valid_items} //= { map { $_ => 1 } Koha::Account::DebitTypes->search_with_library_limits( {}, {}, $self->{cash_register}->branch )->get_column('code') }; return $self->{valid_items}; } =head3 purchase my $credit_line = $sale->purchase; =cut sub purchase { my ( $self, $params ) = @_; if ( $params->{payment_type} ) { Koha::Exceptions::Account::UnrecognisedType->throw( error => 'Type of payment not recognised' ) unless ( exists( $self->_get_valid_payments->{ $params->{payment_type} } ) ); $self->{payment_type} = $params->{payment_type}; } Koha::Exceptions::MissingParameter->throw( "Missing mandatory parameter: payment_type") unless $self->{payment_type}; Koha::Exceptions::NoChanges->throw( "Cannot purchase before calling add_item") unless $self->{items}; my $schema = Koha::Database->new->schema; my $dt = dt_from_string(); my $total_owed = 0; my $payment; $schema->txn_do( sub { # Add accountlines for each item being purchased my $debits; for my $item ( @{ $self->{items} } ) { my $amount = $item->{quantity} * $item->{price}; $total_owed = $total_owed + $amount; # Insert the account line my $debit = Koha::Account::Line->new( { amount => $amount, debit_type_code => $item->{code}, amountoutstanding => $amount, note => $item->{quantity}, manager_id => $self->{staff_id}, interface => 'intranet', branchcode => $self->{cash_register}->branch, date => $dt } )->store(); push @{$debits}, $debit; # Record the account offset my $account_offset = Koha::Account::Offset->new( { debit_id => $debit->id, type => 'CREATE', amount => $amount } )->store(); } # Add accountline for payment $payment = Koha::Account::Line->new( { amount => 0 - $total_owed, credit_type_code => 'PURCHASE', payment_type => $self->{payment_type}, amountoutstanding => 0 - $total_owed, manager_id => $self->{staff_id}, interface => 'intranet', branchcode => $self->{cash_register}->branch, register_id => $self->{cash_register}->id, date => $dt, note => "POS SALE" } )->store(); # Record the account offset my $payment_offset = Koha::Account::Offset->new( { credit_id => $payment->id, type => 'CREATE', amount => $payment->amount } )->store(); # Link payment to charges $payment->apply( { debits => $debits } ); $payment->discard_changes; } ); return $payment; } =head1 AUTHOR Martin Renvoize =cut 1;