diff options
author | Jonathan Prykop <jonathan@freeside.biz> | 2016-02-22 17:14:07 -0600 |
---|---|---|
committer | Jonathan Prykop <jonathan@freeside.biz> | 2016-02-22 17:14:07 -0600 |
commit | b1b3d6b3c0db38909b6f569e08877d2678587d22 (patch) | |
tree | 55ab377b72c5d2e3ebba9653024ceb23d75e3dda /FS/FS | |
parent | 308694b3b6219171858f336681f4b265327fdc78 (diff) |
RT#39586 Manual check refunds cannot be unapplied [source_paynum field, reason bug fixes, link text]
Diffstat (limited to 'FS/FS')
-rw-r--r-- | FS/FS/Schema.pm | 5 | ||||
-rw-r--r-- | FS/FS/cust_credit.pm | 2 | ||||
-rw-r--r-- | FS/FS/cust_main/Billing_Realtime.pm | 17 | ||||
-rw-r--r-- | FS/FS/cust_pay.pm | 4 | ||||
-rw-r--r-- | FS/FS/cust_refund.pm | 24 |
5 files changed, 37 insertions, 15 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 66575fa13..ff6a9241a 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -3061,6 +3061,7 @@ sub tables_hashref { 'paymask', 'varchar', 'NULL', $char_d, '', '', 'paybatch', 'varchar', 'NULL', $char_d, '', '', 'closed', 'char', 'NULL', 1, '', '', + 'source_paynum', 'int', 'NULL', '', '', '', # link to cust_payby, to prevent unapply of gateway-generated refunds # credit card/EFT fields (formerly in paybatch) 'gatewaynum', 'int', 'NULL', '', '', '', # payment_gateway FK 'processor', 'varchar', 'NULL', $char_d, '', '', # module name @@ -3083,6 +3084,10 @@ sub tables_hashref { { columns => [ 'gatewaynum' ], table => 'payment_gateway', }, + { columns => [ 'source_paynum' ], + table => 'cust_pay', + references => [ 'paynum' ], + }, ], }, diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm index a598b37a3..4be4b177a 100644 --- a/FS/FS/cust_credit.pm +++ b/FS/FS/cust_credit.pm @@ -1045,7 +1045,7 @@ sub refund_to_unapply { 'table' => 'cust_credit_refund', 'hashref' => { 'crednum' => $self->crednum }, 'addl_from' => 'LEFT JOIN cust_refund USING (refundnum)', - 'extra_sql' => "AND (cust_refund.closed = '' OR cust_refund.closed IS NULL)", + 'extra_sql' => "AND cust_refund.closed IS NULL AND cust_refund.source_paynum IS NULL", }); } diff --git a/FS/FS/cust_main/Billing_Realtime.pm b/FS/FS/cust_main/Billing_Realtime.pm index 3396ec4a0..747f4af5d 100644 --- a/FS/FS/cust_main/Billing_Realtime.pm +++ b/FS/FS/cust_main/Billing_Realtime.pm @@ -1323,14 +1323,14 @@ L<http://420.am/business-onlinepayment> for supported gateways. Available methods are: I<CC>, I<ECHECK> and I<LEC> -Available options are: I<amount>, I<reason>, I<paynum>, I<paydate> +Available options are: I<amount>, I<reasonnum>, I<paynum>, I<paydate> Most gateways require a reference to an original payment transaction to refund, so you probably need to specify a I<paynum>. I<amount> defaults to the original amount of the payment if not specified. -I<reason> specifies a reason for the refund. +I<reasonnum> specified an existing refund reason for the refund I<paydate> specifies the expiration date for a credit card overriding the value from the customer record or the payment record. Specified as yyyy-mm-dd @@ -1373,6 +1373,8 @@ sub realtime_refund_bop { warn " $_ => $options{$_}\n" foreach keys %options; } + return "No reason specified" unless $options{'reasonnum'} =~ /^\d+$/; + my %content = (); ### @@ -1531,7 +1533,12 @@ sub realtime_refund_bop { if $conf->exists('business-onlinepayment-test_transaction'); $void->submit(); if ( $void->is_success ) { - my $error = $cust_pay->void($options{'reason'}); + # specified as a refund reason, but now we want a payment void reason + # extract just the reason text, let cust_pay::void handle new_or_existing + my $reason = qsearchs('reason',{ 'reasonnum' => $options{'reasonnum'} }); + my $error; + $error = 'Reason could not be loaded' unless $reason; + $error = $cust_pay->void($reason->reason) unless $error; if ( $error ) { # gah, even with transactions. my $e = 'WARNING: Card/ACH voided but database not updated - '. @@ -1652,11 +1659,12 @@ sub realtime_refund_bop { my $cust_refund = new FS::cust_refund ( { 'custnum' => $self->custnum, 'paynum' => $options{'paynum'}, + 'source_paynum' => $options{'paynum'}, 'refund' => $amount, '_date' => '', 'payby' => $bop_method2payby{$options{method}}, 'payinfo' => $payinfo, - 'reason' => $options{'reason'} || 'card or ACH refund', + 'reasonnum' => $options{'reasonnum'}, 'gatewaynum' => $gatewaynum, # may be null 'processor' => $processor, 'auth' => $refund->authorization, @@ -1665,6 +1673,7 @@ sub realtime_refund_bop { my $error = $cust_refund->insert; if ( $error ) { $cust_refund->paynum(''); #try again with no specific paynum + $cust_refund->source_paynum(''); my $error2 = $cust_refund->insert; if ( $error2 ) { # gah, even with transactions. diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index af76b8990..620f6c629 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -444,7 +444,7 @@ sub void { unless (ref($reason) || !$reason) { $reason = FS::reason->new_or_existing( - 'class' => 'X', + 'class' => 'P', 'type' => 'Void payment', 'reason' => $reason ); @@ -920,7 +920,7 @@ sub refund_to_unapply { 'table' => 'cust_pay_refund', 'hashref' => { 'paynum' => $self->paynum }, 'addl_from' => 'LEFT JOIN cust_refund USING (refundnum)', - 'extra_sql' => "AND (cust_refund.closed = '' OR cust_refund.closed IS NULL)", + 'extra_sql' => "AND cust_refund.closed IS NULL AND cust_refund.source_paynum IS NULL", }); } diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm index efbdceeb0..ced954036 100644 --- a/FS/FS/cust_refund.pm +++ b/FS/FS/cust_refund.pm @@ -143,16 +143,23 @@ sub insert { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - unless ($self->reasonnum) { - my $result = $self->reason( $self->getfield('reason'), - exists($options{ 'reason_type' }) - ? ('reason_type' => $options{ 'reason_type' }) - : (), - ); - unless($result) { + if (!$self->reasonnum) { + my $reason_text = $self->get('reason') + or return "reason text or existing reason required"; + my $reason_type = $options{'reason_type'} + or return "reason type required"; + + local $@; + my $reason = FS::reason->new_or_existing( + reason => $reason_text, + type => $reason_type, + class => 'F', + ); + if ($@) { $dbh->rollback if $oldAutoCommit; - return "failed to set reason for $me"; #: ". $dbh->errstr; + return "failed to set refund reason: $@"; } + $self->set('reasonnum', $reason->reasonnum); } $self->setfield('reason', ''); @@ -303,6 +310,7 @@ sub check { || $self->ut_numbern('_date') || $self->ut_textn('paybatch') || $self->ut_enum('closed', [ '', 'Y' ]) + || $self->ut_foreign_keyn('source_paynum', 'cust_pay', 'paynum') ; return $error if $error; |