RT#39586 Manual check refunds cannot be unapplied
authorJonathan Prykop <jonathan@freeside.biz>
Fri, 5 Feb 2016 21:16:12 +0000 (15:16 -0600)
committerJonathan Prykop <jonathan@freeside.biz>
Fri, 5 Feb 2016 21:16:12 +0000 (15:16 -0600)
FS/FS/cust_credit.pm
FS/FS/cust_pay.pm
httemplate/misc/unapply-cust_credit_refund.cgi [new file with mode: 0755]
httemplate/misc/unapply-cust_pay_refund.cgi [new file with mode: 0755]
httemplate/view/cust_main/payment_history/credit.html
httemplate/view/cust_main/payment_history/payment.html

index 6b21d69..a598b37 100644 (file)
@@ -1028,6 +1028,58 @@ sub credit_lineitems {
 
 }
 
+### refund_to_unapply/unapply_refund false laziness with FS::cust_pay
+
+=item refund_to_unapply
+
+Returns L<FS::cust_credit_refund> objects that will be deleted by L</unapply_refund>
+(all currently applied refunds that aren't closed.)
+Returns empty list if credit itself is closed.
+
+=cut
+
+sub refund_to_unapply {
+  my $self = shift;
+  return () if $self->closed;
+  qsearch({
+    '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)",
+  });
+}
+
+=item unapply_refund
+
+Deletes all objects returned by L</refund_to_unapply>.
+
+=cut
+
+sub unapply_refund {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  foreach my $cust_credit_refund ($self->refund_to_unapply) {
+    my $error = $cust_credit_refund->delete;
+    if ($error) {
+      dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  dbh->commit or die dbh->errstr if $oldAutoCommit;
+  return '';
+}
+
 =back
 
 =head1 SUBROUTINES
index 4d06862..af76b89 100644 (file)
@@ -903,6 +903,58 @@ sub refund {
   return '';
 }
 
+### refund_to_unapply/unapply_refund false laziness with FS::cust_credit
+
+=item refund_to_unapply
+
+Returns L<FS::cust_pay_refund> objects that will be deleted by L</unapply_refund>
+(all currently applied refunds that aren't closed.)
+Returns empty list if payment itself is closed.
+
+=cut
+
+sub refund_to_unapply {
+  my $self = shift;
+  return () if $self->closed;
+  qsearch({
+    '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)",
+  });
+}
+
+=item unapply_refund
+
+Deletes all objects returned by L</refund_to_unapply>.
+
+=cut
+
+sub unapply_refund {
+  my $self = shift;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  foreach my $cust_pay_refund ($self->refund_to_unapply) {
+    my $error = $cust_pay_refund->delete;
+    if ($error) {
+      dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
+  dbh->commit or die dbh->errstr if $oldAutoCommit;
+  return '';
+}
+
 =back
 
 =head1 CLASS METHODS
@@ -990,7 +1042,7 @@ sub batch_insert {
 
 Returns an SQL fragment to retreive the unapplied amount.
 
-=cut 
+=cut
 
 sub unapplied_sql {
   my ($class, $start, $end) = @_;
diff --git a/httemplate/misc/unapply-cust_credit_refund.cgi b/httemplate/misc/unapply-cust_credit_refund.cgi
new file mode 100755 (executable)
index 0000000..55a81b0
--- /dev/null
@@ -0,0 +1,18 @@
+<% $cgi->redirect($p. "view/cust_main.cgi?custnum=". $custnum. ";show=payment_history") %>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Unapply credit');
+
+#untaint crednum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal crednum";
+my $crednum = $1;
+
+my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } );
+my $custnum = $cust_credit->custnum;
+
+my $error = $cust_credit->unapply_refund;
+errorpage($error) if $error;
+
+</%init>
diff --git a/httemplate/misc/unapply-cust_pay_refund.cgi b/httemplate/misc/unapply-cust_pay_refund.cgi
new file mode 100755 (executable)
index 0000000..9e470b6
--- /dev/null
@@ -0,0 +1,18 @@
+<% $cgi->redirect($p. "view/cust_main.cgi?custnum=". $custnum. ";show=payment_history") %>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Unapply payment');
+
+#untaint paynum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal paynum";
+my $paynum = $1;
+
+my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } );
+my $custnum = $cust_pay->custnum;
+
+my $error = $cust_pay->unapply_refund;
+errorpage($error) if $error;
+
+</%init>
index db2e5e5..85911a0 100644 (file)
@@ -139,14 +139,23 @@ $void = ' ('.
   && $opt{'Void credit'};
 
 my $unapply = '';
-$unapply = areyousure_link("${p}misc/unapply-cust_credit.cgi?".$cust_credit->crednum,
-                            emt('Are you sure you want to unapply this credit?'),
-                            '',
-                            emt('unapply')
-                          )
-  if $cust_credit->closed !~ /^Y/i
-  && scalar(@cust_credit_bill)
-  && $opt{'Unapply credit'};
+
+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'),
+                              emt('unapply') . ($usepre ? '&nbsp;' . emt('invoices') : '')
+                            )
+    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 ? '&nbsp;' . emt('refunds') : '')
+                             )
+    if $refund_to_unapply;
+}
 
 my $reason = $cust_credit->reason;
 $reason = $reason ? " ($reason)" : '';
index 6c93f7b..16b91c2 100644 (file)
@@ -197,13 +197,21 @@ $void = ' ('.
      );
 
 my $unapply = '';
-$unapply = areyousure_link("${p}misc/unapply-cust_pay.cgi?".$cust_pay->paynum,
-                            emt('Are you sure you want to unapply this payment?'),
-                            emt('Keep this payment, but dissociate it from the invoices it is currently applied against'),
-                            emt('unapply')
-                          )
-  if $cust_pay->closed !~ /^Y/i
-  && scalar(@cust_bill_pay)           
-  && $opt{'Unapply payment'};
+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'),
+                              emt('unapply') . ($usepre ? '&nbsp;' . emt('invoices') : '')
+                            )
+    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 ? '&nbsp;' . emt('refunds') : '')
+                             )
+    if $refund_to_unapply;
+}
 
 </%init>