[open-ils-commits] r14628 - in trunk/Open-ILS: examples src/extras src/perlmods/OpenILS/Application src/perlmods/OpenILS/Application/Circ src/sql/Pg src/sql/Pg/upgrade web/opac/locale/en-US xul/staff_client/server/locale/en-US xul/staff_client/server/patron (erickson)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Oct 27 10:44:23 EDT 2009


Author: erickson
Date: 2009-10-27 10:44:20 -0400 (Tue, 27 Oct 2009)
New Revision: 14628

Added:
   trunk/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql
Modified:
   trunk/Open-ILS/examples/fm_IDL.xml
   trunk/Open-ILS/src/extras/ils_events.xml
   trunk/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm
   trunk/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
   trunk/Open-ILS/src/sql/Pg/002.schema.config.sql
   trunk/Open-ILS/src/sql/Pg/080.schema.money.sql
   trunk/Open-ILS/web/opac/locale/en-US/lang.dtd
   trunk/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
   trunk/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul
Log:

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




Modified: trunk/Open-ILS/examples/fm_IDL.xml
===================================================================
--- trunk/Open-ILS/examples/fm_IDL.xml	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/examples/fm_IDL.xml	2009-10-27 14:44:20 UTC (rev 14628)
@@ -1294,6 +1294,7 @@
 			<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" />

Modified: trunk/Open-ILS/src/extras/ils_events.xml
===================================================================
--- trunk/Open-ILS/src/extras/ils_events.xml	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/src/extras/ils_events.xml	2009-10-27 14:44:20 UTC (rev 14628)
@@ -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'>

Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/Circ/Money.pm	2009-10-27 14:44:20 UTC (rev 14628)
@@ -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::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 @@
                     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 @@
         ]
     }
 );
-
 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 @@
 
     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 } );
-			}
-		}
+                return OpenILS::Event->new(
+                    'REFUND_EXCEEDS_DESK_PAYMENTS', 
+                    payload => { allowed_refund => $desk_total, submitted_refund => -$amount } );
+            }
+        }
 
-		my $payobj = "Fieldmapper::money::$type";
-		$payobj = $payobj->new;
+        my $payobj = "Fieldmapper::money::$type";
+        $payobj = $payobj->new;
 
-		$payobj->amount($amount);
-		$payobj->amount_collected($amount);
-		$payobj->xact($transid);
-		$payobj->note($note);
+        $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});
+        }
 
-		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); }
+        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 ) {
+        # 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.
 
-			# Any overpay on this transaction goes directly into patron credit 
-			$cred = -$cred;
-			$credit += $cred;
-            my $circ = $e->retrieve_action_circulation($transid);
+        push(@payment_objs, $payobj);
 
-			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;
-			}
-		}
+    } # all payment objects have been created and inserted. 
 
-        my $method = "create_money_$type";
-        $e->$method($payobj) or return $e->die_event;
-        push(@payment_objs, $payobj);
+    #### NO WRITES TO THE DB ABOVE THIS LINE -- THEY'LL ONLY BE DISCARDED  ###
+    $e->rollback;
 
-	} # all payment objects have been created and inserted. 
+    # 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') {
+        $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
+                }
+            );
 
-	my $evt = _update_patron_credit($e, $patron, $credit);
-	return $evt if $evt;
-
-    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;
+            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($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
+    ### 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 (exists $response->{ilsevent}) {
+        $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;
-            return $response;
+            return OpenILS::Event->new(
+                'CREDIT_PROCESSOR_SUCCESS_WO_RECORD',
+                note => "$create_money_method failed"
+            );
         }
-        if ($response->{statusCode} != 200) {
+    }
+
+    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;
-            $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 => "OpenILS::Utils::Penalty::calculate_penalties() failed"
             );
         }
-
-        for my $payment (@payment_objs) {
-            $payment->approval_code($response->{approvalCode});
-            $e->update_money_credit_card_payment($payment) or return $e->die_event;
-        }
-        $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( $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 $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 );
-	}
+    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;
+    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( $self, $client, $login, $transid ) = @_;
 
