RT# 82137 - Added ability for processing fee to be pain on seperate invoice.
authorChristopher Burger <burgerc@freeside.biz>
Mon, 24 Jun 2019 17:27:17 +0000 (13:27 -0400)
committerChristopher Burger <burgerc@freeside.biz>
Mon, 24 Jun 2019 17:27:17 +0000 (13:27 -0400)
FS/FS/Conf.pm
FS/FS/cust_main/Billing_Realtime.pm
FS/FS/cust_pay.pm
httemplate/config/config-process.cgi
httemplate/elements/tr-amount_fee.html
httemplate/elements/tr-select-payment_options.html

index 0f774d1..9e68ffc 100644 (file)
@@ -2683,6 +2683,17 @@ and customer address. Include units.',
   },
 
   {
   },
 
   {
+    'key'         => 'processing-fee_on_separate_invoice',
+    'section'     => 'payments',
+    'description' => 'Places the processing fee on a separate invoice by itself.  Only works with real time processing.',
+    'type'        => 'checkbox',
+    'validate'    => sub {
+                        my $conf = new FS::Conf;
+                        !$conf->config('batch-enable_payby') ? '' : 'You can not set this option while batch processing is enabled.';
+                     },
+  },
+
+  {
     'key'         => 'banned_pay-pad',
     'section'     => 'credit_cards',
     'description' => 'Padding for encrypted storage of banned credit card hashes.  If you already have new-style SHA512 entries in the banned_pay table, do not change as this will invalidate the old entries.',
     'key'         => 'banned_pay-pad',
     'section'     => 'credit_cards',
     'description' => 'Padding for encrypted storage of banned credit card hashes.  If you already have new-style SHA512 entries in the banned_pay table, do not change as this will invalidate the old entries.',
@@ -3840,6 +3851,11 @@ and customer address. Include units.',
     'description' => 'Enable batch processing for the specified payment types.',
     'type'        => 'selectmultiple',
     'select_enum' => [qw( CARD CHEK )],
     'description' => 'Enable batch processing for the specified payment types.',
     'type'        => 'selectmultiple',
     'select_enum' => [qw( CARD CHEK )],
+    'validate'    => sub {
+                        ## can not create a new invoice and pay it silently with batch processing, only realtime processing.
+                        my $conf = new FS::Conf;
+                        !$conf->exists('processing-fee_on_separate_invoice') ? '' : 'You can not enable batch processing while processing-fee_on_separate_invoice option is enabled.';
+                     },
   },
 
   {
   },
 
   {
index 89d63dd..b65860e 100644 (file)
@@ -985,17 +985,20 @@ sub _realtime_bop_result {
     savepoint_create( $savepoint_label );
 
     #start a transaction, insert the cust_pay and set cust_pay_pending.status to done in a single transction
     savepoint_create( $savepoint_label );
 
     #start a transaction, insert the cust_pay and set cust_pay_pending.status to done in a single transction
-
-    my $error = $cust_pay->insert($options{'manual'} ? ( 'manual' => 1 ) : () );
+    my $error = $cust_pay->insert(
+      $options{'manual'} ? ( 'manual' => 1 ) : (),
+      $options{'processing-fee'} > 0 ? ( 'processing-fee' => $options{'processing-fee'} ) : (),
+    );
 
     if ( $error ) {
       savepoint_rollback( $savepoint_label );
 
       $cust_pay->invnum(''); #try again with no specific invnum
       $cust_pay->paynum('');
 
     if ( $error ) {
       savepoint_rollback( $savepoint_label );
 
       $cust_pay->invnum(''); #try again with no specific invnum
       $cust_pay->paynum('');
-      my $error2 = $cust_pay->insert( $options{'manual'} ?
-                                      ( 'manual' => 1 ) : ()
-                                    );
+      my $error2 = $cust_pay->insert(
+        $options{'manual'} ? ( 'manual' => 1 ) : (),
+        $options{'processing-fee'} > 0 ? ( 'processing-fee' => $options{'processing-fee'} ) : (),
+      );
       if ( $error2 ) {
         # gah.  but at least we have a record of the state we had to abort in
         # from cust_pay_pending now.
       if ( $error2 ) {
         # gah.  but at least we have a record of the state we had to abort in
         # from cust_pay_pending now.
@@ -1137,11 +1140,23 @@ sub _realtime_bop_result {
     if ($options{'processing-fee'} > 0) {
       my $pf_cust_pkg;
       my $processing_fee_text = 'Payment Processing Fee';
     if ($options{'processing-fee'} > 0) {
       my $pf_cust_pkg;
       my $processing_fee_text = 'Payment Processing Fee';
+
+      my $conf = new FS::Conf;
+
+      my $pf_seperate_bill;
+      my $pf_bill_now;
+      if ($conf->exists('processing-fee_on_separate_invoice')) {
+        $pf_seperate_bill = 'Y';
+        $pf_bill_now = '1';
+      }
+
       my $pf_change_error = $self->charge({
             'amount'  => $options{'processing-fee'},
             'pkg'   => $processing_fee_text,
             'setuptax'  => 'Y',
             'cust_pkg_ref' => \$pf_cust_pkg,
       my $pf_change_error = $self->charge({
             'amount'  => $options{'processing-fee'},
             'pkg'   => $processing_fee_text,
             'setuptax'  => 'Y',
             'cust_pkg_ref' => \$pf_cust_pkg,
+            'separate_bill' => $pf_seperate_bill,
+            'bill_now' => $pf_bill_now,
       });
 
       if($pf_change_error) {
       });
 
       if($pf_change_error) {
@@ -1156,17 +1171,41 @@ sub _realtime_bop_result {
         # but keep going...
       }
 
         # but keep going...
       }
 
-      my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum });
-      unless ( $cust_bill ) {
-        warn "race condition + invoice deletion just happened";
-        return '';
-      }
+      if ($conf->exists('processing-fee_on_separate_invoice')) {
+        my $cust_bill_pkg = qsearchs( 'cust_bill_pkg', { 'pkgnum' => $pf_cust_pkg->pkgnum } );
+
+        my $pf_cust_bill = qsearchs('cust_bill', { 'invnum' => $cust_bill_pkg->invnum });
+        unless ( $pf_cust_bill ) {
+          warn "no processing fee inv found!";
+          return '';
+        }
+
+        my $pf_apply_error = $pf_cust_bill->apply_payments_and_credits;
+
+        my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum });
+        unless ( $cust_bill ) {
+          warn "race condition + invoice deletion just happened";
+         return '';
+        }
+
+        my $grand_pf_error = $cust_bill->apply_payments_and_credits;
+
+        warn "cannot apply Processing fee to invoice #$invnum: $grand_pf_error - $pf_apply_error"
+          if $grand_pf_error || $pf_apply_error;
+      } ## processing-fee_on_separate_invoice
+      else {
+        my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum });
+        unless ( $cust_bill ) {
+          warn "race condition + invoice deletion just happened";
+          return '';
+        }
 
 
-      my $grand_pf_error =
-        $cust_bill->add_cc_surcharge($pf_cust_pkg->pkgnum,$options{'processing-fee'});
+        my $grand_pf_error =
+          $cust_bill->add_cc_surcharge($pf_cust_pkg->pkgnum,$options{'processing-fee'});
 
 
-      warn "cannot add Processing fee to invoice #$invnum: $grand_pf_error"
-        if $grand_pf_error;
+        warn "cannot add Processing fee to invoice #$invnum: $grand_pf_error"
+          if $grand_pf_error;
+      } ## no processing-fee_on_separate_invoice
     } #end if $options{'processing-fee'}
 
       } #end if ( $options{'cc_surcharge'} > 0 || $options{'processing-fee'} > 0)
     } #end if $options{'processing-fee'}
 
       } #end if ( $options{'cc_surcharge'} > 0 || $options{'processing-fee'} > 0)
