summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FS/FS/Conf.pm8
-rw-r--r--FS/FS/cust_main/Billing_Batch.pm35
-rw-r--r--FS/FS/cust_main/Billing_Realtime.pm97
-rw-r--r--httemplate/elements/tr-amount_fee.html26
-rw-r--r--httemplate/elements/tr-select-payment_options.html40
-rw-r--r--httemplate/misc/payment.cgi1
-rw-r--r--httemplate/misc/process/payment.cgi4
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;