From 8c804ba59c8b284e1294e9928b5412fdf31e412c Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 14 Apr 2009 17:16:16 +0000 Subject: [PATCH] add configuration option to control recurring_flag behavior, RT#3843 --- FS/FS/Conf.pm | 7 +++ FS/FS/Schema.pm | 1 + FS/FS/agent.pm | 15 +++-- FS/FS/cust_main.pm | 154 +++++++++++++++++++++++++++++++-------------- 4 files changed, 125 insertions(+), 52 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 6403fb7bc..7be0dd0ca 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1671,6 +1671,13 @@ worry that config_items is freeside-specific and icky. ], }, + { + 'key' => 'credit_card-recurring_billing_acct_code', + 'section' => 'billing', + 'description' => 'When the "recurring billing" flag is set, also set the "acct_code" to "rebill". Useful for reporting purposes with supported gateways (PlugNPay, others?)', + 'type' => 'checkbox', + }, + { 'key' => 'cvv-save', 'section' => 'billing', diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index e4076b13d..c7bbf614c 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -847,6 +847,7 @@ sub tables_hashref { 'payinfo', 'varchar', 'NULL', 512, '', '', #see cust_main above 'paymask', 'varchar', 'NULL', $char_d, '', '', 'paydate', 'varchar', 'NULL', 10, '', '', + 'recurring_billing', 'varchar', 'NULL', $char_d, '', '', #'paybatch', 'varchar', 'NULL', $char_d, '', '', #for auditing purposes. 'payunique', 'varchar', 'NULL', $char_d, '', '', #separate paybatch "unique" functions from current usage diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm index e471e04a5..5fbe2c46d 100644 --- a/FS/FS/agent.pm +++ b/FS/FS/agent.pm @@ -225,16 +225,21 @@ sub payment_gateway { my $taxclass = ''; if ( $options{invnum} ) { + my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{invnum} } ); die "invnum ". $options{'invnum'}. " not found" unless $cust_bill; - my @taxclasses = - map { $_->part_pkg->taxclass } + + my @part_pkg = + map { $_->part_pkg } grep { $_ } map { $_->cust_pkg } $cust_bill->cust_bill_pkg; - unless ( grep { $taxclasses[0] ne $_ } @taxclasses ) { #unless there are - #different taxclasses $taxclass = $taxclasses[0]; - } + + my @taxclasses = map $_->taxclass, @part_pkg; + + $taxclass = $taxclasses[0] + unless grep { $taxclasses[0] ne $_ } @taxclasses; #unless there are + #different taxclasses } #look for an agent gateway override first diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 9aac1db7b..a62987b32 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3503,24 +3503,35 @@ sub realtime_bop { return "Banned credit card" if $ban; ### - # select a gateway + # set taxclass and trans_is_recur based on invnum if there is one ### my $taxclass = ''; + my $trans_is_recur = 0; if ( $options{'invnum'} ) { + my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{'invnum'} } ); die "invnum ". $options{'invnum'}. " not found" unless $cust_bill; - my @taxclasses = - map { $_->part_pkg->taxclass } + + my @part_pkg = + map { $_->part_pkg } grep { $_ } map { $_->cust_pkg } $cust_bill->cust_bill_pkg; - unless ( grep { $taxclasses[0] ne $_ } @taxclasses ) { #unless there are - #different taxclasses - $taxclass = $taxclasses[0]; - } + + my @taxclasses = map $_->taxclass, @part_pkg; + $taxclass = $taxclasses[0] + unless grep { $taxclasses[0] ne $_ } @taxclasses; #unless there are + #different taxclasses + $trans_is_recur = 1 + if grep { $_->freq ne '0' } @part_pkg; + } + ### + # select a gateway + ### + #look for an agent gateway override first my $cardtype; if ( $method eq 'CC' ) { @@ -3648,16 +3659,15 @@ sub realtime_bop { : $self->payissue; $content{issue_number} = $payissue if $payissue; - $content{recurring_billing} = 'YES' - if qsearch('cust_pay', { 'custnum' => $self->custnum, - 'payby' => 'CARD', - 'payinfo' => $payinfo, - } ) - || qsearch('cust_pay', { 'custnum' => $self->custnum, - 'payby' => 'CARD', - 'paymask' => $self->mask_payinfo('CARD', $payinfo), - } ); - + if ( $self->_bop_recurring_billing( 'payinfo' => $payinfo, + 'trans_is_recur' => $trans_is_recur, + ) + ) + { + $content{recurring_billing} = 'YES'; + $content{acct_code} = 'rebill' + if $conf->exists('credit_card-recurring_billing_acct_code'); + } } elsif ( $method eq 'ECHECK' ) { ( $content{account_number}, $content{routing_code} ) = @@ -3716,15 +3726,16 @@ sub realtime_bop { #okay, good to go, if we're a duplicate, cust_pay_pending will kick us out my $cust_pay_pending = new FS::cust_pay_pending { - 'custnum' => $self->custnum, - #'invnum' => $options{'invnum'}, - 'paid' => $amount, - '_date' => '', - 'payby' => $method2payby{$method}, - 'payinfo' => $payinfo, - 'paydate' => $paydate, - 'status' => 'new', - 'gatewaynum' => ( $payment_gateway ? $payment_gateway->gatewaynum : '' ), + 'custnum' => $self->custnum, + #'invnum' => $options{'invnum'}, + 'paid' => $amount, + '_date' => '', + 'payby' => $method2payby{$method}, + 'payinfo' => $payinfo, + 'paydate' => $paydate, + 'recurring_billing' => $content{recurring_billing}, + 'status' => 'new', + 'gatewaynum' => ( $payment_gateway ? $payment_gateway->gatewaynum : '' ), }; $cust_pay_pending->payunique( $options{payunique} ) if defined($options{payunique}) && length($options{payunique}); @@ -4010,6 +4021,34 @@ sub realtime_bop { } +sub _bop_recurring_billing { + my( $self, %opt ) = @_; + + my $method = $conf->config('credit_card-recurring_billing_flag'); + + if ( $method eq 'transaction_is_recur' ) { + + return 1 if $opt{'trans_is_recur'}; + + } else { + + my %hash = ( 'custnum' => $self->custnum, + 'payby' => 'CARD', + ); + + return 1 + if qsearch('cust_pay', { %hash, 'payinfo' => $opt{'payinfo'} } ) + || qsearch('cust_pay', { %hash, 'paymask' => $self->mask_payinfo('CARD', + $opt{'payinfo'} ) + } ); + + } + + return 0; + +} + + =item realtime_refund_bop METHOD [ OPTION => VALUE ... ] Refunds a realtime credit card, ACH (electronic check) or phone bill transaction @@ -4561,6 +4600,27 @@ sub _new_realtime_bop { $self->_bop_defaults(\%options); + ### + # set trans_is_recur based on invnum if there is one + ### + + my $trans_is_recur = 0; + if ( $options{'invnum'} ) { + + my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{'invnum'} } ); + die "invnum ". $options{'invnum'}. " not found" unless $cust_bill; + + my @part_pkg = + map { $_->part_pkg } + grep { $_ } + map { $_->cust_pkg } + $cust_bill->cust_bill_pkg; + + $trans_is_recur = 1 + if grep { $_->freq ne '0' } @part_pkg; + + } + ### # select a gateway ### @@ -4637,16 +4697,15 @@ sub _new_realtime_bop { : $self->payissue; $content{issue_number} = $payissue if $payissue; - $content{recurring_billing} = 'YES' - if qsearch('cust_pay', { 'custnum' => $self->custnum, - 'payby' => 'CARD', - 'payinfo' => $options{payinfo}, - } ) - || qsearch('cust_pay', { 'custnum' => $self->custnum, - 'payby' => 'CARD', - 'paymask' => $self->mask_payinfo('CARD', $options{payinfo}), - } ); - + if ( $self->_bop_recurring_billing( 'payinfo' => $options{'payinfo'}, + 'trans_is_recur' => $trans_is_recur, + ) + ) + { + $content{recurring_billing} = 'YES'; + $content{acct_code} = 'rebill' + if $conf->exists('credit_card-recurring_billing_acct_code'); + } } elsif ( $namespace eq 'Business::OnlinePayment' && $options{method} eq 'ECHECK' ){ ( $content{account_number}, $content{routing_code} ) = @@ -4708,17 +4767,18 @@ sub _new_realtime_bop { #okay, good to go, if we're a duplicate, cust_pay_pending will kick us out my $cust_pay_pending = new FS::cust_pay_pending { - 'custnum' => $self->custnum, - #'invnum' => $options{'invnum'}, - 'paid' => $options{amount}, - '_date' => '', - 'payby' => $bop_method2payby{$options{method}}, - 'payinfo' => $options{payinfo}, - 'paydate' => $paydate, - 'status' => 'new', - 'gatewaynum' => $payment_gateway->gatewaynum || '', - 'session_id' => $options{session_id} || '', - 'jobnum' => $options{depend_jobnum} || '', + 'custnum' => $self->custnum, + #'invnum' => $options{'invnum'}, + 'paid' => $options{amount}, + '_date' => '', + 'payby' => $bop_method2payby{$options{method}}, + 'payinfo' => $options{payinfo}, + 'paydate' => $paydate, + 'recurring_billing' => $content{recurring_billing}, + 'status' => 'new', + 'gatewaynum' => $payment_gateway->gatewaynum || '', + 'session_id' => $options{session_id} || '', + 'jobnum' => $options{depend_jobnum} || '', }; $cust_pay_pending->payunique( $options{payunique} ) if defined($options{payunique}) && length($options{payunique}); -- 2.20.1