add (unfinished) credit card surcharge, part 1
authorlevinse <levinse>
Fri, 21 Jan 2011 22:17:30 +0000 (22:17 +0000)
committerlevinse <levinse>
Fri, 21 Jan 2011 22:17:30 +0000 (22:17 +0000)
FS/FS/ClientAPI/MyAccount.pm
FS/FS/Conf.pm
FS/FS/cust_bill.pm
FS/FS/cust_main/Billing_Realtime.pm
FS/FS/part_event/Action/cust_bill_realtime_card.pm
fs_selfservice/FS-SelfService/cgi/make_payment.html
httemplate/misc/payment.cgi

index ad40b17..633d74d 100644 (file)
@@ -533,6 +533,8 @@ sub payment_info {
       'show_paystate' => $conf->exists('show_bankstate'),
 
       'save_unchecked' => $conf->exists('selfservice-save_unchecked'),
+
+      'credit_card_surcharge_percentage' => $conf->config('credit-card-surcharge-percentage'),
     };
 
   }
index d8321b9..fc7e5c8 100644 (file)
@@ -655,6 +655,13 @@ my %payment_gateway_options = (
   },
   
   {
+    'key'         => 'credit-card-surcharge-percentage',
+    'section'     => 'billing',
+    'description' => 'Add a credit card surcharge to invoices, as a % of the invoice total. WARNING: this is usually prohibited by merchant account / other agreements and/or law, but is currently lawful in AU and UK.',
+    'type'        => 'text',
+  },
+
+  {
     'key'         => 'discount-show-always',
     'section'     => 'billing',
     'description' => 'Generate a line item on an invoice even when a package is discounted 100%',
index f078342..62ab87f 100644 (file)
@@ -1958,7 +1958,8 @@ sub realtime_lec {
 }
 
 sub realtime_bop {
-  my( $self, $method ) = @_;
+  my( $self, $method ) = (shift,shift);
+  my %opt = @_;
 
   my $cust_main = $self->cust_main;
   my $balance = $cust_main->balance;
@@ -1987,6 +1988,7 @@ sub realtime_bop {
 #this didn't do what we want, it just calls apply_payments_and_credits
 #    'apply'       => 1,
     'apply_to_invoice' => 1,
+    %opt,
  #what we want:
  #this changes application behavior: auto payments
                         #triggered against a specific invoice are now applied
index 10b898d..ea09379 100644 (file)
@@ -19,7 +19,7 @@ $realtime_bop_decline_quiet = 0;
 # 1 is mostly method/subroutine entry and options
 # 2 traces progress of some operations
 # 3 is even more information including possibly sensitive data
-$DEBUG = 0;
+$DEBUG = 1;
 $me = '[FS::cust_main::Billing_Realtime]';
 
 install_callback FS::UID sub { 
@@ -186,6 +186,13 @@ sub _payment_gateway {
     }
   }
 
+  if ( $options->{'fake_gatewaynum'} ) {
+       $options->{payment_gateway} =
+           qsearchs('payment_gateway',
+                     { 'gatewaynum' => $options->{'fake_gatewaynum'}, }
+                   );
+  }
+
   $options->{payment_gateway} = $self->agent->payment_gateway( %$options )
     unless exists($options->{payment_gateway});
 
@@ -308,13 +315,39 @@ sub realtime_bop {
     $options{method} = $method;
     $options{amount} = $amount;
   }
+
+
+  ### 
+  # optional credit card surcharge
+  ###
+
+  my $cc_surcharge = 0;
+  my $cc_surcharge_pct = $conf->config('credit-card-surcharge-percentage');
   
+  # always add cc surcharge if called from event 
+  if($options{'cc_surcharge_from_event'} && $cc_surcharge_pct > 0) {
+      $cc_surcharge = $options{'amount'} * $cc_surcharge_pct / 100;
+      $options{'amount'} += $cc_surcharge;
+      $options{'amount'} = sprintf("%.2f", $options{'amount'}); # round (again)?
+  }
+  elsif($cc_surcharge_pct > 0) { # we're called not from event (i.e. from a 
+                                 # payment screen), so consider the given 
+                                # amount as post-surcharge
+    $cc_surcharge = $options{'amount'} - ($options{'amount'} / ( 1 + $cc_surcharge_pct/100 ));
+  }
+  if ( $cc_surcharge > 0) {
+      $cc_surcharge = sprintf("%.2f",$cc_surcharge);
+      $options{'cc_surcharge'} = $cc_surcharge;
+  }
+
   if ( $DEBUG ) {
     warn "$me realtime_bop (new): $options{method} $options{amount}\n";
+    warn " cc_surcharge = $cc_surcharge\n";
     warn "  $_ => $options{$_}\n" foreach keys %options;
   }
 
-  return $self->fake_bop(%options) if $options{'fake'};
+  return $self->fake_bop(\%options) if $options{'fake'};
 
   $self->_bop_defaults(\%options);
 
@@ -709,6 +742,11 @@ sub fake_bop {
   } );
   $cust_pay->payunique( $options{payunique} ) if length($options{payunique});
 
+  if ( $DEBUG ) {
+      warn "fake_bop\n cust_pay: ". Dumper($cust_pay) . "\n options: ";
+      warn "  $_ => $options{$_}\n" foreach keys %options;
+  }
+
   my $error = $cust_pay->insert($options{'manual'} ? ( 'manual' => 1 ) : () );
 
   if ( $error ) {
@@ -872,6 +910,60 @@ sub _realtime_bop_result {
         }
       }
 
+      # have a CC surcharge portion --> one-time charge
+      if ( $options{'cc_surcharge'} > 0 ) { 
+         my $invnum;
+         $invnum = $options{'invnum'} if $options{'invnum'};
+         unless ( $invnum ) { # probably from a payment screen
+            # do we have any open invoices? pick earliest
+            # uses the fact that cust_main->cust_bill sorts by date ascending
+            my @open = $self->open_cust_bill;
+            $invnum = $open[0]->invnum if scalar(@open);
+         }
+           
+         unless ( $invnum ) {  # still nothing? pick last closed invoice
+            # again uses fact that cust_main->cust_bill sorts by date ascending
+            my @closed = $self->cust_bill;
+            $invnum = $closed[$#closed]->invnum if scalar(@closed);
+         }
+
+         unless ( $invnum ) {
+           # XXX: unlikely case - pre-paying before any invoices generated
+           # what it should do is create a new invoice and pick it
+               warn 'CC SURCHARGE AND NO INVOICES PICKED TO APPLY IT!';
+               return '';
+         }
+
+         my $cust_pkg;
+         my $charge_error = $self->charge({
+                                   'amount'    => $options{'cc_surcharge'},
+                                   'pkg'       => 'Credit Card Surcharge',
+                                   'setuptax'  => 'Y',
+                                   'cust_pkg_ref' => \$cust_pkg,
+                               });
+         if($charge_error) {
+               warn 'Unable to add CC surcharge';
+               return '';
+         }
+                                   
+         my $cust_bill_pkg = new FS::cust_bill_pkg({
+           'invnum' => $invnum,
+           'pkgnum' => $cust_pkg->pkgnum,
+           'setup' => $options{'cc_surcharge'},
+         });
+         my $cbp_error = $cust_bill_pkg->insert;
+
+         if ( $cbp_error) {
+               warn 'Cannot add CC surcharge line item to invoice #'.$invnum;
+               return '';
+         } else {
+               my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum });
+               warn 'invoice for cc surcharge: ' . Dumper($cust_bill) if $DEBUG;
+               $cust_bill->apply_payments_and_credits;
+         }
+
+      }
+
       return ''; #no error
 
     }