-	my( $trans, $evt ) = $U->fetch_billable_xact($transid);
-	return $evt if $evt;
+    my( $trans, $evt ) = $U->fetch_billable_xact($transid);
+    return $evt if $evt;
 
-	my $staff;
-	($staff, $evt ) = $apputils->checkses($login);
-	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 } )
+    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 @@
             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 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);
+    # 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 )) {
+    # 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;
-	}
+        $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;
+    # 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 );
+    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;
+    $_->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;
-
-
-

Modified: trunk/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm
===================================================================
--- trunk/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/src/perlmods/OpenILS/Application/CreditCard.pm	2009-10-27 14:44:20 UTC (rev 14628)
@@ -265,6 +265,8 @@
 
         my $retval = {
             statusText => "Transaction approved: " . $transaction->authorization,
+            processor => $argshash->{processor},
+            cardType => $cardtype,
             statusCode => 200,
             approvalCode => $transaction->authorization,
             server_response => $transaction->server_response

Modified: trunk/Open-ILS/src/sql/Pg/002.schema.config.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/002.schema.config.sql	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/src/sql/Pg/002.schema.config.sql	2009-10-27 14:44:20 UTC (rev 14628)
@@ -51,9 +51,8 @@
     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,
 	quality		INT	CHECK ( quality BETWEEN 0 AND 100 ),

Modified: trunk/Open-ILS/src/sql/Pg/080.schema.money.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/080.schema.money.sql	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/src/sql/Pg/080.schema.money.sql	2009-10-27 14:44:20 UTC (rev 14628)
@@ -619,6 +619,7 @@
 CREATE TABLE money.credit_card_payment (
 	cc_type		TEXT,
 	cc_number	TEXT,
+    cc_processor TEXT,
 	expire_month	INT,
 	expire_year	INT,
 	approval_code	TEXT

Added: trunk/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql
===================================================================
--- trunk/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql	                        (rev 0)
+++ trunk/Open-ILS/src/sql/Pg/upgrade/0057.mccp_processor_column.sql	2009-10-27 14:44:20 UTC (rev 14628)
@@ -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;

Modified: trunk/Open-ILS/web/opac/locale/en-US/lang.dtd
===================================================================
--- trunk/Open-ILS/web/opac/locale/en-US/lang.dtd	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/web/opac/locale/en-US/lang.dtd	2009-10-27 14:44:20 UTC (rev 14628)
@@ -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">

Modified: trunk/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties
===================================================================
--- trunk/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/xul/staff_client/server/locale/en-US/patron.properties	2009-10-27 14:44:20 UTC (rev 14628)
@@ -10,6 +10,8 @@
 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:

Modified: trunk/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul
===================================================================
--- trunk/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul	2009-10-27 12:42:08 UTC (rev 14627)
+++ trunk/Open-ILS/xul/staff_client/server/patron/bill_cc_info.xul	2009-10-27 14:44:20 UTC (rev 14628)
@@ -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 type="text/javascript" src="/xul/server/main/JSAN.js"/>
 
-    <script>
-    <![CDATA[
-        function $(id) { return document.getElementById(id); }
+	<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');
+        XULElement.prototype.hide = function() {
+            this.style.display = "none";
+        }
+        XULElement.prototype.reveal = function() {
+            this.style.display = "";
+        }
 
-            document.getElementById('cc_number').focus();
+        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 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 refresh_fields() {
+            for (var field in fields_of_interest) {
+                if (is_relevant_here(field)) {
+                    $('row_' + field).reveal();
+                }
+                else {
+                    $('row_' + field).hide();
+                }
+            }
         }
 
-    ]]>
-    </script>
+		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');
 
-    <messagecatalog id="patronStrings" src="/xul/server/locale/<!--#echo var='locale'-->/patron.properties" />
+			document.getElementById('cc_number').focus();
+		}
 
-    <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 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;
+        }
 
+		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>
 
-



More information about the open-ils-commits mailing list