projects
/
freeside.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
308694b
)
RT#39586 Manual check refunds cannot be unapplied [source_paynum field, reason bug...
author
Jonathan Prykop
<jonathan@freeside.biz>
Mon, 22 Feb 2016 23:14:07 +0000
(17:14 -0600)
committer
Jonathan Prykop
<jonathan@freeside.biz>
Mon, 22 Feb 2016 23:14:07 +0000
(17:14 -0600)
FS/FS/Schema.pm
patch
|
blob
|
history
FS/FS/cust_credit.pm
patch
|
blob
|
history
FS/FS/cust_main/Billing_Realtime.pm
patch
|
blob
|
history
FS/FS/cust_pay.pm
patch
|
blob
|
history
FS/FS/cust_refund.pm
patch
|
blob
|
history
httemplate/edit/process/cust_refund.cgi
patch
|
blob
|
history
httemplate/view/cust_main/payment_history/credit.html
patch
|
blob
|
history
httemplate/view/cust_main/payment_history/payment.html
patch
|
blob
|
history
diff --git
a/FS/FS/Schema.pm
b/FS/FS/Schema.pm
index
66575fa
..
ff6a924
100644
(file)
--- 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, '', '',
'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
# 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 => [ '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
a598b37
..
4be4b17
100644
(file)
--- 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)',
'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
3396ec4
..
747f4af
100644
(file)
--- 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 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<reason
num
>, 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.
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<reason
num> 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
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;
}
warn " $_ => $options{$_}\n" foreach keys %options;
}
+ return "No reason specified" unless $options{'reasonnum'} =~ /^\d+$/;
+
my %content = ();
###
my %content = ();
###
@@
-1531,7
+1533,12
@@
sub realtime_refund_bop {
if $conf->exists('business-onlinepayment-test_transaction');
$void->submit();
if ( $void->is_success ) {
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 - '.
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'},
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,
'refund' => $amount,
'_date' => '',
'payby' => $bop_method2payby{$options{method}},
'payinfo' => $payinfo,
- 'reason
' => $options{'reason'} || 'card or ACH refund'
,
+ 'reason
num' => $options{'reasonnum'}
,
'gatewaynum' => $gatewaynum, # may be null
'processor' => $processor,
'auth' => $refund->authorization,
'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
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.
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
af76b89
..
620f6c6
100644
(file)
--- 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(
unless (ref($reason) || !$reason) {
$reason = FS::reason->new_or_existing(
- 'class' => '
X
',
+ 'class' => '
P
',
'type' => 'Void payment',
'reason' => $reason
);
'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)',
'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
efbdcee
..
ced9540
100644
(file)
--- 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;
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;
$dbh->rollback if $oldAutoCommit;
- return "failed to set re
ason for $me"; #: ". $dbh->errstr
;
+ return "failed to set re
fund reason: $@"
;
}
}
+ $self->set('reasonnum', $reason->reasonnum);
}
$self->setfield('reason', '');
}
$self->setfield('reason', '');
@@
-303,6
+310,7
@@
sub check {
|| $self->ut_numbern('_date')
|| $self->ut_textn('paybatch')
|| $self->ut_enum('closed', [ '', 'Y' ])
|| $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;
;
return $error if $error;
diff --git
a/httemplate/edit/process/cust_refund.cgi
b/httemplate/edit/process/cust_refund.cgi
index
6ad468b
..
8977ced
100755
(executable)
--- a/
httemplate/edit/process/cust_refund.cgi
+++ b/
httemplate/edit/process/cust_refund.cgi
@@
-47,12
+47,11
@@
if ( $error ) {
my $refund = "$1$2";
$cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!";
my $paynum = $1;
my $refund = "$1$2";
$cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!";
my $paynum = $1;
- my $reason = $cgi->param('reason');
my $paydate = $cgi->param('exp_year'). '-'. $cgi->param('exp_month'). '-01';
$options{'paydate'} = $paydate if $paydate =~ /^\d{2,4}-\d{1,2}-01$/;
$error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund,
'paynum' => $paynum,
my $paydate = $cgi->param('exp_year'). '-'. $cgi->param('exp_month'). '-01';
$options{'paydate'} = $paydate if $paydate =~ /^\d{2,4}-\d{1,2}-01$/;
$error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund,
'paynum' => $paynum,
- 'reason
' => $reason
,
+ 'reason
num' => scalar($cgi->param('reasonnum'))
,
%options );
} else {
my %hash = map {
%options );
} else {
my %hash = map {
diff --git
a/httemplate/view/cust_main/payment_history/credit.html
b/httemplate/view/cust_main/payment_history/credit.html
index
85911a0
..
da8ca2e
100644
(file)
--- a/
httemplate/view/cust_main/payment_history/credit.html
+++ b/
httemplate/view/cust_main/payment_history/credit.html
@@
-45,7
+45,7
@@
if ( scalar(@cust_credit_bill) == 0
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
- 'label' => emt('apply
to
refund'),
+ 'label' => emt('apply refund'),
'action' => "${p}edit/cust_credit_refund.cgi?".
$cust_credit->crednum,
'actionlabel' => emt('Apply credit to refund'),
'action' => "${p}edit/cust_credit_refund.cgi?".
$cust_credit->crednum,
'actionlabel' => emt('Apply credit to refund'),
@@
-100,7
+100,7
@@
if ( scalar(@cust_credit_bill) == 0
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
- 'label' => emt('apply
to
refund'),
+ 'label' => emt('apply refund'),
'action' => "${p}edit/cust_credit_refund.cgi?".
$cust_credit->crednum,
'actionlabel' => emt('Apply credit to refund'),
'action' => "${p}edit/cust_credit_refund.cgi?".
$cust_credit->crednum,
'actionlabel' => emt('Apply credit to refund'),
@@
-141,20
+141,18
@@
$void = ' ('.
my $unapply = '';
if ($opt{'Unapply credit'} && !$cust_credit->closed) {
my $unapply = '';
if ($opt{'Unapply credit'} && !$cust_credit->closed) {
- my $refund_to_unapply = $cust_credit->refund_to_unapply;
- my $usepre = $refund_to_unapply && @cust_credit_bill;
$unapply = areyousure_link("${p}misc/unapply-cust_credit.cgi?".$cust_credit->crednum,
emt('Are you sure you want to unapply this credit from invoices?'),
emt('Keep this credit, but dissociate it from the invoices it is currently applied against'),
$unapply = areyousure_link("${p}misc/unapply-cust_credit.cgi?".$cust_credit->crednum,
emt('Are you sure you want to unapply this credit from invoices?'),
emt('Keep this credit, but dissociate it from the invoices it is currently applied against'),
- emt('unapply')
. ($usepre ? ' ' . emt('invoices') : '')
+ emt('unapply')
)
if @cust_credit_bill;
$unapply .= areyousure_link("${p}misc/unapply-cust_credit_refund.cgi?".$cust_credit->crednum,
emt('Are you sure you want to unapply this credit from refunds?'),
emt('Keep this credit, but dissociate it from the refunds it is currently applied to'),
)
if @cust_credit_bill;
$unapply .= areyousure_link("${p}misc/unapply-cust_credit_refund.cgi?".$cust_credit->crednum,
emt('Are you sure you want to unapply this credit from refunds?'),
emt('Keep this credit, but dissociate it from the refunds it is currently applied to'),
- emt('unapply
') . ($usepre ? ' ' . emt('refunds') : '
')
+ emt('unapply
refunds
')
)
)
- if $refund_to_unapply;
+ if $
cust_credit->
refund_to_unapply;
}
my $reason = $cust_credit->reason;
}
my $reason = $cust_credit->reason;
diff --git
a/httemplate/view/cust_main/payment_history/payment.html
b/httemplate/view/cust_main/payment_history/payment.html
index
16b91c2
..
8faed3c
100644
(file)
--- a/
httemplate/view/cust_main/payment_history/payment.html
+++ b/
httemplate/view/cust_main/payment_history/payment.html
@@
-103,7
+103,7
@@
if ($unapplied > 0) {
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
if ( $opt{total_unapplied_refunds} > 0 ) {
$apply.= ' ('.
include( '/elements/popup_link.html',
- 'label' => emt('apply
to
refund'),
+ 'label' => emt('apply refund'),
'action' => "${p}edit/cust_pay_refund.cgi?".
$cust_pay->paynum,
'actionlabel' => emt('Apply payment to refund'),
'action' => "${p}edit/cust_pay_refund.cgi?".
$cust_pay->paynum,
'actionlabel' => emt('Apply payment to refund'),
@@
-198,20
+198,18
@@
$void = ' ('.
my $unapply = '';
if ($opt{'Unapply payment'} && !$cust_pay->closed) {
my $unapply = '';
if ($opt{'Unapply payment'} && !$cust_pay->closed) {
- my $refund_to_unapply = $cust_pay->refund_to_unapply;
- my $usepre = $refund_to_unapply && @cust_bill_pay;
$unapply = areyousure_link("${p}misc/unapply-cust_pay.cgi?".$cust_pay->paynum,
emt('Are you sure you want to unapply this payment from invoices?'),
emt('Keep this payment, but dissociate it from the invoices it is currently applied against'),
$unapply = areyousure_link("${p}misc/unapply-cust_pay.cgi?".$cust_pay->paynum,
emt('Are you sure you want to unapply this payment from invoices?'),
emt('Keep this payment, but dissociate it from the invoices it is currently applied against'),
- emt('unapply')
. ($usepre ? ' ' . emt('invoices') : '')
+ emt('unapply')
)
if @cust_bill_pay;
$unapply .= areyousure_link("${p}misc/unapply-cust_pay_refund.cgi?".$cust_pay->paynum,
emt('Are you sure you want to unapply this payment from refunds?'),
emt('Keep this payment, but dissociate it from the refunds it is currently applied to'),
)
if @cust_bill_pay;
$unapply .= areyousure_link("${p}misc/unapply-cust_pay_refund.cgi?".$cust_pay->paynum,
emt('Are you sure you want to unapply this payment from refunds?'),
emt('Keep this payment, but dissociate it from the refunds it is currently applied to'),
- emt('unapply
') . ($usepre ? ' ' . emt('refunds') : '
')
+ emt('unapply
refunds
')
)
)
- if $refund_to_unapply;
+ if $
cust_pay->
refund_to_unapply;
}
</%init>
}
</%init>