index 915cb33..c0a2541 100644 (file)
@@ -395,6 +395,8 @@ sub insert {
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
+  $self->{'processing_fee'} = $options{'processing-fee'};
+
   #payment receipt
   my $trigger = $conf->config('payment_receipt-trigger', 
                               $self->cust_main->agentnum) || 'cust_pay';
   #payment receipt
   my $trigger = $conf->config('payment_receipt-trigger', 
                               $self->cust_main->agentnum) || 'cust_pay';
@@ -735,6 +737,8 @@ sub send_message_receipt {
 
       my %substitutions = ();
       $substitutions{invnum} = $cust_bill->invnum if $cust_bill;
 
       my %substitutions = ();
       $substitutions{invnum} = $cust_bill->invnum if $cust_bill;
+      $substitutions{'processing_fee'} = $self->{'processing_fee'};
+
 
       my $msg_template = qsearchs('msg_template',{ msgnum => $msgnum});
       unless ($msg_template) {
 
       my $msg_template = qsearchs('msg_template',{ msgnum => $msgnum});
       unless ($msg_template) {
index d84edce..6af7d23 100644 (file)
@@ -155,7 +155,9 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
     }
   } elsif ( $type eq 'checkbox' ) {
     if ( defined $cgi->param($i->key.$n) ) {
     }
   } elsif ( $type eq 'checkbox' ) {
     if ( defined $cgi->param($i->key.$n) ) {
-      push @touch, $i->key;
+      my $error = &{$i->validate}('', $n) if $i->validate;
+      push @error, $error if $error;
+      push @touch, $i->key if !$error;
     } else {
       push @delete, $i->key;
     }
     } else {
       push @delete, $i->key;
     }
@@ -167,7 +169,7 @@ foreach my $type ( ref($i->type) ? @{$i->type} : $i->type ) {
     if ( scalar(@{[ $cgi->param($i->key.$n) ]}) && $cgi->param($i->key.$n) ne '' ) {
       my $error = &{$i->validate}([ $cgi->param($i->key.$n) ], $n) if $i->validate;
       push @error, $error if $error;
     if ( scalar(@{[ $cgi->param($i->key.$n) ]}) && $cgi->param($i->key.$n) ne '' ) {
       my $error = &{$i->validate}([ $cgi->param($i->key.$n) ], $n) if $i->validate;
       push @error, $error if $error;
-      $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum);
+      $conf->set($i->key, join("\n", @{[ $cgi->param($i->key.$n) ]} ), $agentnum) if !$error;
     } else {
       $conf->delete($i->key, $agentnum);
     }
     } else {
       $conf->delete($i->key, $agentnum);
     }
index 94795de..0ae6a0f 100644 (file)
@@ -44,7 +44,7 @@
         <TD>
           <TABLE><TR>
             <TD BGCOLOR="#ffffff">
         <TD>
           <TABLE><TR>
             <TD BGCOLOR="#ffffff">
-             <INPUT TYPE="checkbox" NAME="processing_fee" ID="processing_fee" VALUE="<% $processing_fee %>" onclick="<% $opt{prefix} %>process_fee_changed()">
+             <INPUT TYPE="checkbox" NAME="processing_fee" ID="processing_fee" VALUE="<% $processing_fee %>" onclick="<% $opt{prefix} %>process_fee_changed()" checked>
             </TD>
             <TD ID="ajax_processingfee_cell" BGCOLOR="#dddddd" STYLE="border:1px solid blue">
              <FONT SIZE="+1">A processing fee of <% $processing_fee %> is being applied to this transaction.</FONT>
             </TD>
             <TD ID="ajax_processingfee_cell" BGCOLOR="#dddddd" STYLE="border:1px solid blue">
              <FONT SIZE="+1">A processing fee of <% $processing_fee %> is being applied to this transaction.</FONT>
index c5b84e7..27df962 100644 (file)
@@ -60,7 +60,7 @@ Example:
 
       $('#payment_option_row').<% $payment_option_row %>();
       $('#payment_amount_row').<% $payment_amount_row %>();
 
       $('#payment_option_row').<% $payment_option_row %>();
       $('#payment_amount_row').<% $payment_amount_row %>();
-      $('#ajax_processingfee_cell').hide();
+      $('#ajax_processingfee_cell').show();
 
       if($('#payment_amount_row').is(':visible')) {
         var surcharge;
 
       if($('#payment_amount_row').is(':visible')) {
         var surcharge;