index c1fdba9..1a2d046 100644 (file)
@@ -22,7 +22,8 @@ sub do_action {
   #my $cust_main = $self->cust_main($cust_bill);
   my $cust_main = $cust_bill->cust_main;
 
-  $cust_bill->realtime_card;
+  my %opt = ('cc_surcharge_from_event' => 1);
+  $cust_bill->realtime_card(%opt);
 }
 
 1;
index 645b68e..3bce674 100644 (file)
   <TH ALIGN="right">Payment&nbsp;amount</TH>
   <TD COLSPAN=7>
     <TABLE><TR><TD BGCOLOR="#ffffff">
-      $<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<%=sprintf("%.2f",$balance)%>">
+<%=
+    $amt = $balance;
+    $amt += $amt * $credit_card_surcharge_percentage/100
+       if $credit_card_surcharge_percentage > 0;
+    '';
+%>
+      $<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<%=sprintf("%.2f",$amt)%>">
     </TD></TR></TABLE>
   </TD>
 </TR>
index bcab68a..aec68af 100644 (file)
@@ -332,6 +332,10 @@ if ( $balance > 0 ) {
   $amount = $balance;
   $amount += $fee
     if $fee && $fee_display eq 'subtract';
+
+  my $cc_surcharge_pct = $conf->config('credit-card-surcharge-percentage');
+  $amount += $amount * $cc_surcharge_pct/100 if $cc_surcharge_pct > 0;
+
   $amount = sprintf("%.2f", $amount);
 }