diff options
-rw-r--r-- | FS/FS/Conf.pm | 8 | ||||
-rw-r--r-- | FS/FS/cust_main/Billing_Batch.pm | 35 | ||||
-rw-r--r-- | FS/FS/cust_main/Billing_Realtime.pm | 97 | ||||
-rw-r--r-- | httemplate/elements/tr-amount_fee.html | 26 | ||||
-rw-r--r-- | httemplate/elements/tr-select-payment_options.html | 40 | ||||
-rw-r--r-- | httemplate/misc/payment.cgi | 1 | ||||
-rw-r--r-- | httemplate/misc/process/payment.cgi | 4 |
7 files changed, 178 insertions, 33 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 733ed00..a2436aa 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -2671,6 +2671,14 @@ and customer address. Include units.', }, { + 'key' => 'processing-fee', + 'section' => 'payments', + 'description' => 'Fee for back end payment processing.', + 'type' => 'text', + 'per_agent' => 1, + }, + + { '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.', diff --git a/FS/FS/cust_main/Billing_Batch.pm b/FS/FS/cust_main/Billing_Batch.pm index 0774781..f771329 100644 --- a/FS/FS/cust_main/Billing_Batch.pm +++ b/FS/FS/cust_main/Billing_Batch.pm @@ -162,6 +162,41 @@ sub batch_card { return $error; # e.g. "Illegal zip" ala RT#75998 } + if ($options{'processing-fee'} > 0) { + my $pf_cust_pkg; + my $processing_fee_text = 'Payment Processing Fee'; + my $pf_change_error = $self->charge({ + 'amount' => $options{'processing-fee'}, + 'pkg' => $processing_fee_text, + 'setuptax' => 'Y', + 'cust_pkg_ref' => \$pf_cust_pkg, + }); + + if($pf_change_error) { + warn 'Unable to add payment processing fee'; + return ''; + } + + $pf_cust_pkg->setup(time); + my $pf_error = $pf_cust_pkg->replace; + if($pf_error) { + warn 'Unable to set setup time on cust_pkg for processing fee'; + # but keep going... + } + + 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'}); + + warn "cannot add Processing fee to invoice #$invnum: $grand_pf_error" + if $grand_pf_error; + } + my $unapplied = $self->total_unapplied_credits + $self->total_unapplied_payments + $self->in_transit_payments; diff --git a/FS/FS/cust_main/Billing_Realtime.pm b/FS/FS/cust_main/Billing_Realtime.pm index 64b551c..09f4d25 100644 --- a/FS/FS/cust_main/Billing_Realtime.pm +++ b/FS/FS/cust_main/Billing_Realtime.pm @@ -474,8 +474,8 @@ sub realtime_bop { elsif($cc_surcharge_pct > 0 || $cc_surcharge_flat > 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'} - $cc_surcharge_flat) / ( 1 + $cc_surcharge_pct/100 )) if $options{'amount'} > 0; + # amount as post-surcharge-processing_fee + $cc_surcharge = $options{'amount'} - $options{'processing-fee'} - (($options{'amount'} - ($cc_surcharge_flat + $options{'processing-fee'})) / ( 1 + $cc_surcharge_pct/100 )) if $options{'amount'} > 0; } $cc_surcharge = sprintf("%.2f",$cc_surcharge) if $cc_surcharge > 0; @@ -1061,7 +1061,7 @@ sub _realtime_bop_result { } # have a CC surcharge portion --> one-time charge - if ( $options{'cc_surcharge'} > 0 ) { + if ( $options{'cc_surcharge'} > 0 || $options{'processing-fee'} > 0) { # XXX: this whole block needs to be in a transaction? my $invnum; @@ -1082,44 +1082,83 @@ sub _realtime_bop_result { 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!'; + warn 'CC SURCHARGE OR PROCESS FEE AND NO INVOICES PICKED TO APPLY IT!'; return ''; } - my $cust_pkg; - my $cc_surcharge_text = 'Credit Card Surcharge'; - $cc_surcharge_text = $conf->config('credit-card-surcharge-text', $self->agentnum) if $conf->exists('credit-card-surcharge-text', $self->agentnum); - my $charge_error = $self->charge({ + if ($options{'cc_surcharge'} > 0) { + my $cust_pkg; + my $cc_surcharge_text = 'Credit Card Surcharge'; + $cc_surcharge_text = $conf->config('credit-card-surcharge-text', $self->agentnum) if $conf->exists('credit-card-surcharge-text', $self->agentnum); + my $charge_error = $self->charge({ 'amount' => $options{'cc_surcharge'}, 'pkg' => $cc_surcharge_text, 'setuptax' => 'Y', 'cust_pkg_ref' => \$cust_pkg, - }); - if($charge_error) { - warn 'Unable to add CC surcharge cust_pkg'; - return ''; - } + }); + + if($charge_error) { + warn 'Unable to add CC surcharge cust_pkg'; + return ''; + } + + $cust_pkg->setup(time); + my $cp_error = $cust_pkg->replace; + if($cp_error) { + warn 'Unable to set setup time on cust_pkg for cc surcharge'; + # but keep going... + } - $cust_pkg->setup(time); - my $cp_error = $cust_pkg->replace; - if($cp_error) { - warn 'Unable to set setup time on cust_pkg for cc surcharge'; - # but keep going... - } - - my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum }); - unless ( $cust_bill ) { - warn "race condition + invoice deletion just happened"; - return ''; - } + my $cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum }); + unless ( $cust_bill ) { + warn "race condition + invoice deletion just happened"; + return ''; + } + + my $grand_error = + $cust_bill->add_cc_surcharge($cust_pkg->pkgnum,$options{'cc_surcharge'}); + + warn "cannot add CC surcharge to invoice #$invnum: $grand_error" + if $grand_error; + } # end if $options{'cc_surcharge'} + + if ($options{'processing-fee'} > 0) { + my $pf_cust_pkg; + my $processing_fee_text = 'Payment Processing Fee'; + my $pf_change_error = $self->charge({ + 'amount' => $options{'processing-fee'}, + 'pkg' => $processing_fee_text, + 'setuptax' => 'Y', + 'cust_pkg_ref' => \$pf_cust_pkg, + }); + + if($pf_change_error) { + warn 'Unable to add payment processing fee'; + return ''; + } - my $grand_error = - $cust_bill->add_cc_surcharge($cust_pkg->pkgnum,$options{'cc_surcharge'}); + $pf_cust_pkg->setup(time); + my $pf_error = $pf_cust_pkg->replace; + if($pf_error) { + warn 'Unable to set setup time on cust_pkg for processing fee'; + # but keep going... + } - warn "cannot add CC surcharge to invoice #$invnum: $grand_error" - if $grand_error; + 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'}); + + warn "cannot add Processing fee to invoice #$invnum: $grand_pf_error" + if $grand_pf_error; + } #end if $options{'processing-fee'} + + } #end if ( $options{'cc_surcharge'} > 0 || $options{'processing-fee'} > 0) + return ''; #no error } diff --git a/httemplate/elements/tr-amount_fee.html b/httemplate/elements/tr-amount_fee.html index a84fef6..94795de 100644 --- a/httemplate/elements/tr-amount_fee.html +++ b/httemplate/elements/tr-amount_fee.html @@ -8,7 +8,7 @@ VALUE = "<% $amount %>" SIZE = 8 STYLE = "text-align:right;" -% if ( $fee || $surcharge_percentage || $surcharge_flatfee ) { +% if ( $fee || $surcharge_percentage || $surcharge_flatfee || $processing_fee) { onChange = "amount_changed(this)" onKeyDown = "amount_changed(this)" onKeyUp = "amount_changed(this)" @@ -38,7 +38,23 @@ </TD> </TR> -% if ($fee || $surcharge_percentage || $surcharge_flatfee ) { +% if ( $processing_fee ) { + <TR> + <TH ALIGN="right"><% mt('Apply processing fee') |h %></TH> + <TD> + <TABLE><TR> + <TD BGCOLOR="#ffffff"> + <INPUT TYPE="checkbox" NAME="processing_fee" ID="processing_fee" VALUE="<% $processing_fee %>" onclick="<% $opt{prefix} %>process_fee_changed()"> + </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> + </TR></TABLE> + </TD> + </TR> +% } + +% if ($fee || $surcharge_percentage || $surcharge_flatfee || $processing_fee) { <SCRIPT TYPE="text/javascript"> @@ -58,6 +74,10 @@ % if ( $surcharge_percentage || $surcharge_flatfee ) { var surcharge_cell = document.getElementById('ajax_surcharge_cell'); + var amount = what.value; + if (document.getElementById('processing_fee').checked == true) { + amount = (what.value - <% $processing_fee %>); + } var surcharge = ((what.value - <% $surcharge_flatfee %>) * <% $surcharge_percentage %>) + <% $surcharge_flatfee %>; surcharge_cell.innerHTML = '<FONT SIZE="+1">A credit card surcharge of ' + surcharge.toFixed(2) + ' is included in this payment</FONT>'; % } @@ -82,6 +102,7 @@ my $fee_op = ''; my $surcharge = ''; my $surcharge_percentage = 0; my $surcharge_flatfee = 0; +my $processing_fee = 0; if ( $opt{'process-pkgpart'} and ! $opt{'process-skip_first'} || $opt{'num_payments'} @@ -115,6 +136,7 @@ if ( $amount ) { $surcharge_flatfee = $opt{'surcharge_flatfee'} if $opt{'surcharge_flatfee'} > 0; $surcharge = $amount * $surcharge_percentage if $surcharge_percentage > 0; $surcharge += $surcharge_flatfee if ( $surcharge_flatfee > 0 && $amount > 0 ); + $processing_fee = $opt{'processing_fee'} if $opt{'processing_fee'} > 0; $amount += $surcharge; diff --git a/httemplate/elements/tr-select-payment_options.html b/httemplate/elements/tr-select-payment_options.html index f86f3ed..c5b84e7 100644 --- a/httemplate/elements/tr-select-payment_options.html +++ b/httemplate/elements/tr-select-payment_options.html @@ -22,6 +22,7 @@ Example: ? scalar($conf->config('credit-card-surcharge-flatfee', $cust_main->agentnum)) : 0 ), + 'processing_fee' => scalar($conf->config('processing-fee', $cust_main->agentnum)), ) </%doc> @@ -59,6 +60,7 @@ Example: $('#payment_option_row').<% $payment_option_row %>(); $('#payment_amount_row').<% $payment_amount_row %>(); + $('#ajax_processingfee_cell').hide(); if($('#payment_amount_row').is(':visible')) { var surcharge; @@ -76,11 +78,21 @@ Example: function <% $opt{prefix} %>payment_option_changed(what) { var surcharge; + var processingFee = 0; + var pfElement = document.getElementById('processing_fee'); + if (document.getElementById('surcharge_percentage') || document.getElementById('surcharge_flatfee')) { surcharge = (+what.value * +document.getElementById('surcharge_percentage').value) + +document.getElementById('surcharge_flatfee').value; } else { surcharge = 0; } - var amount = +what.value + +surcharge; + + if (pfElement != null) { + if (pfElement.checked == true) { + processingFee = +pfElement.value; + } + } + + var amount = +what.value + +surcharge + +processingFee; document.getElementById('amount').disabled = true; if ( what.value == 'select' ) { @@ -131,12 +143,21 @@ Example: function <% $opt{prefix} %>invoice_select_changed(what) { var surcharge; + var processingFee = 0; + var pfElement = document.getElementById('processing_fee'); var invdue = document.getElementById("<% $opt{prefix} %>inv" + what.value); if (document.getElementById('surcharge_percentage') || document.getElementById('surcharge_flatfee')) { surcharge = (+invdue.value * +document.getElementById('surcharge_percentage').value) + +document.getElementById('surcharge_flatfee').value; } else { surcharge = 0; } - var amount = +invdue.value + +surcharge; + + if (pfElement != null) { + if (pfElement.checked == true) { + processingFee = +pfElement.value; + } + } + + var amount = +invdue.value + +surcharge + +processingFee; if ( what.value == 'select' ) { $('#payment_amount_row').hide(); @@ -154,6 +175,21 @@ Example: } + function <% $opt{prefix} %>process_fee_changed(what) { + + if (document.getElementById('processing_fee').checked == true) { + var amount = +document.getElementById('amount').value + +document.getElementById('processing_fee').value; + $('#amount').val(amount.toFixed(2)); + $('#ajax_processingfee_cell').show(); + } + else { + var amount = +document.getElementById('amount').value - +document.getElementById('processing_fee').value; + $('#amount').val(amount.toFixed(2)); + $('#ajax_processingfee_cell').hide(); + } + + } + </SCRIPT> <%init> diff --git a/httemplate/misc/payment.cgi b/httemplate/misc/payment.cgi index 77f5acd..7911a5d 100644 --- a/httemplate/misc/payment.cgi +++ b/httemplate/misc/payment.cgi @@ -29,6 +29,7 @@ ? scalar($conf->config('credit-card-surcharge-flatfee', $cust_main->agentnum)) : 0 ), + 'processing_fee' => scalar($conf->config('processing-fee', $cust_main->agentnum)), &> % if ( $conf->exists('part_pkg-term_discounts') ) { diff --git a/httemplate/misc/process/payment.cgi b/httemplate/misc/process/payment.cgi index 7747bcb..56bcfd8 100644 --- a/httemplate/misc/process/payment.cgi +++ b/httemplate/misc/process/payment.cgi @@ -41,6 +41,8 @@ my $cust_main = qsearchs({ my $invoice = ($cgi->param('invoice') =~ /^(\d+)$/) ? $cgi->param('invoice') : ''; +my $processing_fee = $cgi->param('processing_fee') ? $cgi->param('processing_fee') : ''; + $cgi->param('amount') =~ /^\s*(\d*(\.\d\d)?)\s*$/ or errorpage("illegal amount ". $cgi->param('amount')); my $amount = $1; @@ -233,6 +235,7 @@ if ( $cgi->param('batch') ) { 'paydate' => $paydate, 'payname' => $payname, 'invnum' => $invoice, + 'processing-fee' => $processing_fee, map { $_ => scalar($cgi->param($_)) } @{$payby2fields{$payby}} ); @@ -256,6 +259,7 @@ if ( $cgi->param('batch') ) { 'no_auto_apply' => ($cgi->param('apply') eq 'never') ? 'Y' : '', 'no_invnum' => 1, 'invnum' => $invoice, + 'processing-fee' => $processing_fee, map { $_ => scalar($cgi->param($_)) } @{$payby2fields{$payby}} ); errorpage($error) if $error; |