From: erickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Tue, 27 Oct 2009 14:44:20 +0000 (+0000) Subject: Patch from Lebbeous Fogle-Weekley to fine-tune credit card payment support in the... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=95e351e1d73134542edd87bc3b5c37e8059548aa;p=evergreen%2Fmasslnc.git Patch from Lebbeous Fogle-Weekley to fine-tune credit card payment support in the the staff client. This adds support for differentiating between in-band (using credit card processor) and out-of-band (using external CC mechamism) in the staff client and payment entries git-svn-id: svn://svn.open-ils.org/ILS/trunk@14628 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index ad6187540a..e3c8d3f4bc 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -1294,6 +1294,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <field name="cash_drawer" reporter:datatype="link"/> <field name="cc_number" reporter:datatype="text"/> <field name="cc_type" reporter:datatype="text"/> + <field name="cc_processor" reporter:datatype="text"/> <field name="expire_month" reporter:datatype="int" /> <field name="expire_year" reporter:datatype="int" /> <field name="id" reporter:datatype="id" /> diff --git a/Open-ILS/src/extras/ils_events.xml b/Open-ILS/src/extras/ils_events.xml index 56c40da1d8..4f189fb183 100644 --- a/Open-ILS/src/extras/ils_events.xml +++ b/Open-ILS/src/extras/ils_events.xml @@ -756,6 +756,12 @@ <event code='4020' textcode='CREDIT_PROCESSOR_DECLINED_TRANSACTION'> <desc xml:lang="en-US">The credit card processor has declined the transaction.</desc> </event> + <event code='4040' textcode='CREDIT_PROCESSOR_SUCCESS_WO_RECORD'> + <desc xml:lang="en-US">A *TERRIBLE* problem has occurred: a credit + card transaction was processed successfuly, but the patron's + payment could not be recorded within Evergreen. Please seek + assistance.</desc> + </event> <event code='5000' textcode='PERM_FAILURE'> diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm index 2aa3240c72..778055d2c4 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm @@ -13,7 +13,6 @@ # GNU General Public License for more details. # --------------------------------------------------------------- - package OpenILS::Application::Circ::Money; use base qw/OpenILS::Application/; use strict; use warnings; @@ -30,12 +29,12 @@ use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Utils::Penalty; __PACKAGE__->register_method( - method => "make_payments", - api_name => "open-ils.circ.money.payment", + method => "make_payments", + api_name => "open-ils.circ.money.payment", signature => { desc => q/Create payments for a given user and set of transactions, - login must have CREATE_PAYMENT priveleges. - If any payments fail, all are reverted back./, + login must have CREATE_PAYMENT privileges. + If any payments fail, all are reverted back./, params => [ {desc => 'Authtoken', type => 'string'}, {desc => q/Arguments Hash, supporting the following params: @@ -44,13 +43,15 @@ __PACKAGE__->register_method( userid patron_credit note - cc_args : { - type - number - expire_month - expire_year - approval_code - } + cc_args: { + where_process 1 to use processor, !1 for out-of-band + approval_code (for out-of-band payment) + type (for out-of-band payment) + number (for call to payment processor) + expire_month (for call to payment processor) + expire_year (for call to payment processor) + note (if payments->{note} is blank, use this) + }, check_number payments: [ [trans_id, amt], @@ -61,36 +62,38 @@ __PACKAGE__->register_method( ] } ); - sub make_payments { - my($self, $client, $auth, $payments) = @_; + my($self, $client, $auth, $payments) = @_; - my $e = new_editor(authtoken => $auth, xact => 1); + my $e = new_editor(authtoken => $auth, xact => 1); return $e->die_event unless $e->checkauth; - my $type = $payments->{payment_type}; - my $user_id = $payments->{userid}; - my $credit = $payments->{patron_credit} || 0; - my $drawer = $e->requestor->wsid; - my $note = $payments->{note}; - my $check_number = $payments->{check_number}; + my $type = $payments->{payment_type}; + my $user_id = $payments->{userid}; + my $credit = $payments->{patron_credit} || 0; + my $drawer = $e->requestor->wsid; + my $note = $payments->{note}; my $cc_args = $payments->{cc_args}; - my $total_paid = 0; + my $check_number = $payments->{check_number}; + my $total_paid = 0; + my $this_ou = $e->requestor->ws_ou; my %orgs; + # unless/until determined by payment processor API + my ($approval_code, $cc_processor, $cc_type) = (undef,undef,undef); + my $patron = $e->retrieve_actor_user($user_id) or return $e->die_event; # A user is allowed to make credit card payments on his/her own behalf # All other scenarious require permission unless($type eq 'credit_card_payment' and $user_id == $e->requestor->id) { - return $e->die_event unless $e->allowed('CREATE_PAYMENT', $patron->home_ou); + return $e->die_event unless $e->allowed('CREATE_PAYMENT', $patron->home_ou); } # first collect the transactions and make sure the transaction # user matches the requested user my %xacts; for my $pay (@{$payments->{payments}}) { - my $xact_id = $pay->[0]; my $xact = $e->retrieve_money_billable_transaction_summary($xact_id) or return $e->die_event; @@ -105,379 +108,442 @@ sub make_payments { my @payment_objs; - for my $pay (@{$payments->{payments}}) { - + for my $pay (@{$payments->{payments}}) { my $transid = $pay->[0]; - my $amount = $pay->[1]; - $amount =~ s/\$//og; # just to be safe + my $amount = $pay->[1]; + $amount =~ s/\$//og; # just to be safe my $trans = $xacts{$transid}; - $total_paid += $amount; + $total_paid += $amount; $orgs{$U->xact_org($transid, $e)} = 1; - # making payment with existing patron credit - $credit -= $amount if $type eq 'credit_payment'; - - # A negative payment is a refund. - if( $amount < 0 ) { + # A negative payment is a refund. + if( $amount < 0 ) { # Negative credit card payments are not allowed if($type eq 'credit_card_payment') { $e->rollback; - return OpenILS::Event->new( + return OpenILS::Event->new( 'BAD_PARAMS', note => q/Negative credit card payments not allowed/ ); } - # If the refund causes the transaction balance to exceed 0 dollars, - # we are in effect loaning the patron money. This is not allowed. - if( ($trans->balance_owed - $amount) > 0 ) { + # If the refund causes the transaction balance to exceed 0 dollars, + # we are in effect loaning the patron money. This is not allowed. + if( ($trans->balance_owed - $amount) > 0 ) { $e->rollback; - return OpenILS::Event->new('REFUND_EXCEEDS_BALANCE'); - } + return OpenILS::Event->new('REFUND_EXCEEDS_BALANCE'); + } - # Otherwise, make sure the refund does not exceed desk payments - # This is also not allowed - my $desk_total = 0; - my $desk_payments = $e->search_money_desk_payment({xact => $transid, voided => 'f'}); - $desk_total += $_->amount for @$desk_payments; + # Otherwise, make sure the refund does not exceed desk payments + # This is also not allowed + my $desk_total = 0; + my $desk_payments = $e->search_money_desk_payment({xact => $transid, voided => 'f'}); + $desk_total += $_->amount for @$desk_payments; - if( (-$amount) > $desk_total ) { + if( (-$amount) > $desk_total ) { $e->rollback; - return OpenILS::Event->new( - 'REFUND_EXCEEDS_DESK_PAYMENTS', - payload => { allowed_refund => $desk_total, submitted_refund => -$amount } ); - } - } - - my $payobj = "Fieldmapper::money::$type"; - $payobj = $payobj->new; - - $payobj->amount($amount); - $payobj->amount_collected($amount); - $payobj->xact($transid); - $payobj->note($note); - - if ($payobj->has_field('accepting_usr')) { $payobj->accepting_usr($e->requestor->id); } - if ($payobj->has_field('cash_drawer')) { $payobj->cash_drawer($drawer); } - if ($payobj->has_field('cc_type')) { $payobj->cc_type($cc_args->{type}); } - if ($payobj->has_field('check_number')) { $payobj->check_number($check_number); } - - # Store the last 4 digits? - #if ($payobj->has_field('cc_number')) { $payobj->cc_number($cc_args->{number}); } - #if ($payobj->has_field('approval_code')) { $payobj->approval_code($cc_args->{approval_code}); } - if ($payobj->has_field('expire_month')) { $payobj->expire_month($cc_args->{expire_month}); } - if ($payobj->has_field('expire_year')) { $payobj->expire_year($cc_args->{expire_year}); } - - # update the transaction if it's done - if( (my $cred = ($trans->balance_owed - $amount)) <= 0 ) { - - # Any overpay on this transaction goes directly into patron credit - $cred = -$cred; - $credit += $cred; - my $circ = $e->retrieve_action_circulation($transid); + return OpenILS::Event->new( + 'REFUND_EXCEEDS_DESK_PAYMENTS', + payload => { allowed_refund => $desk_total, submitted_refund => -$amount } ); + } + } - if(!$circ || $circ->stop_fines) { - # If this is a circulation, we can't close the transaction unless stop_fines is set - $trans = $e->retrieve_money_billable_transaction($transid); - $trans->xact_finish("now"); - $e->update_money_billable_transaction($trans) or return $e->die_event; - } - } + my $payobj = "Fieldmapper::money::$type"; + $payobj = $payobj->new; - my $method = "create_money_$type"; - $e->$method($payobj) or return $e->die_event; - push(@payment_objs, $payobj); + $payobj->amount($amount); + $payobj->amount_collected($amount); + $payobj->xact($transid); + $payobj->note($note); + if ((not $payobj->note) and ($type eq 'credit_card_payment')) { + $payobj->note($cc_args->{note}); + } - } # all payment objects have been created and inserted. + if ($payobj->has_field('accepting_usr')) { $payobj->accepting_usr($e->requestor->id); } + if ($payobj->has_field('cash_drawer')) { $payobj->cash_drawer($drawer); } + if ($payobj->has_field('cc_type')) { $payobj->cc_type($cc_args->{type}); } + if ($payobj->has_field('check_number')) { $payobj->check_number($check_number); } - my $evt = _update_patron_credit($e, $patron, $credit); - return $evt if $evt; + # Store the last 4 digits of the CC number + if ($payobj->has_field('cc_number')) { + $payobj->cc_number(substr($cc_args->{number}, -4)); + } + if ($payobj->has_field('expire_month')) { $payobj->expire_month($cc_args->{expire_month}); } + if ($payobj->has_field('expire_year')) { $payobj->expire_year($cc_args->{expire_year}); } + + # Note: It is important not to set approval_code + # on the fieldmapper object yet. - for my $org_id (keys %orgs) { - # calculate penalties for each of the affected orgs - $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $user_id, $org_id); - return $evt if $evt; - } + push(@payment_objs, $payobj); + + } # all payment objects have been created and inserted. + #### NO WRITES TO THE DB ABOVE THIS LINE -- THEY'LL ONLY BE DISCARDED ### + $e->rollback; + + # After we try to externally process a credit card (if desired), we'll + # open a new transaction. We cannot leave one open while credit card + # processing might be happening, as it can easily time out the database + # transaction. if($type eq 'credit_card_payment') { - my $this_ou = $e->requestor->ws_ou; - my $response = $apputils->simplereq( - 'open-ils.credit', - 'open-ils.credit.process', - { - "desc" => $payments->{note}, - "amount" => $total_paid, - "patron_id" => $user_id, - "cc" => $payments->{cc_number}, - "expiration" => sprintf( - "%02d-%04d", - $payments->{expire_month}, - $payments->{expire_year} - ), - "ou" => $this_ou + $approval_code = $cc_args->{approval_code}; + # If an approval code was not given, we'll need + # to call to the payment processor ourselves. + if ($cc_args->{where_process} == 1) { + return OpenILS::Event->new('BAD_PARAMS', note => 'Need CC number') + if not $cc_args->{number}; + my $response = $apputils->simplereq( + 'open-ils.credit', + 'open-ils.credit.process', + { + "desc" => $cc_args->{note}, + "amount" => $total_paid, + "patron_id" => $user_id, + "cc" => $cc_args->{number}, + "expiration" => sprintf( + "%02d-%04d", + $cc_args->{expire_month}, + $cc_args->{expire_year} + ), + "ou" => $this_ou + } + ); + + if (exists $response->{ilsevent}) { + return $response; } - ); + if ($response->{statusCode} != 200) { + $logger->info("Credit card payment for user $user_id " . + "failed with message: " . $response->{statusText}); + return OpenILS::Event->new( + 'CREDIT_PROCESSOR_DECLINED_TRANSACTION', + note => $response->{statusText} + ); + } + $approval_code = $response->{approvalCode}; + $cc_type = $response->{cardType}; + $cc_processor = $response->{processor}; + $logger->info("Credit card payment processing for " . + "user $user_id succeeded"); + } + else { + return OpenILS::Event->new( + 'BAD_PARAMS', note => 'Need approval code' + ) if not $cc_args->{approval_code}; + } + } - if (exists $response->{ilsevent}) { - $e->rollback; - return $response; + ### RE-OPEN TRANSACTION HERE ### + $e->xact_begin; + + # create payment records + my $create_money_method = "create_money_" . $type; + for my $payment (@payment_objs) { + # update the transaction if it's done + my $amount = $payment->amount; + my $transid = $payment->xact; + my $trans = $xacts{$transid}; + if( (my $cred = ($trans->balance_owed - $amount)) <= 0 ) { + # Any overpay on this transaction goes directly into patron + # credit making payment with existing patron credit. + $credit -= $amount if $type eq 'credit_payment'; + + $cred = -$cred; + $credit += $cred; + my $circ = $e->retrieve_action_circulation($transid); + + if(!$circ || $circ->stop_fines) { + # If this is a circulation, we can't close the transaction + # unless stop_fines is set. + $trans = $e->retrieve_money_billable_transaction($transid); + $trans->xact_finish("now"); + if (!$e->update_money_billable_transaction($trans)) { + $logger->warn("update_money_billable_transaction() " . + "failed"); + $e->rollback; + return OpenILS::Event->new( + 'CREDIT_PROCESSOR_SUCCESS_WO_RECORD', + note => 'update_money_billable_transaction() failed' + ); + } + } } - if ($response->{statusCode} != 200) { + + $payment->approval_code($approval_code) if $approval_code; + $payment->cc_type($cc_type) if $cc_type; + $payment->cc_processor($cc_processor) if $cc_processor; + if (!$e->$create_money_method($payment)) { + $logger->warn("$create_money_method failed: " . + Dumper($payment)); # won't contain CC number. $e->rollback; - $logger->info("Credit card payment for user $user_id failed with message: " . $response->{statusText}); return OpenILS::Event->new( - 'CREDIT_PROCESSOR_DECLINED_TRANSACTION', - note => $response->{statusText} + 'CREDIT_PROCESSOR_SUCCESS_WO_RECORD', + note => "$create_money_method failed" ); } + } - for my $payment (@payment_objs) { - $payment->approval_code($response->{approvalCode}); - $e->update_money_credit_card_payment($payment) or return $e->die_event; + my $evt = _update_patron_credit($e, $patron, $credit); + if ($evt) { + $logger->warn("_update_patron_credit() failed"); + $e->rollback; + return OpenILS::Event->new( + 'CREDIT_PROCESSOR_SUCCESS_WO_RECORD', + note => "_update_patron_credit() failed" + ); + } + + for my $org_id (keys %orgs) { + # calculate penalties for each of the affected orgs + $evt = OpenILS::Utils::Penalty->calculate_penalties( + $e, $user_id, $org_id + ); + if ($evt) { + $logger->warn( + "OpenILS::Utils::Penalty::calculate_penalties() failed" + ); + $e->rollback; + return OpenILS::Event->new( + 'CREDIT_PROCESSOR_SUCCESS_WO_RECORD', + note => "OpenILS::Utils::Penalty::calculate_penalties() failed" + ); } - $logger->info("Credit card payment for user $user_id succeeded"); } $e->commit; return 1; } - sub _update_patron_credit { - my($e, $patron, $credit) = @_; + my($e, $patron, $credit) = @_; return undef if $credit == 0; - $patron->credit_forward_balance($patron->credit_forward_balance + $credit); + $patron->credit_forward_balance($patron->credit_forward_balance + $credit); return OpenILS::Event->new('NEGATIVE_PATRON_BALANCE') if $patron->credit_forward_balance < 0; $e->update_actor_user($patron) or return $e->die_event; - return undef; + return undef; } __PACKAGE__->register_method( - method => "retrieve_payments", - api_name => "open-ils.circ.money.payment.retrieve.all_", - notes => "Returns a list of payments attached to a given transaction" - ); - + method => "retrieve_payments", + api_name => "open-ils.circ.money.payment.retrieve.all_", + notes => "Returns a list of payments attached to a given transaction" + ); sub retrieve_payments { - my( $self, $client, $login, $transid ) = @_; + my( $self, $client, $login, $transid ) = @_; - my( $staff, $evt ) = - $apputils->checksesperm($login, 'VIEW_TRANSACTION'); - return $evt if $evt; + my( $staff, $evt ) = + $apputils->checksesperm($login, 'VIEW_TRANSACTION'); + return $evt if $evt; - # XXX the logic here is wrong.. we need to check the owner of the transaction - # to make sure the requestor has access + # XXX the logic here is wrong.. we need to check the owner of the transaction + # to make sure the requestor has access - # XXX grab the view, for each object in the view, grab the real object + # XXX grab the view, for each object in the view, grab the real object - return $apputils->simplereq( - 'open-ils.cstore', - 'open-ils.cstore.direct.money.payment.search.atomic', { xact => $transid } ); + return $apputils->simplereq( + 'open-ils.cstore', + 'open-ils.cstore.direct.money.payment.search.atomic', { xact => $transid } ); } - __PACKAGE__->register_method( - method => "retrieve_payments2", + method => "retrieve_payments2", authoritative => 1, - api_name => "open-ils.circ.money.payment.retrieve.all", - notes => "Returns a list of payments attached to a given transaction" - ); - + api_name => "open-ils.circ.money.payment.retrieve.all", + notes => "Returns a list of payments attached to a given transaction" + ); + sub retrieve_payments2 { - my( $self, $client, $login, $transid ) = @_; - - my $e = new_editor(authtoken=>$login); - return $e->event unless $e->checkauth; - return $e->event unless $e->allowed('VIEW_TRANSACTION'); - - my @payments; - my $pmnts = $e->search_money_payment({ xact => $transid }); - for( @$pmnts ) { - my $type = $_->payment_type; - my $meth = "retrieve_money_$type"; - my $p = $e->$meth($_->id) or return $e->event; - $p->payment_type($type); - $p->cash_drawer($e->retrieve_actor_workstation($p->cash_drawer)) - if $p->has_field('cash_drawer'); - push( @payments, $p ); - } - - return \@payments; -} + my( $self, $client, $login, $transid ) = @_; + + my $e = new_editor(authtoken=>$login); + return $e->event unless $e->checkauth; + return $e->event unless $e->allowed('VIEW_TRANSACTION'); + + my @payments; + my $pmnts = $e->search_money_payment({ xact => $transid }); + for( @$pmnts ) { + my $type = $_->payment_type; + my $meth = "retrieve_money_$type"; + my $p = $e->$meth($_->id) or return $e->event; + $p->payment_type($type); + $p->cash_drawer($e->retrieve_actor_workstation($p->cash_drawer)) + if $p->has_field('cash_drawer'); + push( @payments, $p ); + } + return \@payments; +} __PACKAGE__->register_method( - method => "create_grocery_bill", - api_name => "open-ils.circ.money.grocery.create", - notes => <<" NOTE"); - Creates a new grocery transaction using the transaction object provided - PARAMS: (login_session, money.grocery (mg) object) - NOTE + method => "create_grocery_bill", + api_name => "open-ils.circ.money.grocery.create", + notes => <<" NOTE"); + Creates a new grocery transaction using the transaction object provided + PARAMS: (login_session, money.grocery (mg) object) + NOTE sub create_grocery_bill { - my( $self, $client, $login, $transaction ) = @_; + my( $self, $client, $login, $transaction ) = @_; - my( $staff, $evt ) = $apputils->checkses($login); - return $evt if $evt; - $evt = $apputils->check_perms($staff->id, - $transaction->billing_location, 'CREATE_TRANSACTION' ); - return $evt if $evt; + my( $staff, $evt ) = $apputils->checkses($login); + return $evt if $evt; + $evt = $apputils->check_perms($staff->id, + $transaction->billing_location, 'CREATE_TRANSACTION' ); + return $evt if $evt; - $logger->activity("Creating grocery bill " . Dumper($transaction) ); + $logger->activity("Creating grocery bill " . Dumper($transaction) ); - $transaction->clear_id; - my $session = $apputils->start_db_session; - my $transid = $session->request( - 'open-ils.storage.direct.money.grocery.create', $transaction)->gather(1); + $transaction->clear_id; + my $session = $apputils->start_db_session; + my $transid = $session->request( + 'open-ils.storage.direct.money.grocery.create', $transaction)->gather(1); - throw OpenSRF::EX ("Error creating new money.grocery") unless defined $transid; + throw OpenSRF::EX ("Error creating new money.grocery") unless defined $transid; - $logger->debug("Created new grocery transaction $transid"); - - $apputils->commit_db_session($session); + $logger->debug("Created new grocery transaction $transid"); + + $apputils->commit_db_session($session); my $e = new_editor(xact=>1); $evt = _check_open_xact($e, $transid); return $evt if $evt; $e->commit; - return $transid; + return $transid; } __PACKAGE__->register_method( - method => 'fetch_grocery', - api_name => 'open-ils.circ.money.grocery.retrieve' + method => 'fetch_grocery', + api_name => 'open-ils.circ.money.grocery.retrieve' ); - sub fetch_grocery { - my( $self, $conn, $auth, $id ) = @_; - my $e = new_editor(authtoken=>$auth); - return $e->event unless $e->checkauth; - return $e->event unless $e->allowed('VIEW_TRANSACTION'); # eh.. basically the same permission - my $g = $e->retrieve_money_grocery($id) - or return $e->event; - return $g; + my( $self, $conn, $auth, $id ) = @_; + my $e = new_editor(authtoken=>$auth); + return $e->event unless $e->checkauth; + return $e->event unless $e->allowed('VIEW_TRANSACTION'); # eh.. basically the same permission + my $g = $e->retrieve_money_grocery($id) + or return $e->event; + return $g; } __PACKAGE__->register_method( - method => "billing_items", + method => "billing_items", authoritative => 1, - api_name => "open-ils.circ.money.billing.retrieve.all", - notes =><<" NOTE"); - Returns a list of billing items for the given transaction. - PARAMS( login, transaction_id ) - NOTE + api_name => "open-ils.circ.money.billing.retrieve.all", + notes =><<" NOTE"); + Returns a list of billing items for the given transaction. + PARAMS( login, transaction_id ) + NOTE sub billing_items { - my( $self, $client, $login, $transid ) = @_; - - my( $trans, $evt ) = $U->fetch_billable_xact($transid); - return $evt if $evt; - - my $staff; - ($staff, $evt ) = $apputils->checkses($login); - return $evt if $evt; - - if($staff->id ne $trans->usr) { - $evt = $U->check_perms($staff->id, $staff->home_ou, 'VIEW_TRANSACTION'); - return $evt if $evt; - } - - return $apputils->simplereq( 'open-ils.cstore', - 'open-ils.cstore.direct.money.billing.search.atomic', { xact => $transid } ) + my( $self, $client, $login, $transid ) = @_; + + my( $trans, $evt ) = $U->fetch_billable_xact($transid); + return $evt if $evt; + + my $staff; + ($staff, $evt ) = $apputils->checkses($login); + return $evt if $evt; + + if($staff->id ne $trans->usr) { + $evt = $U->check_perms($staff->id, $staff->home_ou, 'VIEW_TRANSACTION'); + return $evt if $evt; + } + + return $apputils->simplereq( 'open-ils.cstore', + 'open-ils.cstore.direct.money.billing.search.atomic', { xact => $transid } ) } __PACKAGE__->register_method( - method => "billing_items_create", - api_name => "open-ils.circ.money.billing.create", - notes =><<" NOTE"); - Creates a new billing line item - PARAMS( login, bill_object (mb) ) - NOTE + method => "billing_items_create", + api_name => "open-ils.circ.money.billing.create", + notes =><<" NOTE"); + Creates a new billing line item + PARAMS( login, bill_object (mb) ) + NOTE sub billing_items_create { - my( $self, $client, $login, $billing ) = @_; + my( $self, $client, $login, $billing ) = @_; - my $e = new_editor(authtoken => $login, xact => 1); - return $e->die_event unless $e->checkauth; - return $e->die_event unless $e->allowed('CREATE_BILL'); + my $e = new_editor(authtoken => $login, xact => 1); + return $e->die_event unless $e->checkauth; + return $e->die_event unless $e->allowed('CREATE_BILL'); - my $xact = $e->retrieve_money_billable_transaction($billing->xact) - or return $e->die_event; + my $xact = $e->retrieve_money_billable_transaction($billing->xact) + or return $e->die_event; - # if the transaction was closed, re-open it - if($xact->xact_finish) { - $xact->clear_xact_finish; - $e->update_money_billable_transaction($xact) - or return $e->die_event; - } + # if the transaction was closed, re-open it + if($xact->xact_finish) { + $xact->clear_xact_finish; + $e->update_money_billable_transaction($xact) + or return $e->die_event; + } - my $amt = $billing->amount; - $amt =~ s/\$//og; - $billing->amount($amt); + my $amt = $billing->amount; + $amt =~ s/\$//og; + $billing->amount($amt); - $e->create_money_billing($billing) or return $e->die_event; + $e->create_money_billing($billing) or return $e->die_event; my $evt = OpenILS::Utils::Penalty->calculate_penalties($e, $xact->usr, $U->xact_org($xact->id)); return $evt if $evt; - $e->commit; + $e->commit; - return $billing->id; + return $billing->id; } + __PACKAGE__->register_method( - method => 'void_bill', - api_name => 'open-ils.circ.money.billing.void', - signature => q/ - Voids a bill - @param authtoken Login session key - @param billid Id for the bill to void. This parameter may be repeated to reference other bills. - @return 1 on success, Event on error - / + method => 'void_bill', + api_name => 'open-ils.circ.money.billing.void', + signature => q/ + Voids a bill + @param authtoken Login session key + @param billid Id for the bill to void. This parameter may be repeated to reference other bills. + @return 1 on success, Event on error + / ); - - sub void_bill { - my( $s, $c, $authtoken, @billids ) = @_; + my( $s, $c, $authtoken, @billids ) = @_; - my $e = new_editor( authtoken => $authtoken, xact => 1 ); - return $e->die_event unless $e->checkauth; - return $e->die_event unless $e->allowed('VOID_BILLING'); + my $e = new_editor( authtoken => $authtoken, xact => 1 ); + return $e->die_event unless $e->checkauth; + return $e->die_event unless $e->allowed('VOID_BILLING'); my %users; for my $billid (@billids) { - my $bill = $e->retrieve_money_billing($billid) - or return $e->die_event; + my $bill = $e->retrieve_money_billing($billid) + or return $e->die_event; my $xact = $e->retrieve_money_billable_transaction($bill->xact) or return $e->die_event; if($U->is_true($bill->voided)) { $e->rollback; - return OpenILS::Event->new('BILL_ALREADY_VOIDED', payload => $bill); + return OpenILS::Event->new('BILL_ALREADY_VOIDED', payload => $bill); } my $org = $U->xact_org($bill->xact, $e); $users{$xact->usr} = {} unless $users{$xact->usr}; $users{$xact->usr}->{$org} = 1; - $bill->voided('t'); - $bill->voider($e->requestor->id); - $bill->void_time('now'); + $bill->voided('t'); + $bill->voider($e->requestor->id); + $bill->void_time('now'); - $e->update_money_billing($bill) or return $e->die_event; - my $evt = _check_open_xact($e, $bill->xact, $xact); - return $evt if $evt; + $e->update_money_billing($bill) or return $e->die_event; + my $evt = _check_open_xact($e, $bill->xact, $xact); + return $evt if $evt; } # calculate penalties for all user/org combinations @@ -486,190 +552,176 @@ sub void_bill { OpenILS::Utils::Penalty->calculate_penalties($e, $user_id, $org_id); } } - - $e->commit; - return 1; + $e->commit; + return 1; } + __PACKAGE__->register_method( - method => 'edit_bill_note', - api_name => 'open-ils.circ.money.billing.note.edit', - signature => q/ - Edits the note for a bill - @param authtoken Login session key + method => 'edit_bill_note', + api_name => 'open-ils.circ.money.billing.note.edit', + signature => q/ + Edits the note for a bill + @param authtoken Login session key @param note The replacement note for the bills we're editing - @param billid Id for the bill to edit the note of. This parameter may be repeated to reference other bills. - @return 1 on success, Event on error - / + @param billid Id for the bill to edit the note of. This parameter may be repeated to reference other bills. + @return 1 on success, Event on error + / ); - - sub edit_bill_note { - my( $s, $c, $authtoken, $note, @billids ) = @_; + my( $s, $c, $authtoken, $note, @billids ) = @_; - my $e = new_editor( authtoken => $authtoken, xact => 1 ); - return $e->die_event unless $e->checkauth; - return $e->die_event unless $e->allowed('UPDATE_BILL_NOTE'); + my $e = new_editor( authtoken => $authtoken, xact => 1 ); + return $e->die_event unless $e->checkauth; + return $e->die_event unless $e->allowed('UPDATE_BILL_NOTE'); for my $billid (@billids) { - my $bill = $e->retrieve_money_billing($billid) - or return $e->die_event; + my $bill = $e->retrieve_money_billing($billid) + or return $e->die_event; - $bill->note($note); + $bill->note($note); # FIXME: Does this get audited? Need some way so that the original creator of the bill does not get credit/blame for the new note. - $e->update_money_billing($bill) or return $e->die_event; + $e->update_money_billing($bill) or return $e->die_event; } - - $e->commit; - return 1; + $e->commit; + return 1; } + __PACKAGE__->register_method( - method => 'edit_payment_note', - api_name => 'open-ils.circ.money.payment.note.edit', - signature => q/ - Edits the note for a payment - @param authtoken Login session key + method => 'edit_payment_note', + api_name => 'open-ils.circ.money.payment.note.edit', + signature => q/ + Edits the note for a payment + @param authtoken Login session key @param note The replacement note for the payments we're editing - @param paymentid Id for the payment to edit the note of. This parameter may be repeated to reference other payments. - @return 1 on success, Event on error - / + @param paymentid Id for the payment to edit the note of. This parameter may be repeated to reference other payments. + @return 1 on success, Event on error + / ); - - sub edit_payment_note { - my( $s, $c, $authtoken, $note, @paymentids ) = @_; + my( $s, $c, $authtoken, $note, @paymentids ) = @_; - my $e = new_editor( authtoken => $authtoken, xact => 1 ); - return $e->die_event unless $e->checkauth; - return $e->die_event unless $e->allowed('UPDATE_PAYMENT_NOTE'); + my $e = new_editor( authtoken => $authtoken, xact => 1 ); + return $e->die_event unless $e->checkauth; + return $e->die_event unless $e->allowed('UPDATE_PAYMENT_NOTE'); for my $paymentid (@paymentids) { - my $payment = $e->retrieve_money_payment($paymentid) - or return $e->die_event; + my $payment = $e->retrieve_money_payment($paymentid) + or return $e->die_event; - $payment->note($note); + $payment->note($note); # FIXME: Does this get audited? Need some way so that the original taker of the payment does not get credit/blame for the new note. - $e->update_money_payment($payment) or return $e->die_event; + $e->update_money_payment($payment) or return $e->die_event; } - $e->commit; - return 1; + $e->commit; + return 1; } sub _check_open_xact { - my( $editor, $xactid, $xact ) = @_; + my( $editor, $xactid, $xact ) = @_; - # Grab the transaction - $xact ||= $editor->retrieve_money_billable_transaction($xactid); + # Grab the transaction + $xact ||= $editor->retrieve_money_billable_transaction($xactid); return $editor->event unless $xact; $xactid ||= $xact->id; - # grab the summary and see how much is owed on this transaction - my ($summary) = $U->fetch_mbts($xactid, $editor); - - # grab the circulation if it is a circ; - my $circ = $editor->retrieve_action_circulation($xactid); - - # If nothing is owed on the transaction but it is still open - # and this transaction is not an open circulation, close it - if( - ( $summary->balance_owed == 0 and ! $xact->xact_finish ) and - ( !$circ or $circ->stop_fines )) { - - $logger->info("closing transaction ".$xact->id. ' becauase balance_owed == 0'); - $xact->xact_finish('now'); - $editor->update_money_billable_transaction($xact) - or return $editor->event; - return undef; - } - - # If money is owed or a refund is due on the xact and xact_finish - # is set, clear it (to reopen the xact) and update - if( $summary->balance_owed != 0 and $xact->xact_finish ) { - $logger->info("re-opening transaction ".$xact->id. ' becauase balance_owed != 0'); - $xact->clear_xact_finish; - $editor->update_money_billable_transaction($xact) - or return $editor->event; - return undef; - } - - return undef; -} + # grab the summary and see how much is owed on this transaction + my ($summary) = $U->fetch_mbts($xactid, $editor); + + # grab the circulation if it is a circ; + my $circ = $editor->retrieve_action_circulation($xactid); + # If nothing is owed on the transaction but it is still open + # and this transaction is not an open circulation, close it + if( + ( $summary->balance_owed == 0 and ! $xact->xact_finish ) and + ( !$circ or $circ->stop_fines )) { + + $logger->info("closing transaction ".$xact->id. ' becauase balance_owed == 0'); + $xact->xact_finish('now'); + $editor->update_money_billable_transaction($xact) + or return $editor->event; + return undef; + } + + # If money is owed or a refund is due on the xact and xact_finish + # is set, clear it (to reopen the xact) and update + if( $summary->balance_owed != 0 and $xact->xact_finish ) { + $logger->info("re-opening transaction ".$xact->id. ' becauase balance_owed != 0'); + $xact->clear_xact_finish; + $editor->update_money_billable_transaction($xact) + or return $editor->event; + return undef; + } + return undef; +} __PACKAGE__->register_method ( - method => 'fetch_mbts', + method => 'fetch_mbts', authoritative => 1, - api_name => 'open-ils.circ.money.billable_xact_summary.retrieve' + api_name => 'open-ils.circ.money.billable_xact_summary.retrieve' ); sub fetch_mbts { - my( $self, $conn, $auth, $id) = @_; + my( $self, $conn, $auth, $id) = @_; - my $e = new_editor(xact => 1, authtoken=>$auth); - return $e->event unless $e->checkauth; - my ($mbts) = $U->fetch_mbts($id, $e); + my $e = new_editor(xact => 1, authtoken=>$auth); + return $e->event unless $e->checkauth; + my ($mbts) = $U->fetch_mbts($id, $e); - my $user = $e->retrieve_actor_user($mbts->usr) - or return $e->die_event; + my $user = $e->retrieve_actor_user($mbts->usr) + or return $e->die_event; - return $e->die_event unless $e->allowed('VIEW_TRANSACTION', $user->home_ou); - $e->rollback; - return $mbts + return $e->die_event unless $e->allowed('VIEW_TRANSACTION', $user->home_ou); + $e->rollback; + return $mbts } - __PACKAGE__->register_method( - method => 'desk_payments', - api_name => 'open-ils.circ.money.org_unit.desk_payments' + method => 'desk_payments', + api_name => 'open-ils.circ.money.org_unit.desk_payments' ); - sub desk_payments { - my( $self, $conn, $auth, $org, $start_date, $end_date ) = @_; - my $e = new_editor(authtoken=>$auth); - return $e->event unless $e->checkauth; - return $e->event unless $e->allowed('VIEW_TRANSACTION', $org); - my $data = $U->storagereq( - 'open-ils.storage.money.org_unit.desk_payments.atomic', - $org, $start_date, $end_date ); - - $_->workstation( $_->workstation->name ) for(@$data); - return $data; + my( $self, $conn, $auth, $org, $start_date, $end_date ) = @_; + my $e = new_editor(authtoken=>$auth); + return $e->event unless $e->checkauth; + return $e->event unless $e->allowed('VIEW_TRANSACTION', $org); + my $data = $U->storagereq( + 'open-ils.storage.money.org_unit.desk_payments.atomic', + $org, $start_date, $end_date ); + + $_->workstation( $_->workstation->name ) for(@$data); + return $data; } __PACKAGE__->register_method( - method => 'user_payments', - api_name => 'open-ils.circ.money.org_unit.user_payments' + method => 'user_payments', + api_name => 'open-ils.circ.money.org_unit.user_payments' ); sub user_payments { - my( $self, $conn, $auth, $org, $start_date, $end_date ) = @_; - my $e = new_editor(authtoken=>$auth); - return $e->event unless $e->checkauth; - return $e->event unless $e->allowed('VIEW_TRANSACTION', $org); - my $data = $U->storagereq( - 'open-ils.storage.money.org_unit.user_payments.atomic', - $org, $start_date, $end_date ); - for(@$data) { - $_->usr->card( - $e->retrieve_actor_card($_->usr->card)->barcode); - $_->usr->home_ou( - $e->retrieve_actor_org_unit($_->usr->home_ou)->shortname); - } - return $data; + my( $self, $conn, $auth, $org, $start_date, $end_date ) = @_; + my $e = new_editor(authtoken=>$auth); + return $e->event unless $e->checkauth; + return $e->event unless $e->allowed('VIEW_TRANSACTION', $org); + my $data = $U->storagereq( + 'open-ils.storage.money.org_unit.user_payments.atomic', + $org, $start_date, $end_date ); + for(@$data) { + $_->usr->card( + $e->retrieve_actor_card($_->usr->card)->barcode); + $_->usr->home_ou( + $e->retrieve_actor_org_unit($_->usr->home_ou)->shortname); + } + return $data; } - - - 1; - - - diff --git a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm index bd1a845326..c43b8dec9b 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm @@ -265,6 +265,8 @@ sub dispatch { my $retval = { statusText => "Transaction approved: " . $transaction->authorization, + processor => $argshash->{processor}, + cardType => $cardtype, statusCode => 200, approvalCode => $transaction->authorization, server_response => $transaction->server_response diff --git a/Open-ILS/src/sql/Pg/002.schema.config.sql b/Open-ILS/src/sql/Pg/002.schema.config.sql index 2715e7ade4..86e1052d37 100644 --- a/Open-ILS/src/sql/Pg/002.schema.config.sql +++ b/Open-ILS/src/sql/Pg/002.schema.config.sql @@ -51,8 +51,7 @@ CREATE TABLE config.upgrade_log ( install_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); -INSERT INTO config.upgrade_log (version) VALUES ('0056'); -- phasefx - +INSERT INTO config.upgrade_log (version) VALUES ('0057'); -- senator CREATE TABLE config.bib_source ( id SERIAL PRIMARY KEY, diff --git a/Open-ILS/src/sql/Pg/080.schema.money.sql b/Open-ILS/src/sql/Pg/080.schema.money.sql index 16955f95e4..007990bc53 100644 --- a/Open-ILS/src/sql/Pg/080.schema.money.sql +++ b/Open-ILS/src/sql/Pg/080.schema.money.sql @@ -619,6 +619,7 @@ CREATE TRIGGER mat_summary_del_tgr BEFORE DELETE ON money.check_payment FOR EACH CREATE TABLE money.credit_card_payment ( cc_type TEXT, cc_number TEXT, + cc_processor TEXT, expire_month INT, expire_year INT, approval_code TEXT diff --git a/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql b/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql new file mode 100644 index 0000000000..c1659bf2c5 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql @@ -0,0 +1,7 @@ +BEGIN; + +INSERT INTO config.upgrade_log (version) VALUES ('0057'); -- senator + +ALTER TABLE money.credit_card_payment ADD COLUMN cc_processor TEXT; + +COMMIT; diff --git a/Open-ILS/web/opac/locale/en-US/lang.dtd b/Open-ILS/web/opac/locale/en-US/lang.dtd index 011f64afe9..6cbdeafd26 100644 --- a/Open-ILS/web/opac/locale/en-US/lang.dtd +++ b/Open-ILS/web/opac/locale/en-US/lang.dtd @@ -2415,6 +2415,9 @@ <!ENTITY staff.pat.barcode_entry.submit_btn.accesskey "S"> <!ENTITY staff.pat.barcode_entry.retrieving.label "Retrieving..."> <!ENTITY staff.patron.bill_cc_info.title "Credit Card Information"> +<!ENTITY staff.patron.bill_cc_info.where_process.label "Process where?"> +<!ENTITY staff.patron.bill_cc_info.process_int.label "Process payment through Evergreen"> +<!ENTITY staff.patron.bill_cc_info.process_ext.label "Record externally processed payment"> <!ENTITY staff.patron.bill_cc_info.visa.label "Visa"> <!ENTITY staff.patron.bill_cc_info.mastercard.label "Mastercard"> <!ENTITY staff.patron.bill_cc_info.american_express.label "American Express"> diff --git a/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties b/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties index 3f08b1cb57..e6b5fc330b 100644 --- a/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties +++ b/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties @@ -10,6 +10,8 @@ staff.patron.barcode_entry.patron_consent_deny=Deny staff.patron.barcode_entry.patron_consent_confirm=Check here to confirm this message staff.patron.barcode_entry.patron_display_error=spawning patron display staff.patron.barcode_entry.user_perm_display_error=spawning user perm editor +staff.patron.bill_cc_info.need_cc_number=You must provide a credit card number +staff.patron.bill_cc_info.need_approval_code=You must provide an approval code or an imprint slip number staff.patron.bill_details.my_init.error=bill_details.xul, my_init: staff.patron.bill_details.handle_edit_bill_note.note_dialog.title=Replacement Note staff.patron.bill_details.handle_edit_bill_note.note_dialog.prompt=Enter new note: diff --git a/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul b/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul index 937966926b..808242a7c3 100644 --- a/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul +++ b/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul @@ -19,95 +19,170 @@ <?xul-overlay href="/xul/server/OpenILS/util_overlay.xul"?> <window id="patron_bill" title="&staff.patron.bill_cc_info.title;" - orient="vertical" style="overflow: auto" - onload="try{info_init(); font_helper();}catch(E){alert(E);}" - xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + orient="vertical" style="overflow: auto" + onload="try{info_init(); font_helper();refresh_fields();}catch(E){alert(E);}" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <!-- ///////////////////////////////////////////////////////////////////////////////////////////////////////////// --> <!-- BEHAVIOR --> <script type="text/javascript">var myPackageDir = 'open_ils_staff_client'; var IAMXUL = true; var g = {};</script> <scripts id="openils_util_scripts"/> - <script type="text/javascript" src="/xul/server/main/JSAN.js"/> - - <script> - <![CDATA[ - function $(id) { return document.getElementById(id); } - - function info_init() { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); } - JSAN.errorLevel = "die"; // none, warn, or die - JSAN.addRepository('/xul/server/'); - JSAN.use('util.error'); g.error = new util.error(); - g.error.sdump('D_TRACE','my_init() for patron_display.xul'); - g.OpenILS = {}; JSAN.use('OpenILS.data'); g.OpenILS.data = new OpenILS.data(); - g.OpenILS.data.init({'via':'stash'}); - g.payment_blob = { 'cc_args' : {}, 'cancelled' : true }; - g.OpenILS.data.temp = js2JSON( g.payment_blob ); - g.OpenILS.data.stash('temp'); - - document.getElementById('cc_number').focus(); + <script type="text/javascript" src="/xul/server/main/JSAN.js"/> + + <script> + <![CDATA[ + function $(id) { return document.getElementById(id); } + + XULElement.prototype.hide = function() { + this.style.display = "none"; + } + XULElement.prototype.reveal = function() { + this.style.display = ""; + } + + var show = {'int': 1, 'ext': 2}; // tied to Application::Circ::Money + var fields_of_interest = { + "cc_type": show['ext'], + "cc_number": show['int'], + "expire_month": show['int'], + "expire_year": show['int'], + "approval_code": show['ext'], + "note": show['ext'] + show['int'], + "where_process": show['ext'] + show['int'] + }; + + function is_relevant_here(field) { + var flag = $('where_process').value; + var field_flag = fields_of_interest[field]; + return ((field_flag & flag) == flag); + } + + function refresh_fields() { + for (var field in fields_of_interest) { + if (is_relevant_here(field)) { + $('row_' + field).reveal(); + } + else { + $('row_' + field).hide(); + } + } } - function info_finish() { - /* FIXME -- need unique temp space name */ - delete( g.payment_blob.cancelled ); - g.OpenILS.data.temp = js2JSON( g.payment_blob ); - g.OpenILS.data.stash('temp'); + function info_init() { + netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); + if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); } + JSAN.errorLevel = "die"; // none, warn, or die + JSAN.addRepository('/xul/server/'); + JSAN.use('util.error'); g.error = new util.error(); + g.error.sdump('D_TRACE','my_init() for patron_display.xul'); + g.OpenILS = {}; JSAN.use('OpenILS.data'); g.OpenILS.data = new OpenILS.data(); + g.OpenILS.data.init({'via':'stash'}); + /* 'true' as a string matches the expectations in bills.js */ + g.payment_blob = { 'cc_args' : {}, 'cancelled' : 'true' }; + g.OpenILS.data.temp = js2JSON( g.payment_blob ); + g.OpenILS.data.stash('temp'); + + document.getElementById('cc_number').focus(); + } + + function sanity_check() { + if ($('where_process').value == show['int']) { // internal process + if ($('cc_number').value.match(/^\s*$/)) { + alert($('patronStrings').getString('staff.patron.bill_cc_info.need_cc_number')); + return false; + } + } + else { // external + if ($('approval_code').value.match(/^\s*$/)) { + alert($('patronStrings').getString('staff.patron.bill_cc_info.need_approval_code')); + return false; + } + } + return true; } - ]]> - </script> - - <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties" /> - - <groupbox> - <caption label="&staff.patron.bill_cc_info.info.label;"/> - <grid> - <columns> <column flex="0" /> <column flex="0" /> </columns> - <rows> - <row> - <label value="&staff.patron.bill_cc_info.type.label;"/> - <menulist id="cc_type" oncommand="g.payment_blob.cc_args.type = this.value;"> - <menupopup> - <menuitem label="&staff.patron.bill_cc_info.visa.label;" value="Visa"/> - <menuitem label="&staff.patron.bill_cc_info.mastercard.label;" value="Mastercard"/> - <menuitem label="&staff.patron.bill_cc_info.american_express.label;" value="American Express"/> - <menuitem label="&staff.patron.bill_cc_info.discover.label;" value="Discover"/> - <menuitem label="&staff.patron.bill_cc_info.other.label;" value="Other"/> - </menupopup> - </menulist> - </row> - <row> - <label value="&staff.patron.bill_cc_info.cc_number.value;"/> - <textbox id="cc_number" onchange="g.payment_blob.cc_args.number = event.target.value" context="clipboard"/> - </row> - <row> - <label value="&staff.patron.bill_cc_info.month_expire.value;"/> - <textbox id="expire_month" onchange="g.payment_blob.cc_args.expire_month = event.target.value" context="clipboard"/> - </row> - <row> - <label value="&staff.patron.bill_cc_info.year_expire.value;"/> - <textbox id="expire_year" onchange="g.payment_blob.cc_args.expire_year = event.target.value" context="clipboard"/> - </row> - <row> - <label value="&staff.patron.bill_cc_info.approval_code.value;"/> - <textbox id="approval_code" onchange="g.payment_blob.cc_args.approval_code = event.target.value" context="clipboard"/> - </row> - <row> - <label value="&staff.patron.bill_cc_info.note.value;"/> - <textbox id="note" onchange="g.payment_blob.note = event.target.value" multiline="true" context="clipboard"/> - </row> - </rows> - </grid> - <hbox> - <spacer flex="1"/> - <button label="&staff.patron.bill_cc_info.cancel.label;" oncommand="window.close()" accesskey="&staff.patron.bill_cc_info.cancel.accesskey;"/> - <button label="&staff.patron.bill_cc_info.submit.label;" oncommand="info_finish(); window.close();" accesskey="&staff.patron.bill_cc_info.submit.accesskey;"/> - </hbox> - </groupbox> + function info_finish() { + /* FIXME -- need unique temp space name */ + + /* The following for loop gathers our payment_blob values from + the widgets in this window. This is better than the method of + gathering data that was here before (using oncommand attributes + to set values in this JS object whenever a field value changed) + because (if for no other reason), a select menu, if left at the + default value, would never reach the payment_blob, because its + oncommand attribute would never fire. */ + for (var field in fields_of_interest) { + if (is_relevant_here(field)) { + var matches = field.match(/^cc_(.+)$/); + var target_key = matches ? matches[1] : field; + g.payment_blob.cc_args[target_key] = $(field).value; + } + } + delete( g.payment_blob.cancelled ); + g.OpenILS.data.temp = js2JSON( g.payment_blob ); + g.OpenILS.data.stash('temp'); + } + + ]]> + </script> + + <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties" /> + + <groupbox> + <caption label="&staff.patron.bill_cc_info.info.label;"/> + <grid> + <columns> <column flex="0" /> <column flex="0" /> </columns> + <rows> + <row id="row_where_process"> + <label value="&staff.patron.bill_cc_info.where_process.label;"/> + <menulist id="where_process" oncommand="refresh_fields();"> + <menupopup> + <menuitem label="&staff.patron.bill_cc_info.process_int.label;" value="1"/> + <menuitem label="&staff.patron.bill_cc_info.process_ext.label;" value="2"/> + </menupopup> + </menulist> + </row> + <row id="row_cc_type"> + <label value="&staff.patron.bill_cc_info.type.label;"/> + <menulist id="cc_type"> + <menupopup> + <menuitem label="&staff.patron.bill_cc_info.visa.label;" value="VISA"/><!-- capitalization to match CC processors' output --> + <menuitem label="&staff.patron.bill_cc_info.mastercard.label;" value="MasterCard"/><!-- capitalization to match CC processors' output --> + <menuitem label="&staff.patron.bill_cc_info.american_express.label;" value="American Express"/> + <menuitem label="&staff.patron.bill_cc_info.discover.label;" value="Discover"/> + <menuitem label="&staff.patron.bill_cc_info.other.label;" value="Other"/> + </menupopup> + </menulist> + </row> + <row id="row_approval_code"> + <label value="&staff.patron.bill_cc_info.approval_code.value;"/> + <textbox id="approval_code" context="clipboard"/> + </row> + <row id="row_cc_number"> + <label value="&staff.patron.bill_cc_info.cc_number.value;"/> + <textbox id="cc_number" context="clipboard"/> + </row> + <row id="row_expire_month"> + <label value="&staff.patron.bill_cc_info.month_expire.value;"/> + <textbox id="expire_month" context="clipboard"/> + </row> + <row id="row_expire_year"> + <label value="&staff.patron.bill_cc_info.year_expire.value;"/> + <textbox id="expire_year" context="clipboard"/> + </row> + <row id="row_note"> + <label value="&staff.patron.bill_cc_info.note.value;"/> + <textbox id="note" multiline="true" context="clipboard"/> + </row> + </rows> + </grid> + <hbox> + <spacer flex="1"/> + <button label="&staff.patron.bill_cc_info.cancel.label;" oncommand="window.close()" accesskey="&staff.patron.bill_cc_info.cancel.accesskey;"/> + <button label="&staff.patron.bill_cc_info.submit.label;" oncommand="if (sanity_check()) { info_finish(); window.close(); }" accesskey="&staff.patron.bill_cc_info.submit.accesskey;"/> + </hbox> + </groupbox> </window> -