From: Bill Erickson Date: Mon, 2 Nov 2020 21:38:12 +0000 (-0500) Subject: LP1901930 Payments support X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=791cd89c5c89aea684187ad2321c162dcc1bb89c;p=working%2FEvergreen.git LP1901930 Payments support Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm index 0bdda664ae..348f4d85bc 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm @@ -16,6 +16,7 @@ use OpenILS::Application::SIP2::Item; use OpenILS::Application::SIP2::Patron; use OpenILS::Application::SIP2::Checkout; use OpenILS::Application::SIP2::Checkin; +use OpenILS::Application::SIP2::Payment; my $U = 'OpenILS::Application::AppUtils'; my $SC = 'OpenILS::Application::SIP2::Common'; @@ -70,6 +71,7 @@ sub dispatch_sip2_request { '11' => \&handle_checkout, '17' => \&handle_item_info, '23' => \&handle_patron_status, + '37' => \&handle_payment, '63' => \&handle_patron_info, 'XS' => \&handle_end_session }; @@ -528,6 +530,49 @@ sub handle_checkin { }; } +sub handle_payment { + my ($session, $message) = @_; + my $config = $session->config; + + my $fee_type = $message->fixed_fields[1]; + my $pay_type = $message->fixed_fields[2]; + my $pay_amount = $SC->get_field_value($message, 'BV'); + my $patron_barcode = $SC->get_field_value($message, 'AA'); + my $fee_id = $SC->get_field_value($message, 'CG'); + my $terminal_xact = $SC->get_field_value($message, 'BK'); + + # Envisionware extensions for relaying information about + # payments made via credit card kiosk or cash register. + my $register_login = $SC->get_field_value($message, 'OR'); + my $check_number = $SC->get_field_value($message, 'RN'); + + my $details = OpenILS::Application::SIP2::Payment->apply_payment( + $session, + fee_id => $fee_id, + fee_type => $fee_type, + pay_type => $pay_type, + pay_amount => $pay_amount, + check_number => $check_number, + patron_barcode => $patron_barcode, + terminal_xact => $terminal_xact, + register_login => $register_login + ); + + my $screen_msg = $details->{screen_msg}; + + return { + code => '38', + fixed_fields => [ + $SC->sipbool($details->{ok}), + $SC->sipdate, + ], + fields => [ + {AA => $patron_barcode}, + {AO => $config->{institution}}, + $screen_msg ? {AF => $screen_msg} : (), + ] + } +} 1; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Payment.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Payment.pm new file mode 100644 index 0000000000..062be095f4 --- /dev/null +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Payment.pm @@ -0,0 +1,181 @@ +package OpenILS::Application::SIP2::Payment; +use strict; use warnings; +use DateTime; +use DateTime::Format::ISO8601; +use OpenSRF::System; +use OpenILS::Utils::CStoreEditor q/:funcs/; +use OpenSRF::Utils::Logger q/$logger/; +use OpenILS::Application::AppUtils; +use OpenILS::Utils::DateTime qw/:datetime/; +use OpenILS::Const qw/:const/; +use OpenILS::Application::SIP2::Common; +use OpenILS::Application::SIP2::Session; +my $U = 'OpenILS::Application::AppUtils'; +my $SC = 'OpenILS::Application::SIP2::Common'; + + +sub apply_payment { + my ($class, $session, %params) = @_; + + my $details = {ok => 0}; + + my $card = $session->editor->search_actor_card([ + {barcode => $params{patron_barcode}}, + {flesh => 1, flesh_fields => {ac => [qw/usr/]}} + ])->[0]; + + return $details unless $card; + my $user = $card->usr; + + if ($params{fee_id}) { + pay_one_transaction($session, $details, $user, %params); + + } else { + # No transaction was specified, pay whatever we can. + pay_multi_transactions($session, $details, $user, %params); + } + + return $details; +} + +sub pay_one_transaction { + my ($session, $details, $user, %params) = @_; + + my $fee_id = $params{fee_id}; # action.billable_xact.id + + my $xact = $session->editor->retrieve_money_billable_xact_summary($fee_id); + + return unless $xact && $xact->usr == $user->id; + + my $pay_amount = $params{pay_amount}; + + return unless $pay_amount > 0; + + if ($pay_amount > $xact->balance_owed) { + # TODO strings + $details->{screen_msg} = 'Overpayment not allowed'; + return; + } + + my $payments = [[$xact->id, $pay_amount]]; + + send_payments($session, $details, $user, $payments, %params); +} + +sub pay_multi_transactions { + my ($session, $details, $user, %params) = @_; + my $payments = []; + + # See if we can find some find some transactions to pay. + my $xacts = $U->simplereq('open-ils.actor', + 'open-ils.actor.user.transactions.history.have_balance', + $session->editor->authtoken, $user->id); + + if (!$xacts || !@$xacts) { # nothing to pay + # TODO: i18n + $details->{screen_msg} = 'Bill not found'; + return; + } + + my $pay_amount = $params{pay_amount}; + my $amount_paid = $pay_amount; + + for my $xact (@$xacts) { + next if $xact->balance_owed <= 0; + + my $payment; + my $xact_id = $xact->id; + my $balance_owed = $xact->balance_owed; + + if ($balance_owed >= $amount_paid) { + + # We owe as much as or more than we have money left, + # so pay what we have left. + $payment = $amount_paid; + $amount_paid = 0; + + } else { + + # This bill is for less than the amount we have + # left, so pay the full bill amount. + $payment = $balance_owed; + $amount_paid = $U->fpdiff($amount_paid, $balance_owed); + } + + push(@$payments, [$xact->id, $payment]); + + $amount_paid = sprintf("%.2f", $amount_paid); + $balance_owed = sprintf("%.2f", $balance_owed); + + $logger->info("SIP paid $payment on $xact_id with a ". + "balance of $balance_owed and $amount_paid remaining"); + + # Leave if we ran out of money. + last if $amount_paid == 0; + } + + if ($amount_paid == 0) { + # TODO strings + $details->{screen_msg} = 'Overpayment not allowed'; + return; + } + + send_payments($session, $details, $user, $payments, %params); +} + +# Takes array ref of array ref of [xact_id, payment_amount] to pay in batch. +sub send_payments { + my ($session, $details, $user, $payments, %params); + + my $pay_type = $params{pay_type}; + my $register_login = $params{register_login}; + + if ($register_login) { + $logger->debug("SIP register login sent as '$register_login'"); + + if ($register_login =~ /\\.+/) { # Windows domain login DOMAIN\user + my @parts = split(/\\/, $register_login); + $register_login = $parts[1]; + } + } + + my $args = { + userid => $user->id, + note => $register_login ? + "Via SIP2: Register login '$register_login'" : "Via SIP2", + payments => $payments, + payment_type => 'cash_payment' + }; + + if ($pay_type eq '01' || $pay_type eq '02') { + # '01' is "VISA" + # '02' is "credit card" + + $args->{payment_type} = 'credit_card_payment'; + $args->{cc_args} = { + approval_code => + $params{terminal_xact} || 'Not provided by SIP client' + }; + + } elsif ($pay_type eq '05') { + + $args->{payment_type} = 'check_payment'; + $args->{check_number} = + $params{check_number} || 'Not Provided by SIP Client'; + } + + my $resp = $U->simplereq( + 'open-ils.circ', 'open-ils.circ.money.payment', + $session->editor->authtoken, $args, $user->last_xact_id); + + if ($U->event_code($resp)) { + $details->{screen_msg} = $resp->{descr} || $resp->{textcode}; + } else { + $details->{ok} = 1; + } +} + + + + +