summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2015-02-10 01:38:56 -0800
committerIvan Kohler <ivan@freeside.biz>2015-02-10 01:38:56 -0800
commita4d4d3df88b33a6db30b565921f6d62efb252351 (patch)
tree0ddfa8fe885dfe6776a0c074aed9e1e0735a7cd7
parent6615733676adb431ae48c78ce24758fe571614c1 (diff)
multiple payment options, RT#23741
-rw-r--r--FS/FS/Conf.pm8
-rw-r--r--FS/FS/Schema.pm5
-rw-r--r--FS/FS/Template_Mixin.pm19
-rw-r--r--FS/FS/Upgrade.pm5
-rw-r--r--FS/FS/cust_main.pm127
-rw-r--r--FS/FS/cust_main/Location.pm22
-rw-r--r--FS/FS/cust_main/Search.pm44
-rw-r--r--FS/FS/cust_payby.pm442
-rw-r--r--FS/FS/o2m_Common.pm2
-rw-r--r--FS/FS/part_event/Action/cust_bill_realtime_lec.pm28
-rw-r--r--FS/FS/part_event/Condition/has_cust_payby_auto.pm43
-rw-r--r--FS/FS/part_event/Condition/hasnt_cust_payby_auto.pm27
-rw-r--r--FS/FS/part_event/Condition/payby.pm44
-rw-r--r--FS/FS/part_event_condition.pm39
-rw-r--r--FS/FS/payby.pm27
-rwxr-xr-xhttemplate/edit/cust_main.cgi28
-rw-r--r--httemplate/edit/cust_main/billing.html477
-rw-r--r--httemplate/edit/cust_main/bottomfixup.js45
-rw-r--r--httemplate/edit/cust_main/contact.html171
-rw-r--r--httemplate/edit/cust_main/contacts_new.html5
-rw-r--r--httemplate/edit/cust_main/cust_payby.html56
-rw-r--r--httemplate/edit/elements/edit.html4
-rwxr-xr-xhttemplate/edit/process/cust_main.cgi57
-rw-r--r--httemplate/elements/menu.html1
-rw-r--r--httemplate/elements/tr-coords.html2
-rwxr-xr-xhttemplate/search/cust_main.html4
-rw-r--r--httemplate/search/cust_payby.html94
-rwxr-xr-xhttemplate/search/report_cust_main.html37
-rw-r--r--httemplate/search/report_cust_payby.html57
-rwxr-xr-xhttemplate/view/cust_main.cgi17
-rw-r--r--httemplate/view/cust_main/billing.html194
-rw-r--r--httemplate/view/cust_main/cust_payby.html133
-rwxr-xr-xhttemplate/view/cust_main/packages.html4
33 files changed, 1034 insertions, 1234 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 2b959e6..4497916 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -2249,7 +2249,7 @@ and customer address. Include units.',
'section' => 'self-service',
'description' => 'Acceptable payment types for the signup server',
'type' => 'selectmultiple',
- 'select_enum' => [ qw(CARD DCRD CHEK DCHK PREPAY PPAL BILL COMP) ],
+ 'select_enum' => [ qw(CARD DCRD CHEK DCHK PREPAY PPAL ) ], # BILL COMP) ],
},
{
@@ -2652,13 +2652,13 @@ and customer address. Include units.',
'section' => 'billing',
'description' => 'Available payment types.',
'type' => 'selectmultiple',
- 'select_enum' => [ qw(CARD DCRD CHEK DCHK BILL CASH WEST MCRD MCHK PPAL COMP) ],
+ 'select_enum' => [ qw(CARD DCRD CHEK DCHK CASH WEST MCRD MCHK PPAL) ],
},
{
'key' => 'payby-default',
- 'section' => 'UI',
- 'description' => 'Default payment type. HIDE disables display of billing information and sets customers to BILL.',
+ 'section' => 'deprecated',
+ 'description' => 'Deprecated; in 4.x there is no longer the concept of a single "payment type". Used to indicate the default payment type. HIDE disables display of billing information and sets customers to BILL.',
'type' => 'select',
'select_enum' => [ '', qw(CARD DCRD CHEK DCHK BILL CASH WEST MCRD PPAL COMP HIDE) ],
},
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 133b6d8..54a4680 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -1651,6 +1651,9 @@ sub tables_hashref {
'bill_locationnum', 'int', 'NULL', '', '', '',
'ship_locationnum', 'int', 'NULL', '', '', '',
'taxstatusnum', 'char', 'NULL', 32, '', '',
+ 'complimentary', 'char', 'NULL', 1, '', '',
+ 'po_number', 'varchar', 'NULL', $char_d, '', '',
+ 'invoice_attn', 'varchar', 'NULL', $char_d, '', '',
],
'primary_key' => 'custnum',
'unique' => [ [ 'agentnum', 'agent_custid' ] ],
@@ -1699,7 +1702,7 @@ sub tables_hashref {
'columns' => [
'custpaybynum', 'serial', '', '', '', '',
'custnum', 'int', '', '', '', '',
- 'weight', 'int', '', '', '', '',
+ 'weight', 'int', 'NULL', '', '', '',
'payby', 'char', '', 4, '', '',
'payinfo', 'varchar', 'NULL', 512, '', '',
'cardtype', 'varchar', 'NULL', $char_d, '', '',
diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm
index 95d001e..fe484a4 100644
--- a/FS/FS/Template_Mixin.pm
+++ b/FS/FS/Template_Mixin.pm
@@ -316,9 +316,6 @@ sub print_generic {
unless $format =~ /^(latex|html|template)$/;
my $cust_main = $self->cust_main || $self->prospect_main;
- $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
- unless $cust_main->payname
- && $cust_main->payby !~ /^(CARD|DCRD|CHEK|DCHK)$/;
my $locale = $params{'locale'} || $cust_main->locale;
@@ -565,9 +562,11 @@ sub print_generic {
'custnum' => $cust_main->display_custnum,
'prospectnum' => $cust_main->prospectnum,
'agent_custid' => &$escape_function($cust_main->agent_custid),
- ( map { $_ => &$escape_function($cust_main->$_()) } qw(
- payname company address1 address2 city state zip fax
- )),
+ ( map { $_ => &$escape_function($cust_main->$_()) }
+ qw( company address1 address2 city state zip fax )
+ ),
+ 'payname' => &$escape_function( $cust_main->invoice_attn
+ || $cust_main->contact_firstlast ),
#global config
'ship_enable' => $conf->exists('invoice-ship_address'),
@@ -655,10 +654,10 @@ sub print_generic {
my @address = ();
$invoice_data{'address'} = \@address;
push @address,
- $cust_main->payname.
- ( ( $cust_main->payby eq 'BILL' ) && $cust_main->payinfo
- ? " (P.O. #". $cust_main->payinfo. ")"
- : ''
+ $invoice_data{'payname'}.
+ ( $cust_main->po_number
+ ? " (P.O. #". $cust_main->po_number. ")"
+ : ''
)
;
push @address, $cust_main->company
diff --git a/FS/FS/Upgrade.pm b/FS/FS/Upgrade.pm
index d05b309..263be80 100644
--- a/FS/FS/Upgrade.pm
+++ b/FS/FS/Upgrade.pm
@@ -309,7 +309,10 @@ sub upgrade_data {
tie my %hash, 'Tie::IxHash',
- #cust_main (remove paycvv from history)
+ #payby conditions to new ones
+ 'part_event_condition' => [],
+
+ #cust_main (remove paycvv from history, locations, cust_payby, etc)
'cust_main' => [],
#contact -> cust_contact / prospect_contact
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index cd675f9..d38f3d0 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -76,6 +76,7 @@ use FS::Locales;
use FS::upgrade_journal;
use FS::sales;
use FS::cust_payby;
+use FS::contact;
# 1 is mostly method/subroutine entry and options
# 2 traces progress of some operations
@@ -95,8 +96,6 @@ our $ucfirst_nowarn = 0;
our @encrypted_fields = ('payinfo', 'paycvv');
sub nohistory_fields { ('payinfo', 'paycvv'); }
-our @paytypes = ('', 'Personal checking', 'Personal savings', 'Business checking', 'Business savings');
-
our $conf;
#ask FS::UID to run this stuff for us later
#$FS::UID::callback{'FS::cust_main'} = sub {
@@ -331,7 +330,7 @@ invoicing_list destination to the newly-created svc_acct. Here's an example:
$cust_main->insert( {}, [ $email, 'POST' ] );
Currently available options are: I<depend_jobnum>, I<noexport>,
-I<tax_exemption> and I<prospectnum>.
+I<tax_exemption>, I<prospectnum>, I<contact> and I<contact_params>.
If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
on the supplied jobnum (they will not run until the specific job completes).
@@ -351,6 +350,14 @@ If I<prospectnum> is set, moves contacts and locations from that prospect.
If I<contact> is set to an arrayref of FS::contact objects, inserts those
new contacts with this new customer.
+If I<contact_params> is set to a hashref of CGI parameters (and I<contact> is
+unset), inserts those new contacts with this new customer. Handles CGI
+paramaters for an "m2" multiple entry field as passed by edit/cust_main.cgi
+
+If I<cust_payby_params> is set to a hashref o fCGI parameters, inserts those
+new stored payment records with this new customer. Handles CGI parameters
+for an "m2" multiple entry field as passed by edit/cust_main.cgi
+
=cut
sub insert {
@@ -378,7 +385,7 @@ sub insert {
my $payby = '';
if ( $self->payby eq 'PREPAY' ) {
- $self->payby('BILL');
+ $self->payby(''); #'BILL');
$prepay_identifier = $self->payinfo;
$self->payinfo('');
@@ -403,7 +410,7 @@ sub insert {
} elsif ( $self->payby =~ /^(CASH|WEST|MCRD|MCHK|PPAL)$/ ) {
$payby = $1;
- $self->payby('BILL');
+ $self->payby(''); #'BILL');
$amount = $self->paid;
}
@@ -557,8 +564,10 @@ sub insert {
}
- my $contact = delete $options{'contact'};
- if ( $contact ) {
+ warn " setting contacts\n"
+ if $DEBUG > 1;
+
+ if ( my $contact = delete $options{'contact'} ) {
foreach my $c ( @$contact ) {
$c->custnum($self->custnum);
@@ -570,6 +579,34 @@ sub insert {
}
+ } elsif ( my $contact_params = delete $options{'contact_params'} ) {
+
+ my $error = $self->process_o2m( 'table' => 'contact',
+ 'fields' => FS::contact->cgi_contact_fields,
+ 'params' => $contact_params,
+ );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ warn " setting cust_payby\n"
+ if $DEBUG > 1;
+
+ if ( my $cust_payby_params = delete $options{'cust_payby_params'} ) {
+
+ my $error = $self->process_o2m(
+ 'table' => 'cust_payby',
+ 'fields' => FS::cust_payby->cgi_cust_payby_fields,
+ 'params' => $cust_payby_params,
+ 'hash_callback' => \&FS::cust_payby::cgi_hash_callback,
+ );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
}
warn " setting cust_main_exemption\n"
@@ -1122,10 +1159,9 @@ sub delete {
#cust_tax_adjustment in financials?
#cust_pay_pending? ouch
- #cust_recon?
foreach my $table (qw(
cust_main_invoice cust_main_exemption cust_tag cust_attachment contact
- cust_location cust_main_note cust_tax_adjustment
+ cust_payby cust_location cust_main_note cust_tax_adjustment
cust_pay_void cust_pay_batch queue cust_tax_exempt
)) {
foreach my $record ( qsearch( $table, { 'custnum' => $self->custnum } ) ) {
@@ -1250,13 +1286,10 @@ sub replace {
if $DEBUG;
my $curuser = $FS::CurrentUser::CurrentUser;
- if ( $self->payby eq 'COMP'
- && $self->payby ne $old->payby
- && ! $curuser->access_right('Complimentary customer')
- )
- {
- return "You are not permitted to create complimentary accounts.";
- }
+ return "You are not permitted to create complimentary accounts."
+ if $self->complimentary eq 'Y'
+ && $self->complimentary ne $old->complimentary
+ && ! $curuser->access_right('Complimentary customer');
local($ignore_expired_card) = 1
if $old->payby =~ /^(CARD|DCRD)$/
@@ -1285,8 +1318,8 @@ sub replace {
my $dbh = dbh;
for my $l (qw(bill_location ship_location)) {
- my $old_loc = $old->$l;
- my $new_loc = $self->$l;
+ #my $old_loc = $old->$l;
+ my $new_loc = $self->$l or next;
# find the existing location if there is one
$new_loc->set('custnum' => $self->custnum);
@@ -1403,21 +1436,19 @@ sub replace {
}
- if ( $self->payby =~ /^(CARD|CHEK|LECB)$/
- && ( ( $self->get('payinfo') ne $old->get('payinfo')
- && $self->get('payinfo') !~ /^99\d{14}$/
- )
- || grep { $self->get($_) ne $old->get($_) } qw(paydate payname)
- )
- )
- {
+ if ( my $cust_payby_params = delete $options{'cust_payby_params'} ) {
- # card/check/lec info has changed, want to retry realtime_ invoice events
- my $error = $self->retry_realtime;
+ my $error = $self->process_o2m(
+ 'table' => 'cust_payby',
+ 'fields' => FS::cust_payby->cgi_cust_payby_fields,
+ 'params' => $cust_payby_params,
+ 'hash_callback' => \&FS::cust_payby::cgi_hash_callback,
+ );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
+
}
unless ( $import || $skip_fuzzyfiles ) {
@@ -1555,6 +1586,8 @@ sub check {
|| $self->ut_flag('message_noemail')
|| $self->ut_enum('locale', [ '', FS::Locales->locales ])
|| $self->ut_currencyn('currency')
+ || $self->ut_alphan('po_number')
+ || $self->ut_enum('complimentary', [ '', 'Y' ])
;
foreach (qw(company ship_company)) {
@@ -1809,6 +1842,11 @@ sub check {
}
+ return "You are not permitted to create complimentary accounts."
+ if ! $self->custnum
+ && $self->complimentary eq 'Y'
+ && ! $FS::CurrentUser->CurrentUser->access_right('Complimentary customer');
+
if ( $self->paydate eq '' || $self->paydate eq '-' ) {
return "Expiration date required"
# shouldn't payinfo_check do this?
@@ -1947,7 +1985,7 @@ sub cust_payby {
qsearch({
'table' => 'cust_payby',
'hashref' => { 'custnum' => $self->custnum },
- 'order_by' => 'ORDER BY weight ASC',
+ 'order_by' => "ORDER BY payby IN ('CARD','CHEK') DESC, weight ASC",
});
}
@@ -4816,18 +4854,31 @@ sub _upgrade_data { #class method
while (my $cust_main = $search->fetch) {
- my $cust_payby = new FS::cust_payby {
- 'custnum' => $cust_main->custnum,
- 'weight' => 1,
- map { $_ => $cust_main->$_(); } @payfields
- };
+ unless ( $cust_main->payby =~ /^(BILL|COMP)$/ ) {
- my $error = $cust_payby->insert;
- die $error if $error;
+ my $cust_payby = new FS::cust_payby {
+ 'custnum' => $cust_main->custnum,
+ 'weight' => 1,
+ map { $_ => $cust_main->$_(); } @payfields
+ };
+
+ my $error = $cust_payby->insert;
+ die $error if $error;
+
+ }
+
+ $cust_main->complimentary('Y') if $cust_main->payby eq 'COMP';
+
+ $cust_main->invoice_attn( $cust_main->payname )
+ if $cust_main->payby eq 'BILL' && $cust_main->payname;
+ $cust_main->po_number( $cust_main->payinfo )
+ if $cust_main->payby eq 'BILL' && $cust_main->payinfo;
$cust_main->setfield($_, '') foreach @payfields;
- $error = $cust_main->replace;
- die $error if $error;
+ my $error = $cust_main->replace;
+ die "Error upgradging payment information for custnum ".
+ $cust_main->custnum. ": $error"
+ if $error;
};
diff --git a/FS/FS/cust_main/Location.pm b/FS/FS/cust_main/Location.pm
index be375dd..3cb73ff 100644
--- a/FS/FS/cust_main/Location.pm
+++ b/FS/FS/cust_main/Location.pm
@@ -74,9 +74,11 @@ sub bill_location {
$self->hashref->{bill_location}
||= FS::cust_location->by_key($self->bill_locationnum)
# degraded mode--let the system keep running during upgrades
- || FS::cust_location->new({
- map { $_ => $self->get($_) } @location_fields
- })
+ || ( $self->get('address1')
+ && FS::cust_location->new({
+ map { $_ => $self->get($_) } @location_fields
+ })
+ );
}
=item ship_location
@@ -89,9 +91,17 @@ sub ship_location {
my $self = shift;
$self->hashref->{ship_location}
||= FS::cust_location->by_key($self->ship_locationnum)
- || FS::cust_location->new({
- map { $_ => $self->get('ship_'.$_) || $self->get($_) } @location_fields
- })
+ # degraded mode--let the system keep running during upgrades
+ || ( $self->get('ship_address1')
+ ? FS::cust_location->new({
+ map { $_ => $self->get('ship_'.$_) } @location_fields
+ })
+ : $self->get('address1')
+ ? FS::cust_location->new({
+ map { $_ => $self->get($_) } @location_fields
+ })
+ : ''
+ );
}
diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm
index f0a7d41..097f2fb 100644
--- a/FS/FS/cust_main/Search.pm
+++ b/FS/FS/cust_main/Search.pm
@@ -608,14 +608,6 @@ listref of start date, end date
listref of start date, end date
-=item payby
-
-listref
-
-=item paydate_year
-
-=item paydate_month
-
=item current_balance
listref (list returned by FS::UI::Web::parse_lt_gt($cgi, 'current_balance'))
@@ -646,7 +638,6 @@ sub search {
'status' => '',
'address' => '',
'zip' => '',
- 'paydate_year' => '',
'invoice_terms' => '',
'custbatch' => '',
%$params
@@ -911,40 +902,6 @@ sub search {
}
###
- # payby
- ###
-
- if ( $params->{'payby'} ) {
-
- my @payby = ref( $params->{'payby'} )
- ? @{ $params->{'payby'} }
- : ( $params->{'payby'} );
-
- @payby = grep /^([A-Z]{4})$/, @payby;
- my $in_payby = 'IN(' . join(',', map {"'$_'"} @payby) . ')';
- push @where, "EXISTS( SELECT 1 FROM cust_payby WHERE payby $in_payby ".
- "AND cust_payby.custnum = cust_main.custnum)"
- if @payby;
- }
-
- ###
- # paydate_year / paydate_month
- ###
-
- if ( $params->{'paydate_year'} =~ /^(\d{4})$/ ) {
- my $year = $1;
- $params->{'paydate_month'} =~ /^(\d\d?)$/
- or die "paydate_year without paydate_month?";
- my $month = $1;
-
- push @where,
- 'paydate IS NOT NULL',
- "paydate != ''",
- "CAST(paydate AS timestamp) < CAST('$year-$month-01' AS timestamp )"
-;
- }
-
- ###
# invoice terms
###
@@ -1134,7 +1091,6 @@ sub search {
'extra_headers' => \@extra_headers,
'extra_fields' => \@extra_fields,
};
- #warn Data::Dumper::Dumper($sql_query);
$sql_query;
}
diff --git a/FS/FS/cust_payby.pm b/FS/FS/cust_payby.pm
index ad3d80a..a65a171 100644
--- a/FS/FS/cust_payby.pm
+++ b/FS/FS/cust_payby.pm
@@ -1,26 +1,23 @@
package FS::cust_payby;
+use base qw( FS::payinfo_Mixin FS::cust_main_Mixin FS::Record );
use strict;
-use base qw( FS::payinfo_Mixin FS::Record );
-use FS::UID;
-use FS::Record qw( qsearchs ); #qsearch;
-use FS::payby;
-use FS::cust_main;
use Business::CreditCard qw( validate cardtype );
+use FS::UID qw( dbh );
use FS::Msgcat qw( gettext );
+use FS::Record; #qw( qsearch qsearchs );
+use FS::payby;
+use FS::cust_main;
+use FS::banned_pay;
-use vars qw( $conf @encrypted_fields
- $ignore_expired_card $ignore_banned_card
- $ignore_invalid_card
- );
-
-@encrypted_fields = ('payinfo', 'paycvv');
+our @encrypted_fields = ('payinfo', 'paycvv');
sub nohistory_fields { ('payinfo', 'paycvv'); }
-$ignore_expired_card = 0;
-$ignore_banned_card = 0;
-$ignore_invalid_card = 0;
+our $ignore_expired_card = 0;
+our $ignore_banned_card = 0;
+our $ignore_invalid_card = 0;
+our $conf;
install_callback FS::UID sub {
$conf = new FS::Conf;
#yes, need it for stuff below (prolly should be cached)
@@ -141,15 +138,44 @@ otherwise returns false.
=cut
-# the insert method can be inherited from FS::Record
+sub insert {
+ my $self = shift;
-=item delete
+ 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;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
-Delete this record from the database.
+ if ( $self->payby =~ /^(CARD|CHEK)$/ ) {
+ # new auto card/check info, want to retry realtime_ invoice events
+ # (new customer? that's okay, they won't have any)
+ my $error = $self->cust_main->retry_realtime;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
-=cut
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
-# the delete method can be inherited from FS::Record
+}
+
+=item delete
+
+Delete this record from the database.
=item replace OLD_RECORD
@@ -158,7 +184,87 @@ returns the error, otherwise returns false.
=cut
-# the replace method can be inherited from FS::Record
+sub replace {
+ my $self = shift;
+
+ my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
+ ? shift
+ : $self->replace_old;
+
+ if ( length($old->paycvv) && $self->paycvv =~ /^\s*[\*x]*\s*$/ ) {
+ $self->paycvv($old->paycvv);
+ }
+
+ if ( $self->payby =~ /^(CARD|DCRD)$/
+ && ( $self->payinfo =~ /xx/
+ || $self->payinfo =~ /^\s*N\/A\s+\(tokenized\)\s*$/
+ )
+ )
+ {
+warn $self->payinfo;
+warn $old->payinfo;
+ $self->payinfo($old->payinfo);
+
+ } elsif ( $self->payby =~ /^(CHEK|DCHK)$/ && $self->payinfo =~ /xx/ ) {
+ #fix for #3085 "edit of customer's routing code only surprisingly causes
+ #nothing to happen...
+ # this probably won't do the right thing when we don't have the
+ # public key (can't actually get the real $old->payinfo)
+ my($new_account, $new_aba) = split('@', $self->payinfo);
+ my($old_account, $old_aba) = split('@', $old->payinfo);
+ $new_account = $old_account if $new_account =~ /xx/;
+ $new_aba = $old_aba if $new_aba =~ /xx/;
+ $self->payinfo($new_account.'@'.$new_aba);
+ }
+
+ local($ignore_expired_card) = 1
+ if $old->payby =~ /^(CARD|DCRD)$/
+ && $self->payby =~ /^(CARD|DCRD)$/
+ && ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+
+ local($ignore_banned_card) = 1
+ if ( $old->payby =~ /^(CARD|DCRD)$/ && $self->payby =~ /^(CARD|DCRD)$/
+ || $old->payby =~ /^(CHEK|DCHK)$/ && $self->payby =~ /^(CHEK|DCHK)$/ )
+ && ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
+
+ 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;
+ my $dbh = dbh;
+
+ my $error = $self->SUPER::replace($old);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ if ( $self->payby =~ /^(CARD|CHEK)$/
+ && ( ( $self->get('payinfo') ne $old->get('payinfo')
+ && $self->get('payinfo') !~ /^99\d{14}$/
+ )
+ || grep { $self->get($_) ne $old->get($_) } qw(paydate payname)
+ )
+ )
+ {
+
+ # card/check/lec info has changed, want to retry realtime_ invoice events
+ my $error = $self->cust_main->retry_realtime;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
=item check
@@ -174,7 +280,7 @@ sub check {
my $error =
$self->ut_numbern('custpaybynum')
|| $self->ut_foreign_key('custnum', 'cust_main', 'custnum')
- || $self->ut_number('weight')
+ || $self->ut_numbern('weight')
#encrypted #|| $self->ut_textn('payinfo')
#encrypted #|| $self->ut_textn('paycvv')
# || $self->ut_textn('paymask') #XXX something
@@ -207,7 +313,7 @@ sub check {
my $payinfo = $self->payinfo;
$payinfo =~ s/\D//g;
$payinfo =~ /^(\d{13,16}|\d{8,9})$/
- or return gettext('invalid_card'); # . ": ". $self->payinfo;
+ or return gettext('invalid_card'); #. ": ". $self->payinfo;
$payinfo = $1;
$self->payinfo($payinfo);
validate($payinfo)
@@ -308,52 +414,23 @@ sub check {
}
}
- } elsif ( $self->payby eq 'LECB' ) {
-
- my $payinfo = $self->payinfo;
- $payinfo =~ s/\D//g;
- $payinfo =~ /^1?(\d{10})$/ or return 'invalid btn billing telephone number';
- $payinfo = $1;
- $self->payinfo($payinfo);
- $self->paycvv('');
-
- } elsif ( $self->payby eq 'BILL' ) {
-
- $error = $self->ut_textn('payinfo');
- return "Illegal P.O. number: ". $self->payinfo if $error;
- $self->paycvv('');
-
- } elsif ( $self->payby eq 'COMP' ) {
-
- my $curuser = $FS::CurrentUser::CurrentUser;
- if ( ! $self->custnum
- && ! $curuser->access_right('Complimentary customer')
- )
- {
- return "You are not permitted to create complimentary accounts."
- }
-
- $error = $self->ut_textn('payinfo');
- return "Illegal comp account issuer: ". $self->payinfo if $error;
- $self->paycvv('');
-
- } elsif ( $self->payby eq 'PREPAY' ) {
-
- my $payinfo = $self->payinfo;
- $payinfo =~ s/\W//g; #anything else would just confuse things
- $self->payinfo($payinfo);
- $error = $self->ut_alpha('payinfo');
- return "Illegal prepayment identifier: ". $self->payinfo if $error;
- return "Unknown prepayment identifier"
- unless qsearchs('prepay_credit', { 'identifier' => $self->payinfo } );
- $self->paycvv('');
+# } elsif ( $self->payby eq 'PREPAY' ) {
+#
+# my $payinfo = $self->payinfo;
+# $payinfo =~ s/\W//g; #anything else would just confuse things
+# $self->payinfo($payinfo);
+# $error = $self->ut_alpha('payinfo');
+# return "Illegal prepayment identifier: ". $self->payinfo if $error;
+# return "Unknown prepayment identifier"
+# unless qsearchs('prepay_credit', { 'identifier' => $self->payinfo } );
+# $self->paycvv('');
}
if ( $self->paydate eq '' || $self->paydate eq '-' ) {
return "Expiration date required"
# shouldn't payinfo_check do this?
- unless $self->payby =~ /^(BILL|PREPAY|CHEK|DCHK|LECB|CASH|WEST|MCRD|MCHK|PPAL)$/;
+ unless $self->payby =~ /^(CHEK|DCHK)$/;
$self->paydate('');
} else {
my( $m, $y );
@@ -400,6 +477,247 @@ sub check {
$self->SUPER::check;
}
+sub _banned_pay_hashref {
+ my $self = shift;
+
+ my %payby2ban = (
+ 'CARD' => 'CARD',
+ 'DCRD' => 'CARD',
+ 'CHEK' => 'CHEK',
+ 'DCHK' => 'CHEK'
+ );
+
+ {
+ 'payby' => $payby2ban{$self->payby},
+ 'payinfo' => $self->payinfo,
+ #don't ever *search* on reason! #'reason' =>
+ };
+}
+
+=item paydate_mon_year
+
+Returns a two element list consisting of the paydate month and year.
+
+=cut
+
+sub paydate_mon_year {
+ my $self = shift;
+
+ my $date = $self->paydate; # || '12-2037';
+
+ #false laziness w/elements/select-month_year.html
+ if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
+ ( $2, $1 );
+ } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+ ( $1, $3 );
+ } else {
+ warn "unrecognized expiration date format: $date";
+ ( '', '' );
+ }
+
+}
+
+=item realtime_bop
+
+=cut
+
+sub realtime_bop {
+ my( $self, %opt ) = @_;
+
+ $opt{$_} = $self->$_() for qw( payinfo payname paydate );
+
+ if ( $self->locationnum ) {
+ my $cust_location = $self->cust_location;
+ $opt{$_} = $cust_location->$_() for qw( address1 address2 city state zip );
+ }
+
+ $self->cust_main->realtime_bop({
+ 'method' => FS::payby->payby2bop( $self->payby ),
+ %opt,
+ });
+
+}
+
+=item paytypes
+
+Returns a list of valid values for the paytype field (bank account type for
+electronic check payment).
+
+=cut
+
+sub paytypes {
+ #my $class = shift;
+
+ ('', 'Personal checking', 'Personal savings', 'Business checking', 'Business savings');
+}
+
+=item cgi_cust_payby_fields
+
+Returns the field names used in the web interface (including some pseudo-fields).
+
+=cut
+
+sub cgi_cust_payby_fields {
+ #my $class = shift;
+ [qw( payby payinfo paydate_month paydate_year paycvv payname weight
+ payinfo1 payinfo2 payinfo3 paytype paystate )];
+}
+
+=item cgi_hash_callback HASHREF
+
+Subroutine (not a class or object method). Processes a hash reference
+of web interface contet (transfers the data from pseudo-fields to real fields).
+
+=cut
+
+sub cgi_hash_callback {
+ my $hashref = shift;
+
+ my %noauto = (
+ 'CARD' => 'DCRD',
+ 'CHEK' => 'DCHK',
+ );
+ $hashref->{payby} = $noauto{$hashref->{payby}}
+ if ! $hashref->{weight} && exists $noauto{$hashref->{payby}};
+
+ if ( $hashref->{payby} =~ /^(CHEK|DCHK)$/ ) {
+
+ unless ( grep $hashref->{$_}, qw( payinfo1 payinfo2 payinfo3 payname ) ) {
+ %$hashref = ();
+ return;
+ }
+
+ $hashref->{payinfo} = $hashref->{payinfo1}. '@';
+ $hashref->{payinfo} .= $hashref->{payinfo3}.'.'
+ if $conf->config('echeck-country') eq 'CA';
+ $hashref->{payinfo} .= $hashref->{'payinfo2'};
+
+ $hashref->{payname} .= $hashref->{'payname_CHEK'};
+
+ } elsif ( $hashref->{payby} =~ /^(CARD|DCRD)$/ ) {
+
+ unless ( grep $hashref->{$_}, qw( payinfo paycvv payname ) ) {
+ %$hashref = ();
+ return;
+ }
+
+ }
+
+ $hashref->{paydate}= $hashref->{paydate_month}. '-'. $hashref->{paydate_year};
+
+}
+
+=item search_sql
+
+Class method.
+
+Returns a qsearch hash expression to search for parameters specified in HASHREF.
+Valid paramters are:
+
+=over 4
+
+=item payby
+
+listref
+
+=item paydate_year
+
+=item paydate_month
+
+
+=back
+
+=cut
+
+sub search_sql {
+ my ($class, $params) = @_;
+
+ my @where = ();
+ my $orderby;
+
+ # initialize these to prevent warnings
+ $params = {
+ 'paydate_year' => '',
+ %$params
+ };
+
+ ###
+ # payby
+ ###
+
+ if ( $params->{'payby'} ) {
+
+ my @payby = ref( $params->{'payby'} )
+ ? @{ $params->{'payby'} }
+ : ( $params->{'payby'} );
+
+ @payby = grep /^([A-Z]{4})$/, @payby;
+ my $in_payby = 'IN(' . join(',', map {"'$_'"} @payby) . ')';
+ push @where, "cust_payby.payby $in_payby"
+ if @payby;
+ }
+
+ ###
+ # paydate_year / paydate_month
+ ###
+
+ if ( $params->{'paydate_year'} =~ /^(\d{4})$/ ) {
+ my $year = $1;
+ $params->{'paydate_month'} =~ /^(\d\d?)$/
+ or die "paydate_year without paydate_month?";
+ my $month = $1;
+
+ push @where,
+ 'cust_payby.paydate IS NOT NULL',
+ "cust_payby.paydate != ''",
+ "CAST(cust_payby.paydate AS timestamp) < CAST('$year-$month-01' AS timestamp )"
+;
+ }
+ ##
+ # setup queries, subs, etc. for the search
+ ##
+
+ $orderby ||= 'ORDER BY custnum';
+
+ # here is the agent virtualization
+ push @where,
+ $FS::CurrentUser::CurrentUser->agentnums_sql(table => 'cust_main');
+
+ my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : '';
+
+ my $addl_from = ' LEFT JOIN cust_main USING ( custnum ) ';
+ # always make address fields available in results
+ for my $pre ('bill_', 'ship_') {
+ $addl_from .=
+ ' LEFT JOIN cust_location AS '.$pre.'location '.
+ 'ON (cust_main.'.$pre.'locationnum = '.$pre.'location.locationnum) ';
+ }
+
+ my $count_query = "SELECT COUNT(*) FROM cust_payby $addl_from $extra_sql";
+
+ my @select = ( 'cust_payby.*',
+ #'cust_main.custnum',
+ # there's a good chance that we'll need these
+ 'cust_main.bill_locationnum',
+ 'cust_main.ship_locationnum',
+ FS::UI::Web::cust_sql_fields($params->{'cust_fields'}),
+ );
+
+ my $select = join(', ', @select);
+
+ my $sql_query = {
+ 'table' => 'cust_payby',
+ 'select' => $select,
+ 'addl_from' => $addl_from,
+ 'hashref' => {},
+ 'extra_sql' => $extra_sql,
+ 'order_by' => $orderby,
+ 'count_query' => $count_query,
+ };
+ $sql_query;
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/o2m_Common.pm b/FS/FS/o2m_Common.pm
index d237bef..4f6d2e7 100644
--- a/FS/FS/o2m_Common.pm
+++ b/FS/FS/o2m_Common.pm
@@ -103,6 +103,7 @@ sub process_o2m {
map { $_ => $opt{'params'}->{$add_param."_$_"} }
@{ $opt{'fields'} }
);
+ &{ $opt{'hash_callback'} }( \%hash ) if $opt{'hash_callback'};
#next unless grep { $_ =~ /\S/ } values %hash;
my $new_obj = "FS::$table"->new( { %$hashref, %hash } );
@@ -117,6 +118,7 @@ sub process_o2m {
my %hash = map { $_ => $opt{'params'}->{$add_param."_$_"} }
@{ $opt{'fields'} };
+ &{ $opt{'hash_callback'} }( \%hash ) if $opt{'hash_callback'};
next unless grep { $_ =~ /\S/ } values %hash;
my $add_obj = "FS::$table"->new( { %$hashref, %hash } );
diff --git a/FS/FS/part_event/Action/cust_bill_realtime_lec.pm b/FS/FS/part_event/Action/cust_bill_realtime_lec.pm
deleted file mode 100644
index cd03ddc..0000000
--- a/FS/FS/part_event/Action/cust_bill_realtime_lec.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-package FS::part_event::Action::cust_bill_realtime_lec;
-
-use strict;
-use base qw( FS::part_event::Action );
-
-sub description {
- #'Run phone bill ("LEC") billing with a <a href="http://420.am/business-onlinepayment/">Business::OnlinePayment</a> realtime gateway';
- 'Run phone bill ("LEC") billing with a Business::OnlinePayment realtime gateway';
-}
-
-sub deprecated { 1; }
-
-sub eventtable_hashref {
- { 'cust_bill' => 1 };
-}
-
-sub default_weight { 30; }
-
-sub do_action {
- my( $self, $cust_bill ) = @_;
-
- #my $cust_main = $self->cust_main($cust_bill);
- my $cust_main = $cust_bill->cust_main;
-
- $cust_bill->realtime_lec;
-}
-
-1;
diff --git a/FS/FS/part_event/Condition/has_cust_payby_auto.pm b/FS/FS/part_event/Condition/has_cust_payby_auto.pm
new file mode 100644
index 0000000..edfb7ec
--- /dev/null
+++ b/FS/FS/part_event/Condition/has_cust_payby_auto.pm
@@ -0,0 +1,43 @@
+package FS::part_event::Condition::has_cust_payby_auto;
+
+use strict;
+use Tie::IxHash;
+use FS::payby;
+
+use base qw( FS::part_event::Condition );
+
+sub description {
+ 'Customer has automatic payment information';
+}
+
+tie my %payby, 'Tie::IxHash', FS::payby->cust_payby2shortname;
+delete $payby{'DCRD'};
+delete $payby{'DCHK'};
+
+sub option_fields {
+ (
+ 'payby' => {
+ label => 'Has automatic payment info',
+ type => 'select',
+ options => [ keys %payby ],
+ option_labels => \%payby,
+ },
+ );
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ scalar( qsearch({
+ 'table' => 'cust_payby',
+ 'hashref' => { 'custnum' => $cust_main->custnum,
+ 'payby' => $self->option('payby')
+ },
+ 'order_by' => 'LIMIT 1',
+ }) );
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/hasnt_cust_payby_auto.pm b/FS/FS/part_event/Condition/hasnt_cust_payby_auto.pm
new file mode 100644
index 0000000..6655a63
--- /dev/null
+++ b/FS/FS/part_event/Condition/hasnt_cust_payby_auto.pm
@@ -0,0 +1,27 @@
+package FS::part_event::Condition::hasnt_cust_payby_auto;
+
+use strict;
+use Tie::IxHash;
+
+use base qw( FS::part_event::Condition );
+
+sub description {
+ 'Customer does not have automatic payment information';
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+
+ my $cust_main = $self->cust_main($object);
+
+ ! scalar( qsearch({
+ 'table' => 'cust_payby',
+ 'hashref' => { 'custnum' => $cust_main->custnum,
+ },
+ 'extra_sql' => "AND payby IN ( 'CARD', 'CHEK' )",
+ 'order_by' => 'LIMIT 1',
+ }) );
+
+}
+
+1;
diff --git a/FS/FS/part_event/Condition/payby.pm b/FS/FS/part_event/Condition/payby.pm
deleted file mode 100644
index 16bf480..0000000
--- a/FS/FS/part_event/Condition/payby.pm
+++ /dev/null
@@ -1,44 +0,0 @@
-package FS::part_event::Condition::payby;
-
-use strict;
-use Tie::IxHash;
-use FS::payby;
-
-use base qw( FS::part_event::Condition );
-
-sub description {
- #'customer payment types: ';
- 'Customer payment type';
-}
-
-#something like this
-tie my %payby, 'Tie::IxHash', FS::payby->cust_payby2longname;
-sub option_fields {
- (
- 'payby' => {
- label => 'Customer payment type',
- #type => 'select-multiple',
- type => 'checkbox-multiple',
- options => [ keys %payby ],
- option_labels => \%payby,
- },
- );
-}
-
-sub condition {
- my( $self, $object ) = @_;
-
- my $cust_main = $self->cust_main($object);
-
- my $hashref = $self->option('payby') || {};
- $hashref->{ $cust_main->payby };
-
-}
-
-sub condition_sql {
- my( $self, $table ) = @_;
-
- 'cust_main.payby IN '. $self->condition_sql_option_option('payby');
-}
-
-1;
diff --git a/FS/FS/part_event_condition.pm b/FS/FS/part_event_condition.pm
index ac2ee82..200049d 100644
--- a/FS/FS/part_event_condition.pm
+++ b/FS/FS/part_event_condition.pm
@@ -354,6 +354,45 @@ sub order_conditions_sql {
}
+sub _upgrade_data { #class method
+ my ($class, %opts) = @_;
+
+ foreach my $part_event_condition (
+ qsearch('part_event_condition', { 'conditionname' => 'payby' } )
+ ) {
+
+ my $payby = $part_event_condition->option('payby');
+
+ if ( scalar( keys %$payby ) == 1 ) {
+
+ if ( $payby->{'CARD'} ) {
+
+ $part_event_condition->conditionname('has_cust_payby_auto');
+
+ } elsif ( $payby->{'CHEK'} ) {
+
+ $part_event_condition->conditionname('has_cust_payby_auto');
+
+ }
+
+ } elsif ( $payby->{'BILL'} && ! $payby->{'CARD'} && ! $payby->{'CHEK'} ) {
+
+ $part_event_condition->conditionname('hasnt_cust_payby_auto');
+
+ } else {
+
+ die 'Unable to automatically convert payby condition for event #'.
+ $part_event_condition->eventpart. "\n";
+
+ }
+
+ my $error = $part_event_condition->replace;
+ die $error if $error;
+
+ }
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm
index c4aa1b1..13423c4 100644
--- a/FS/FS/payby.pm
+++ b/FS/FS/payby.pm
@@ -5,7 +5,6 @@ use vars qw(%hash %payby2bop);
use Tie::IxHash;
use Business::CreditCard;
-
=head1 NAME
FS::payby - Object methods for payment type records
@@ -39,9 +38,8 @@ Payment types.
=cut
# paybys can be any/all of:
-# - a customer payment type (cust_main.payby)
+# - a customer saved payment type (cust_payby.payby)
# - a payment or refund type (cust_pay.payby, cust_pay_batch.payby, cust_refund.payby)
-# - an event type (part_bill_event.payby)
tie %hash, 'Tie::IxHash',
'CARD' => {
@@ -70,18 +68,6 @@ tie %hash, 'Tie::IxHash',
cust_pay => 'CHEK', #this is a customer type only, payments are CHEK...
realtime => 1,
},
- #'LECB' => {
- # tinyname => 'phone bill',
- # shortname => 'Phone bill billing',
- # longname => 'Phone bill billing',
- # realtime => 1,
- #},
- 'BILL' => {
- tinyname => 'billing',
- shortname => 'Billing',
- payname => 'Check',
- longname => 'Billing',
- },
'PPAL' => {
tinyname => 'PayPal',
shortname => 'PayPal',
@@ -143,12 +129,6 @@ tie %hash, 'Tie::IxHash',
longname => 'Wire transfer',
cust_main => '', #not a customer type
},
- 'COMP' => {
- tinyname => 'comp',
- shortname => 'Complimentary',
- longname => 'Complimentary',
- cust_pay => '', # (free) is depricated as a payment type in cust_pay
- },
'CBAK' => {
tinyname => 'chargeback',
shortname => 'Chargeback',
@@ -234,6 +214,11 @@ sub cust_payby {
grep { ! exists $hash{$_}->{cust_main} } $self->payby;
}
+sub cust_payby2shortname {
+ my $self = shift;
+ map { $_ => $hash{$_}->{shortname} } $self->cust_payby;
+}
+
sub cust_payby2longname {
my $self = shift;
map { $_ => $hash{$_}->{longname} } $self->cust_payby;
diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
index da87bfc..f99cce2 100755
--- a/httemplate/edit/cust_main.cgi
+++ b/httemplate/edit/cust_main.cgi
@@ -1,8 +1,4 @@
-<& /elements/header.html,
- $title,
- '',
- ' onUnload="myclose()"' #hmm, in billing.html
-&>
+<& /elements/header.html, $title, &>
<& /elements/error.html &>
@@ -60,7 +56,7 @@
</TABLE>
</TD>
</TR>
-<TR><TD STYLE="height:40px"></TD></TR>
+<TR><TD STYLE="height:14px"></TD></TR>
<TR>
<TD STYLE="width:650px">
<FONT CLASS="fsinnerbox-title"><% mt('Service address') |h %></FONT>
@@ -105,16 +101,13 @@ function samechanged(what) {
<BR>
-<& cust_main/contacts_new.html,
- 'cust_main' => $cust_main,
-&>
+<& cust_main/contacts_new.html, 'cust_main'=>$cust_main, &>
%# billing info
<& cust_main/billing.html, $cust_main,
'payinfo' => $payinfo,
'invoicing_list' => \@invoicing_list,
&>
-<BR>
% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
% if (!$ro_comments || $cust_main->comments) {
@@ -156,18 +149,6 @@ function samechanged(what) {
<INPUT TYPE="hidden" NAME="usernum" VALUE="<% $cust_main->usernum %>">
-%# cust_main/bottomfixup.js
-% foreach my $hidden (
-% 'payauto', 'billday',
-% 'payinfo', 'payinfo1', 'payinfo2', 'payinfo3', 'paytype',
-% 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
-% 'paystart_month', 'paystart_year', 'payissue',
-% 'payip',
-% 'paid',
-% ) {
- <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
-% }
-
<& cust_main/bottomfixup.html, 'custnum' => $custnum &>
<BR>
@@ -375,9 +356,6 @@ if ( $cgi->param('error') ) {
}
-my %keep = map { $_=>1 } qw( error tagnum lock_agentnum lock_pkgpart );
-$cgi->delete( grep { !$keep{$_} && $_ !~ /^tax_/ } $cgi->param );
-
my $title = $custnum ? 'Edit Customer' : 'Add Customer';
$title = mt($title);
$title .= ": ". $cust_main->name if $custnum;
diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html
index fcd8f01..fa392bb 100644
--- a/httemplate/edit/cust_main/billing.html
+++ b/httemplate/edit/cust_main/billing.html
@@ -1,123 +1,7 @@
-%if ( $payby_default eq 'HIDE' ) {
-% $cust_main->payby('BILL') unless $cust_main->payby;
-% my $payby = $cust_main->payby;
-
- <INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
-
- <INPUT TYPE="hidden" NAME="<%$payby%>_payinfo" VALUE="<% $cust_main->paymask %>">
-
-% foreach my $field (qw( payname paycvv paystart_month paystart_year payissue payip paytype paystate billday )) {
-
- <INPUT TYPE="hidden" NAME="<% $payby.'_'.$field %>" VALUE="<% $cust_main->get($field) %>">
-
-% }
-
-% #false laziness w/elements/select-month_year.html & view/cust_main/billing.html
-% my( $mon, $year );
-% my $date = $cust_main->paydate || '12-2037';
-% if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
-% ( $mon, $year ) = ( $2, $1 );
-% } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
-% ( $mon, $year ) = ( $1, $3 );
-% } else {
-% die "unrecognized expiration date format: $date";
-% }
-
- <INPUT TYPE="hidden" NAME="<%$payby%>_exp_month" VALUE="<% $mon %>">
- <INPUT TYPE="hidden" NAME="<%$payby%>_exp_year" VALUE="<% $year %>">
-
- <INPUT TYPE="hidden" NAME="tax" VALUE="<% $cust_main->tax %>">
-
- <INPUT TYPE="hidden" NAME="invoicing_list" VALUE="<% join(', ', @invoicing_list) %>">
-
-% } else {
-%
% my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
- <BR><FONT CLASS="fsinnerbox-title"><% mt('Billing information') |h %></FONT>
- <% &ntable("#cccccc") %>
-
- <TR>
- <TD ALIGN="right" WIDTH="200"><%$r%><% mt('Billing type') |h %></TD>
-
<SCRIPT>
- var mywindow = -1;
- function myopen(filename,windowname,properties) {
- myclose();
- mywindow = window.open(filename,windowname,properties);
- }
- function myclose() {
- if ( mywindow != -1 )
- mywindow.close();
- mywindow = -1;
- }
-
- var achwindow = -1;
- function achopen(filename,windowname,properties) {
- achclose();
- achwindow = window.open(filename,windowname,properties);
- }
- function achclose() {
- if ( achwindow != -1 )
- achwindow.close();
- achwindow = -1;
- }
-
- function card_changed(what) {
- if (
- what.form.payinfo.value.substring(0, 4) == '4093'
- || what.form.payinfo.value.substring(0, 4) == '4911'
- || what.form.payinfo.value.substring(0, 4) == '4936'
- || what.form.payinfo.value.substring(0, 6) == '564132'
- || what.form.payinfo.value.substring(0, 2) == '63'
- || what.form.payinfo.value.substring(0, 2) == '67'
- )
- {
- what.form.paystart_month.disabled = false;
- what.form.paystart_year.disabled = false;
- what.form.payissue.disabled = false;
- what.form.paystart_month.style.backgroundColor = '#ffffff';
- what.form.paystart_year.style.backgroundColor = '#ffffff';
- what.form.payissue.style.backgroundColor = '#ffffff';
- document.getElementById('paystart_label').style.color = '#000000';
- document.getElementById('payissue_label').style.color = '#000000';
- } else {
- what.form.paystart_month.disabled = true;
- what.form.paystart_year.disabled = true;
- what.form.payissue.disabled = true;
- what.form.paystart_month.style.backgroundColor = '#dddddd';
- what.form.paystart_year.style.backgroundColor = '#dddddd';
- what.form.payissue.style.backgroundColor = '#dddddd';
- document.getElementById('paystart_label').style.color = '#999999';
- document.getElementById('payissue_label').style.color = '#999999';
- }
- return true;
- }
-
- function init_payauto_changed(){
- var f = document.getElementById('CARD_payauto');
- if(f != null) payauto_changed(f);
- f = document.getElementById('CHEK_payauto');
- if(f != null) payauto_changed(f);
- }
-
- function payauto_changed(payauto_field){
- var select = (payauto_field.name == 'CARD_payauto') ? 'CARD_billday' : 'CHEK_billday';
- var span = document.getElementById('td_'+select);
- select = document.getElementById(select);
- if (span == null || select == null) return;
- if(payauto_field.checked) {
- span.style.color = '#000000';
- select.disabled = false;
- }
- else {
- span.style.color = '#999999';
- select.disabled = true;
- //why? select.selectedIndex = 0;
- }
- }
-
function tax_changed(what) {
var num = document.getElementById(what.id + '_num');
if ( what.checked ) {
@@ -129,321 +13,10 @@
</SCRIPT>
- <& /elements/init_overlib.html &>
-
-% my $payby = $cust_main->payby;
-% my $paytype = $cust_main->paytype;
-% my( $account, $aba ) = split('@', $payinfo);
-% my $branch = '';
-% ($branch,$aba) = split('\.',$aba)
-% if $conf->config('echeck-country') eq 'CA';
-%
-% my $disabled = 'DISABLED style="background-color: #dddddd"';
-% my $text_disabled = 'style="color: #999999"';
-%
-% if ( $payby =~ /^(CARD|DCRD)$/ && cardtype($payinfo) =~ /^(Switch|Solo)$/ ) {
-% $disabled = 'style="background-color: #ffffff"';
-% $text_disabled = 'style="color: #000000";'
-% }
-%
-% my $disable_payauto = $conf->exists('disable_payauto_default');
-% my $CARD_payauto_checked = $payby eq 'DCRD' ? ''
-% : $payby eq 'CARD' ? 'CHECKED'
-% : $disable_payauto ? '' : 'CHECKED';
-% my $CHEK_payauto_checked = $payby eq 'DCHK' ? ''
-% : $payby eq 'CHEK' ? 'CHECKED'
-% : $disable_payauto ? '' : 'CHECKED';
-%
-% sub billday_options {
-% my $curr_value = shift;
-% my $ret = '';
-% for my $billday ( 1 .. 28 ) {
-% my $sel = '';
-% $sel = "SELECTED='SELECTED'" if $curr_value == $billday;
-% $ret .= "<OPTION VALUE='$billday' $sel>$billday</OPTION>";
-% }
-% $ret;
-% }
-%
-% my $card_billday_style = $payby eq 'CARD' ? '' : 'style="color: #999999"';
-% my $chek_billday_style = $payby eq 'CHEK' ? '' : 'style="color: #999999"';
-% my $card_billday_select_disabled = $payby eq 'CARD' ? '' : 'DISABLED';
-% my $chek_billday_select_disabled = $payby eq 'CHEK' ? '' : 'DISABLED';
-%
-% #false laziness w/view/cust_main/billing.html and misc/payment.cgi
-% my $routing_label = $conf->config('echeck-country') eq 'US'
-% ? 'ABA/Routing number'
-% : 'Routing number';
-% my $routing_size = $conf->config('echeck-country') eq 'CA' ? 4 : 10;
-% my $routing_maxlength = $conf->config('echeck-country') eq 'CA' ? 3 : 9;
-%
-%
-% my %payby = (
-%
-% 'CARD' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Card number').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Expiration').qq! </TD>!.
-% '<TD WIDTH="408">'.
-%
-% include('/elements/select-month_year.html',
-% 'prefix' => 'CARD_exp',
-% 'selected_date' =>
-% ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->paydate : '' ),
-% ).
-%
-% '</TD></TR>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">!.emt('CVV2').qq!&nbsp;!.
-%
-% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">!.emt('help').qq!</A>)!.
-% qq!</TD>!.
-% '<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200"><SPAN ID="paystart_label" $text_disabled>!.emt('Start date').qq! </SPAN></TD>!.
-% '<TD WIDTH="408">'.
-%
-% include('/elements/select-month_year.html',
-% 'prefix' => 'CARD_paystart',
-% 'disabled' => $disabled,
-% 'empty_option' => 1,
-% 'start_year' => 2000,
-% 'end_year' => (localtime())[5] + 1900,
-% 'selected_date' => (
-% ( $payby =~ /^(CARD|DCRD)$/
-% && cardtype($payinfo) =~ /^(Switch|Solo)$/ )
-% ? $cust_main->paystart_month. '-'.
-% $cust_main->paystart_year
-% : ''
-% )
-% ).
-%
-% qq!<SPAN ID="payissue_label" $text_disabled>!.emt('or Issue number').qq! </SPAN>!.
-% '<INPUT TYPE="text" NAME="CARD_payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Exact name on card').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
-%
-% qq!<TR><TD COLSPAN=2 WIDTH="608">!.
-% qq!<INPUT TYPE="checkbox" onchange="payauto_changed(this);" ID="CARD_payauto" NAME="CARD_payauto" $CARD_payauto_checked> !.
-% emt('Charge future payments to this [_1] automatically','credit card').'</TD></TR>'.
-%
-% ( $conf->exists('cust_main-select-billday') ?
-% qq!<TR><TD ALIGN="RIGHT" id="td_CARD_billday" $card_billday_style>
-% Charge on this day of each month</TD><TD> &nbsp;
-% <SELECT id="CARD_billday" $card_billday_select_disabled NAME="CARD_billday">!
-% . billday_options($cust_main->billday) . qq!</SELECT> </TD></TR>!
-% : ''
-% ).
-%
-% '</TABLE>',
-%
-% 'CHEK' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Account number').qq! </TD>!.
-% qq!<TD><INPUT TYPE="text" SIZE=12 NAME="CHEK_payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
-% qq!<TD ALIGN="right">!.emt('Type').qq!</TD><TD><SELECT NAME="CHEK_paytype">!.
-% join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes).
-% qq!</SELECT></TD></TR>!.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt($routing_label).qq! </TD>!.
-% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=$routing_size MAXLENGTH=$routing_maxlength NAME="CHEK_payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!"> !.
-% qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">!.emt('help').qq!</A>)!.
-% qq!</TD></TR>!.
-%
-% qq!<INPUT TYPE="hidden" NAME="CHEK_exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="CHEK_exp_year" VALUE="2037">!.
-%
-% ( $conf->config('echeck-country') eq 'CA' ?
-% qq!<TR><TD ALIGN="right">$r !.emt('Branch number').qq!</TD><TD COLSPAN="3">
-% <INPUT TYPE="text" name="CHEK_payinfo3" VALUE="$branch" SIZE=6 MAXLENGTH=5></TD></TR>! : '' ).
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Bank name').qq! </TD>!.
-% qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="CHEK_payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
-% ( $conf->exists('show_bankstate') ?
-% qq!<TR><TD ALIGN="right" WIDTH="200">$paystate_label</TD>!.
-% qq!<TD COLSPAN="3" WIDTH="408">!.
-% include('/elements/select-state.html',
-% 'empty' => emt('(choose)'),
-% 'state' => $cust_main->paystate,
-% 'country' => $cust_main->country,
-% 'prefix' => 'CHEK_pay',
-% ). "</TD></TR>"
-% : '<INPUT TYPE="hidden" NAME="CHEK_paystate" VALUE="'.
-% $cust_main->paystate. '">'
-% ).
-%
-%
-% qq!<TR><TD COLSPAN=4 WIDTH="608">!.
-% qq!<INPUT TYPE="checkbox" onchange="payauto_changed(this);" ID="CHEK_payauto" NAME="CHEK_payauto" $CHEK_payauto_checked> !.
-% emt('Charge future payments to this [_1] automatically','electronic check').'</TD></TR>'.
-%
-% ( $conf->exists('cust_main-select-billday') ?
-% qq!<TR><TD ALIGN="RIGHT" id="td_CHEK_billday" $chek_billday_style>
-% Charge on this day of each month</TD><TD> &nbsp;
-% <SELECT id="CHEK_billday" $chek_billday_select_disabled NAME="CHEK_billday">!
-% . billday_options($cust_main->billday) . qq!</SELECT> </TD></TR>!
-% : ''
-% ).
-%
-% '</TABLE>',
-%
-% 'LECB' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Phone number').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="LECB_payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
-%
-% qq!<INPUT TYPE="hidden" NAME="LECB_exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="LECB_exp_year" VALUE="2037">!.
-% qq!<INPUT TYPE="hidden" NAME="LECB_payname" VALUE="">!.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% 'BILL' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">!.emt('P.O.').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
-%
-% qq!<INPUT TYPE="hidden" NAME="BILL_exp_month" VALUE="12">!.
-% qq!<INPUT TYPE="hidden" NAME="BILL_exp_year" VALUE="2037">!.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">!.emt('Attention').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payname" VALUE="!. encode_entities( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% 'COMP' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Approved by').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""></TD></TR>!.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Expiration').qq! </TD>!.
-% '<TD WIDTH="408">'.
-%
-% include('/elements/select-month_year.html',
-% 'prefix' => 'COMP_exp',
-% 'selected_date' =>
-% ( $payby eq 'COMP' ? $cust_main->paydate : '' ),
-% ).
-%
-% '</TD></TR>'.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% 'CASH' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Amount').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CASH_paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% 'WEST' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Amount').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="WEST_paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% 'MCRD' =>
-%
-% '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
-%
-% qq!<TR><TD ALIGN="right" WIDTH="200">${r}!.emt('Amount').qq! </TD>!.
-% qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="MCRD_paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
-%
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-% '<TR><TD>&nbsp;</TD></TR>'.
-%
-% '</TABLE>',
-%
-% );
-%
-% #this should use FS::payby
-% my @allopt = qw( CARD CHEK LECB BILL CASH WEST MCRD COMP );
-%
-% my %allopt = map { $_ => FS::payby->shortname($_) } @allopt;
-%
-% if ( $cust_main->custnum ) {
-% #don't offer CASH/WEST/MCRD initial payment types when editing customer
-% delete $allopt{$_} for qw(CASH WEST MCRD);
-% }
-%
-% my @options = grep exists( $allopt{$_} ), @payby;
-%
-% my %payby2option = (
-% ( map { $_ => $_ } @options ),
-% 'DCRD' => 'CARD',
-% 'DCHK' => 'CHEK',
-% );
-
- <TD WIDTH="408">
- <& /elements/selectlayers.html,
- 'field' => 'payby',
- 'curr_value' => $payby2option{$payby || $payby_default || $payby[0] },
- 'options' => \@options,
- 'labels' => \%allopt,
- 'html_between' => '</TD></TR></TABLE>',
- 'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
- 'onchange' => 'init_payauto_changed();',
- &>
+ <BR><FONT CLASS="fsinnerbox-title"><% mt('Billing information') |h %></FONT>
<% &ntable("#cccccc") %>
- <TR><TD>&nbsp;</TD></TR>
-
% my $curuser = $FS::CurrentUser::CurrentUser;
% my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
% if ( $conf->exists('cust_class-tax_exempt')
@@ -490,18 +63,6 @@
</TD>
</TR>
- <TR>
- <TD WIDTH="608" COLSPAN="2"><INPUT TYPE="checkbox" NAME="invoicing_list_FAX" VALUE="FAX" <%
-
- ( grep { $_ eq 'FAX' } @invoicing_list )
- ? 'CHECKED'
- : ''
-
- %>> <% mt('Fax invoices') |h %>
-
- </TD>
- </TR>
-
% }
<TR>
@@ -544,6 +105,26 @@
% }
<TR>
+ <TD ALIGN="right" WIDTH="200"><% mt('Charge card/e-check on this day of the month') |h %> </TD>
+ <TD>
+ <SELECT NAME="billday">
+ <% billday_options($cust_main->billday) %>
+ </SELECT>
+ </TD>
+ </TR>
+
+% sub billday_options {
+% my $curr_value = shift;
+% my $ret = '';
+% for my $billday ( 1 .. 28 ) {
+% my $sel = '';
+% $sel = "SELECTED='SELECTED'" if $curr_value == $billday;
+% $ret .= "<OPTION VALUE='$billday' $sel>$billday</OPTION>";
+% }
+% $ret;
+% }
+
+ <TR>
<TD ALIGN="right" WIDTH="200"><% mt('Invoice terms') |h %> </TD>
<TD WIDTH="408">
<& /elements/select-terms.html,
@@ -673,27 +254,17 @@ function toggle(obj) {
% }
</TABLE>
+ <BR>
- <% $r %><% mt('required fields') |h %>
-% }
-
-<script type="text/javascript">
- init_payauto_changed();
-</script>
-
-<%once>
-
-my $paystate_label = FS::Msgcat::_gettext('paystate');
-$paystate_label = 'Bank state' if $paystate_label =~/^paystate$/;
+ <FONT CLASS="fsinnerbox-title"><% mt('Payment information') |h %></FONT>
+ <& cust_payby.html, 'cust_main'=>$cust_main, &>
-</%once>
<%init>
my( $cust_main, %options ) = @_;
my @invoicing_list = @{ $options{'invoicing_list'} };
my $payinfo = $options{'payinfo'};
my $conf = new FS::Conf;
-my $payby_default = $conf->config('payby-default');
my $money_char = $conf->config('money_char') || '$';
diff --git a/httemplate/edit/cust_main/bottomfixup.js b/httemplate/edit/cust_main/bottomfixup.js
index 6a9deb9..97816aa 100644
--- a/httemplate/edit/cust_main/bottomfixup.js
+++ b/httemplate/edit/cust_main/bottomfixup.js
@@ -5,7 +5,7 @@ my $conf = new FS::Conf;
my $company_latitude = $conf->config('company_latitude');
my $company_longitude = $conf->config('company_longitude');
-my @fixups = ('copy_payby_fields', 'standardize_locations');
+my @fixups = ('standardize_locations');
push @fixups, 'confirm_censustract_bill', 'confirm_censustract_ship'
if $conf->exists('cust_main-require_censustract');
@@ -51,55 +51,12 @@ function do_submit() {
document.CustomerForm.submit();
}
-function copy_payby_fields() {
- var layervars = new Array(
- 'payauto', 'billday',
- 'payinfo', 'payinfo1', 'payinfo2', 'payinfo3', 'paytype',
- 'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
- 'paystart_month', 'paystart_year', 'payissue',
- 'payip',
- 'paid'
- );
-
- var cf = document.CustomerForm;
- var payby = cf.payby.options[cf.payby.selectedIndex].value;
- for ( f=0; f < layervars.length; f++ ) {
- var field = layervars[f];
- copyelement( cf.elements[payby + '_' + field],
- cf.elements[field]
- );
- }
- submit_continue();
-}
-
<& /elements/standardize_locations.js,
'callback' => 'submit_continue();',
'billship' => 1,
'with_census' => 1, # no with_firm, apparently
&>
-function copyelement(from, to) {
- if ( from == undefined ) {
- to.value = '';
- } else if ( from.type == 'select-one' ) {
- to.value = from.options[from.selectedIndex].value;
- //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
- } else if ( from.type == 'checkbox' ) {
- if ( from.checked ) {
- to.value = from.value;
- } else {
- to.value = '';
- }
- } else {
- if ( from.value == undefined ) {
- to.value = '';
- } else {
- to.value = from.value;
- }
- }
- //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
-}
-
% # the value in pre+'censustract' is the confirmed censustract (either from
% # the previous saved record, or from address standardization (if the backend
% # supports it), or from an aborted previous submit. only need to reconfirm
diff --git a/httemplate/edit/cust_main/contact.html b/httemplate/edit/cust_main/contact.html
deleted file mode 100644
index c2ebb09..0000000
--- a/httemplate/edit/cust_main/contact.html
+++ /dev/null
@@ -1,171 +0,0 @@
-<TABLE CLASS="fsinnerbox">
-
-<TR>
- <TH ALIGN="right"><%$r%><% mt('Contact name (last, first)') |h %></TH>
- <TD COLSPAN=7>
- <INPUT TYPE="text" NAME="<%$pre%>last" VALUE="<% $cust_main->get($pre.'last') |h %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>> ,
- <INPUT TYPE="text" NAME="<%$pre%>first" VALUE="<% $cust_main->get($pre.'first') |h %>" onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- </TD>
-% if ( $conf->exists('show_ss') && !$pre ) {
-
- <TD ALIGN="right"><% mt('SS#') |h %></TD>
- <TD><INPUT TYPE="text" NAME="ss" VALUE="<% $opt{ss} %>" SIZE=11></TD>
-% } elsif ( !$pre ) {
-
- <TD><INPUT TYPE="hidden" NAME="ss" VALUE="<% $opt{ss} %>"></TD>
-% }
-</TR>
-
-% if ( $conf->exists('cust-email-high-visibility') && !$pre ) {
- <TR>
- <TD ALIGN="right" WIDTH="200">
- <% $conf->exists('cust_main-require_invoicing_list_email', $agentnum)
- ? $r : '' %>Email address(es)
- </TD>
- <TD bgcolor="#FFFF00">
- <INPUT TYPE="text" NAME="invoicing_list" VALUE="<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) %>">
- </TD>
- </TR>
-% }
-
-% unless ( $conf->exists('cust-edit-alt-field-order') ) { #standard order
-
- <& company &>
- <& location &>
- <& phones &>
- <& fax &>
-
-% } else { #alternate field order
-
- <& phones &>
- <& location &>
- <& fax &>
- <& company &>
-
-% }
-
-% if ( $conf->exists('show_stateid') && !$pre ) {
-
-<TR>
- <TD ALIGN="right"><% $stateid_label %></TD>
- <TD><INPUT TYPE="text" NAME="stateid" VALUE="<% $opt{stateid} %>" SIZE=12 onChange="<% $onchange %>" <%$disabled%> <%$style%>></TD>
- <TD ALIGN="right"><% $stateid_state_label %></TD>
- <TD><& /elements/select-state.html,
- 'state' => $cust_main->stateid_state,
- 'country' => $cust_main->country,
- 'prefix' => 'stateid_',
- 'onchange' => $onchange,
- 'disabled' => $disabled,
- 'style' => \@style,
- &>
- </TD>
-</TR>
-% } elsif ( !$pre ) {
-
- <TD><INPUT TYPE="hidden" NAME="stateid" VALUE="<% $opt{stateid} %>"></TD>
- <TD><INPUT TYPE="hidden" NAME="stateid_state" VALUE="<% $cust_main->stateid_state %>"></TD>
-% }
-
-</TABLE>
-<%$r%><% mt('required fields') |h %><BR>
-
-<%def company>
-% my $display = ($cust_main->residential_commercial eq 'Commercial')
-% ? '' : 'none';
- <TR ID="<%$pre%>company_row" STYLE="display:<%$display%>">
- <TD ALIGN="right"><% mt('Company') |h %></TD>
- <TD COLSPAN=7>
- <INPUT TYPE="text" NAME="<%$pre%>company" ID="<%$pre%>company" VALUE="<% $cust_main->get($pre.'company') |h %>" SIZE=60 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- </TD>
- </TR>
-</%def>
-
-<%def location>
- <& /elements/location.html,
- 'prefix' => $pre,
- 'object' => $cust_main,
- 'onchange' => $onchange,
- 'disabled' => $disabled,
- 'style' => \@style,
- 'same_checked' => $opt{'same_checked'},
- 'geocode' => $opt{'geocode'},
- 'censustract' => $opt{'censustract'},
- &>
-</%def>
-
-<%def phones>
- <& /elements/tr-cust_main-phones.html,
- 'prefix' => $pre,
- 'cust_main' => $cust_main,
- 'onchange' => $onchange,
- 'disabled' => $disabled,
- 'style' => $style,
- &>
-</%def>
-
-<%def fax>
- <TR>
- <TD ALIGN="right"><% mt('Fax') |h %></TD>
- <TD COLSPAN=5>
- <INPUT TYPE="text" NAME="<%$pre%>fax" VALUE="<% $cust_main->get($pre.'fax') %>" SIZE=12 onChange="<% $onchange %>" <%$disabled%> <%$style%>>
- </TD>
- </TR>
-</%def>
-
-<%once>
-
-my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
-
-</%once>
-<%shared>
-
-my( %opt, $cust_main, $pre, $onchange, $disabled, @style, $style );
-
-</%shared>
-<%init>
-
-%opt = @_;
-$cust_main = $opt{'cust_main'};
-$pre = $opt{'pre'};
-$onchange = $opt{'onchange'};
-$disabled = $opt{'disabled'};
-@style = ( $opt{'style'} ? @{ $opt{'style'} } : () );
-
-$style = scalar(@style) ? 'STYLE="'. join(';', @style). '"' : '';
-
-my $conf = new FS::Conf;
-
-foreach (qw(ss stateid)) {
- $opt{$_} = $cust_main->masked($_) unless exists $opt{$_};
-}
-
-#false laziness with ship state
-my $countrydefault = $conf->config('countrydefault') || 'US';
-$cust_main->set($pre.'country', $countrydefault )
- unless $cust_main->get($pre.'country');
-
-my $statedefault = $conf->config('statedefault')
- || ($countrydefault eq 'US' ? 'CA' : '');
-$cust_main->set($pre.'state', $statedefault )
- unless $cust_main->get($pre.'state')
- || $cust_main->get($pre.'country') ne $countrydefault;
-
-$cust_main->set('stateid_state', $cust_main->state )
- unless $pre || $cust_main->get('stateid_state');
-
-$opt{geocode} ||= $cust_main->get('geocode');
-
-$opt{censustract} ||= $cust_main->censustract;
-
-my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
- ? 'Driver&rsquo;s License'
- : FS::Msgcat::_gettext('stateid') || 'Driver&rsquo;s License';
-my $stateid_state_label = FS::Msgcat::_gettext('stateid_state') =~ /^(stateid_state)?$/
- ? 'Driver&rsquo;s License State'
- : FS::Msgcat::_gettext('stateid_state') || 'Driver&rsquo;s License State';
-
-my @invoicing_list = $cust_main->invoicing_list;
-
-my $agentnum = $cust_main->agentnum if $cust_main->custnum;
-
-</%init>
diff --git a/httemplate/edit/cust_main/contacts_new.html b/httemplate/edit/cust_main/contacts_new.html
index 0ab02b4..9ccb45f 100644
--- a/httemplate/edit/cust_main/contacts_new.html
+++ b/httemplate/edit/cust_main/contacts_new.html
@@ -1,10 +1,9 @@
<DIV ID="contacts_div" STYLE="display:<% $display %>">
-<BR>
<FONT CLASS="fsinnerbox-title">Contacts</FONT>
<% include('/edit/elements/edit.html',
'embed' => $opt{cust_main},
'table' => 'cust_main',
- 'labels' => { 'contactnum' => 'Contact',
+ 'labels' => { 'contactnum' => '', #'Contact',
#'locationnum' => '&nbsp;',
},
'fields' => [
@@ -14,7 +13,7 @@
'custnum' => $opt{cust_main}->custnum,
'm2m_method' => 'cust_contact',
'm2m_dstcol' => 'contactnum',
- 'm2_label' => 'Contact',
+ 'm2_label' => ' ', #'Contact',
'm2_error_callback' => $m2_error_callback,
},
],
diff --git a/httemplate/edit/cust_main/cust_payby.html b/httemplate/edit/cust_main/cust_payby.html
new file mode 100644
index 0000000..cf0ada9
--- /dev/null
+++ b/httemplate/edit/cust_main/cust_payby.html
@@ -0,0 +1,56 @@
+<% include('/edit/elements/edit.html',
+ 'embed' => $opt{cust_main},
+ 'tablenum' => 1,
+ 'table' => 'cust_main',
+ 'labels' => { 'custpaybynum' => '',
+ #'locationnum' => '&nbsp;',
+ },
+ 'fields' => [
+ { 'field' => 'custpaybynum',
+ 'type' => 'cust_payby',
+ 'colspan' => 6,
+ #'custnum' => $opt{cust_main}->custnum,
+ 'm2m_method' => 'cust_payby',
+ 'm2m_dstcol' => 'custpaybynum',
+ 'm2_label' => ' ',
+ 'm2_error_callback' => $m2_error_callback,
+ },
+ ],
+ 'agent_virt' => 1,
+ )
+%>
+</DIV>
+<%init>
+
+my %opt = @_;
+
+my $m2_error_callback = sub {
+ my($cgi, $object) = @_;
+
+ #process_o2m fields in process/cust_main-cust_payby.html
+ my $fields = FS::cust_payby->cgi_cust_payby_fields;
+ my @gfields = ( '', map "_$_", grep $_ !~ /^(payby|paydate_)/, @$fields );
+
+ map {
+ if ( /^custpaybynum(\d+)$/ ) {
+ my $num = $1;
+ if ( grep $cgi->param("custpaybynum$num$_"), @gfields ) {
+ my %hash = (
+ 'custpaybynum' => scalar($cgi->param("custpaybynum$num")),
+ map { $_ => scalar($cgi->param("custpaybynum${num}_$_")) }
+ @$fields,
+ );
+ FS::cust_payby::cgi_hash_callback( \%hash );
+ FS::cust_payby->new( \%hash );
+ } else {
+ ();
+ }
+ } else {
+ ();
+ }
+ }
+ $cgi->param;
+};
+
+</%init>
+
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index 4d5beee..5a7920b 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -118,6 +118,8 @@ Example:
# display, no <FORM>, no hidden fields for table name or primary key, no
# display of primary key, no submit button, no html_foot, no footer)
'embed' => $object, #need to pass the object
+ 'tablenum' => 4, #need to specify a table number when using multiple
+ #embedded edits on a page (and m2 stuff)
#don't show the primary key label and value
'no_pkey_display' => 1,
@@ -256,7 +258,7 @@ Example:
% }
-% my $tablenum = 0;
+% my $tablenum = $opt{'tablenum'} || 0;
<TABLE ID="TableNumber<% $tablenum++ %>" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
% my $g_row = 0;
diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi
index 82ec50c..52a2608 100755
--- a/httemplate/edit/process/cust_main.cgi
+++ b/httemplate/edit/process/cust_main.cgi
@@ -29,29 +29,6 @@ $cgi->param('tax','') unless defined $cgi->param('tax');
$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] );
-my $payby = $cgi->param('payby');
-
-my %noauto = (
- 'CARD' => 'DCRD',
- 'CHEK' => 'DCHK',
-);
-$payby = $noauto{$payby}
- if ! $cgi->param('payauto') && exists $noauto{$payby};
-
-$cgi->param('payby', $payby);
-
-if ( $payby ) {
- if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
- my $payinfo = $cgi->param('payinfo1'). '@';
- $payinfo .= $cgi->param('payinfo3').'.'
- if $conf->config('echeck-country') eq 'CA';
- $payinfo .= $cgi->param('payinfo2');
- $cgi->param('payinfo',$payinfo);
- }
- $cgi->param('paydate',
- $cgi->param( 'exp_month' ). '-'. $cgi->param( 'exp_year' ) );
-}
-
my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );
push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST');
push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');
@@ -177,6 +154,9 @@ if ( $curuser->access_right('Edit customer tax exemptions') ) {
};
}
+$options{'contact_params'} = scalar($cgi->Vars);
+$options{'cust_payby_params'} = scalar($cgi->Vars);
+
#perhaps this stuff should go to cust_main.pm
if ( $new->custnum eq '' or $duplicate_of ) {
@@ -304,34 +284,12 @@ if ( $new->custnum eq '' or $duplicate_of ) {
my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } );
$error ||= "Old record not found!" unless $old;
- if ( length($old->paycvv) && $new->paycvv =~ /^\s*\*+\s*$/ ) {
- $new->paycvv($old->paycvv);
- }
if ($new->ss =~ /xx/) {
$new->ss($old->ss);
}
if ($new->stateid =~ /^xxx/) {
$new->stateid($old->stateid);
}
- if ( $new->payby =~ /^(CARD|DCRD)$/
- && ( $new->payinfo =~ /xx/
- || $new->payinfo =~ /^\s*N\/A\s+\(tokenized\)\s*$/
- )
- )
- {
- $new->payinfo($old->payinfo);
-
- } elsif ( $new->payby =~ /^(CHEK|DCHK)$/ && $new->payinfo =~ /xx/ ) {
- #fix for #3085 "edit of customer's routing code only surprisingly causes
- #nothing to happen...
- # this probably won't do the right thing when we don't have the
- # public key (can't actually get the real $old->payinfo)
- my($new_account, $new_aba) = split('@', $new->payinfo);
- my($old_account, $old_aba) = split('@', $old->payinfo);
- $new_account = $old_account if $new_account =~ /xx/;
- $new_aba = $old_aba if $new_aba =~ /xx/;
- $new->payinfo($new_account.'@'.$new_aba);
- }
if ( ! $conf->exists('cust_main-edit_signupdate') or
! $new->signupdate ) {
@@ -353,13 +311,4 @@ if ( $new->custnum eq '' or $duplicate_of ) {
}
-unless ( $error ) { #XXX i should be transactional... all in the insert
- # or replace call
-
- $error = $new->process_o2m( 'table' => 'contact',
- 'fields' => FS::contact->cgi_contact_fields,
- 'params' => scalar($cgi->Vars),
- );
-}
-
</%init>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index 5f6921c..7d5d4f3 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -127,6 +127,7 @@ $report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_m
if ( $curuser->access_right('List contacts') ) {
$report_customers{'separator'} = '';
$report_customers{'Customer contacts'} = [ $fsurl. 'search/report_contact.html?link=cust_main' ];
+ $report_customers{'Customer stored payment information'} = [ $fsurl. 'search/report_cust_payby.html' ];
}
tie my %report_invoices_open, 'Tie::IxHash',
diff --git a/httemplate/elements/tr-coords.html b/httemplate/elements/tr-coords.html
index 3248dc2..5ac5ed4 100644
--- a/httemplate/elements/tr-coords.html
+++ b/httemplate/elements/tr-coords.html
@@ -1,6 +1,6 @@
<TR>
<TD ALIGN="right"><% mt('Latitude') |h %></TD>
- <TD COLSPAN=5>
+ <TD COLSPAN=7>
<FONT STYLE="background-color: #ffffff; border: 1px solid #ffffff"><% $latitude %></FONT>
&nbsp;<% mt('Longitude') |h %>
<FONT STYLE="background-color: #ffffff; border: 1px solid #ffffff"><% $longitude %></FONT>
diff --git a/httemplate/search/cust_main.html b/httemplate/search/cust_main.html
index 503e782..672c201 100755
--- a/httemplate/search/cust_main.html
+++ b/httemplate/search/cust_main.html
@@ -42,7 +42,7 @@ my %search_hash = ();
#scalars
my @scalars = qw (
agentnum salesnum status address city county state zip country
- paydate_year paydate_month invoice_terms
+ invoice_terms
no_censustract with_geocode with_email tax no_tax POST no_POST
custbatch usernum
cancelled_pkgs
@@ -58,7 +58,7 @@ for my $param ( @scalars ) {
}
#lists
-for my $param (qw( classnum refnum payby tagnum pkg_classnum )) {
+for my $param (qw( classnum refnum tagnum pkg_classnum )) {
$search_hash{$param} = [ $cgi->param($param) ];
}
diff --git a/httemplate/search/cust_payby.html b/httemplate/search/cust_payby.html
new file mode 100644
index 0000000..140391b
--- /dev/null
+++ b/httemplate/search/cust_payby.html
@@ -0,0 +1,94 @@
+<& elements/search.html,
+ 'title' => emt('Customer stored payment information results'),
+ 'menubar' => $menubar,
+ 'name' => emt('cards or bank accounts'), #??
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'header' => [ @headers,
+ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ ),
+ ],
+ 'fields' => [
+ @fields,
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'color' => [
+ ( map '', @fields ),
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ ( map '', @fields ),
+ FS::UI::Web::cust_styles(),
+ ],
+ 'align' => [
+ ( map '', @fields ),
+ FS::UI::Web::cust_aligns(),
+ ],
+ 'links' => [
+ ( map '', @fields ),
+ ( map { $_ ne 'Cust. Status' ? $link : '' }
+ FS::UI::Web::cust_header(
+ $cgi->param('cust_fields')
+ )
+ ),
+ ],
+&>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Advanced customer search');
+
+my %search_hash = ();
+
+my @scalars = qw (
+ paydate_year paydate_month
+);
+
+for my $param ( @scalars ) {
+ $search_hash{$param} = scalar( $cgi->param($param) )
+ if length($cgi->param($param));
+}
+
+#lists
+for my $param (qw( payby )) {
+ $search_hash{$param} = [ $cgi->param($param) ];
+}
+
+###
+# etc
+###
+
+my $sql_query = FS::cust_payby->search_sql(\%search_hash);
+my $count_query = delete($sql_query->{'count_query'});
+
+my @headers = ( 'Payment information',
+ );
+
+my @fields = ( sub { my $cust_payby = shift;
+ FS::payby->shortname( $cust_payby->payby ). ' '.
+ $cust_payby->paymask;
+ }
+ );
+
+my $link = [ "${p}view/cust_main.cgi?", 'custnum' ];
+
+###
+# email links
+###
+
+my $menubar = [];
+
+#XXX TODO
+#if ( $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices') ) {
+#
+# my $uri = new URI;
+# $uri->query_form( \%search_hash );
+# my $query = $uri->query;
+#
+# push @$menubar, emt('Email a notice to these customers') =>
+# "${p}misc/email-customers.html?table=cust_main&$query",
+#
+#}
+
+</%init>
diff --git a/httemplate/search/report_cust_main.html b/httemplate/search/report_cust_main.html
index cacb7de..ba7c99a 100755
--- a/httemplate/search/report_cust_main.html
+++ b/httemplate/search/report_cust_main.html
@@ -194,43 +194,6 @@
<TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1"><% mt('Billing search options') |h %></FONT></TH>
</TR>
- <& /elements/tr-select-payby.html,
- 'payby_type' => 'cust',
- 'multiple' => 1,
- 'all_selected' => 1,
- &>
-
- <TR>
- <TD ALIGN="right"><% mt('Payment expiration before') |h %></TD>
- <TD>
- <SELECT NAME="paydate_month" DISABLED>
-% foreach my $month ( 1 .. 12 ) {
- <OPTION VALUE="<% $month %>"><% $month %></OPTION>
-% }
- </SELECT>
- /
- <SELECT NAME="paydate_year" onChange="paydate_year_changed(this);">
- <OPTION VALUE=""></OPTION>
-% my $lastyear = (localtime(time))[5] + 1899;
-% foreach my $year ( $lastyear .. $lastyear+12 ) {
- <OPTION VALUE="<% $year %>"><% $year %></OPTION>
-% }
- </SELECT>
- </TD>
- </TR>
-
- <SCRIPT TYPE="text/javascript">
- function paydate_year_changed(what) {
- var value = what.options[what.selectedIndex].value;
- var month_select = what.form.paydate_month;
- if ( value == '' ) {
- month_select.disabled = true;
- } else {
- month_select.disabled = false;
- }
- }
- </SCRIPT>
-
% my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups');
% unless ( @exempt_groups ) {
diff --git a/httemplate/search/report_cust_payby.html b/httemplate/search/report_cust_payby.html
new file mode 100644
index 0000000..81a8270
--- /dev/null
+++ b/httemplate/search/report_cust_payby.html
@@ -0,0 +1,57 @@
+<& /elements/header.html, mt('Customer stored payment infomation report') &>
+
+<FORM ACTION="cust_payby.html" METHOD="GET">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+
+ <& /elements/tr-select-payby.html,
+ 'payby_type' => 'cust',
+ 'multiple' => 1,
+ 'all_selected' => 1,
+ &>
+
+ <TR>
+ <TD ALIGN="right"><% mt('Payment expiration before') |h %></TD>
+ <TD>
+ <SELECT NAME="paydate_month" DISABLED>
+% foreach my $month ( 1 .. 12 ) {
+ <OPTION VALUE="<% $month %>"><% $month %></OPTION>
+% }
+ </SELECT>
+ /
+ <SELECT NAME="paydate_year" onChange="paydate_year_changed(this);">
+ <OPTION VALUE=""></OPTION>
+% my $lastyear = (localtime(time))[5] + 1899;
+% foreach my $year ( $lastyear .. $lastyear+12 ) {
+ <OPTION VALUE="<% $year %>"><% $year %></OPTION>
+% }
+ </SELECT>
+ </TD>
+ </TR>
+
+ <SCRIPT TYPE="text/javascript">
+ function paydate_year_changed(what) {
+ var value = what.options[what.selectedIndex].value;
+ var month_select = what.form.paydate_month;
+ if ( value == '' ) {
+ month_select.disabled = true;
+ } else {
+ month_select.disabled = false;
+ }
+ }
+ </SCRIPT>
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="<% mt('Get Report') |h %>">
+
+</FORM>
+
+<& /elements/footer.html &>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Advanced customer search');
+
+</%init>
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index d18c7f7..081b96b 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -169,14 +169,12 @@ function areyousure(href, message) {
<TABLE BORDER=0>
<TR>
<TD VALIGN="top">
- <& cust_main/contacts.html, $cust_main &>
+ <& cust_main/misc.html, $cust_main &>
+ <BR><& cust_main/contacts.html, $cust_main &>
</TD>
<TD VALIGN="top" STYLE="padding-left: 54px">
- <& cust_main/misc.html, $cust_main &>
-% if ( $conf->config('payby-default') ne 'HIDE' ) {
- <BR><& cust_main/billing.html, $cust_main &>
-% }
-
+ <& cust_main/billing.html, $cust_main &>
+ <BR><& cust_main/cust_payby.html, $cust_main &>
</TD>
</TR>
<TR>
@@ -281,9 +279,7 @@ function areyousure(href, message) {
% if ( $view eq 'payment_history' || $view eq 'jumbo' ) {
-% if ( $conf->config('payby-default') ne 'HIDE' ) {
- <& cust_main/payment_history.html, $cust_main &>
-% }
+<& cust_main/payment_history.html, $cust_main &>
% }
@@ -352,8 +348,7 @@ if ( $conf->config('ticket_system') ) {
}
$views{emt('Quotations')} = 'quotations';
$views{emt('Packages')} = 'packages';
-$views{emt('Payment History')} = 'payment_history'
- unless $conf->config('payby-default' eq 'HIDE');
+$views{emt('Payment History')} = 'payment_history';
$views{emt('Change History')} = 'change_history'
if $curuser->access_right('View customer history');
$views{$conf->config('cust_main-custom_title') || emt('Custom')} = 'custom'
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index 64ec591..f1125c0 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -32,165 +32,25 @@
% }
% if ( $conf->exists('cust_main-select-billday')
-% && ($cust_main->payby eq 'CARD' || $cust_main->payby eq 'CHEK') ) {
-<TR>
- <TD ALIGN="right"><% mt('Billing day of month') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->billday %>
- </TD>
-</TR>
-% }
-
-<TR>
- <TD ALIGN="right"><% mt('Billing type') |h %></TD>
- <TD BGCOLOR="#ffffff">
-% if ( $cust_main->payby eq 'CARD' || $cust_main->payby eq 'DCRD' ) {
-
-% my $autodemand = $cust_main->payby eq 'CARD' ? 'automatic' : 'on-demand';
- <% mt("Credit card ([_1])",$autodemand) |h %>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Card number') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->paymask %></TD>
-</TR>
-%
-%#false laziness w/elements/select-month_year.html & edit/cust_main/billing.html
-%my( $mon, $year );
-%my $date = $cust_main->paydate || '12-2037';
-%if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
-% ( $mon, $year ) = ( $2, $1 );
-%} elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
-% ( $mon, $year ) = ( $1, $3 );
-%} else {
-% warn "unrecognized expiration date format: $date";
-% ( $mon, $year ) = ( '', '' );
-%}
-%
-
-<TR>
- <TD ALIGN="right"><% mt('Expiration') |h %></TD>
- <TD BGCOLOR="#ffffff"><% "$mon/$year" %></TD>
-</TR>
-% if ( $cust_main->paystart_month ) {
-
- <TR>
- <TD ALIGN="right"><% mt('Start date') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->paystart_month. '/'. $cust_main->paystart_year %>
- </TR>
-% } elsif ( $cust_main->payissue ) {
-
- <TR>
- <TD ALIGN="right"><% mt('Issue #') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payissue %>
- </TR>
-% }
-
-
-<TR>
- <TD ALIGN="right"><% mt('Name on card') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
-</TR>
-% } elsif ( $cust_main->payby eq 'CHEK' || $cust_main->payby eq 'DCHK') {
-% my( $account, $aba ) = split('@', $cust_main->paymask );
-% my $branch = '';
-% ($branch,$aba) = split('\.',$aba) if $conf->config('echeck-country') eq 'CA';
-
-
-% my $autodemand = $cust_main->payby eq 'CHEK' ? 'automatic' : 'on-demand';
- <% mt("Electronic check ([_1])",$autodemand) |h %>
- </TD>
-</TR>
-
-% #false laziness w/edit/cust_main/billing.html and misc/payment.cgi
-% my $routing_label = $conf->config('echeck-country') eq 'US'
-% ? 'ABA/Routing number'
-% : 'Routing number';
-
-<TR>
- <TD ALIGN="right"><% mt($routing_label) |h %></TD>
- <TD BGCOLOR="#ffffff"><% $aba %></TD>
-</TR>
-
-% if ( $conf->config('echeck-country') eq 'CA' ) {
-<TR>
- <TD ALIGN="right"><% mt('Branch number') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $branch %></TD>
-<TR>
-% }
-
- <TD ALIGN="right"><% mt('Account number') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $account %></TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Account type') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->paytype %></TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Bank name') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payname %></TD>
-</TR>
-% if ( $conf->exists('show_bankstate') ) {
-<TR>
- <TD ALIGN="right"><% $paystate_label %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->paystate || '&nbsp;&nbsp;&nbsp;' %></TD>
-</TR>
+% && qsearch({ 'table' => 'cust_payby',
+% 'hashref' => { 'custnum' => $cust_main->custnum, },
+% 'extra_sql' => "AND payby IN ( 'CARD', 'CHEK' )",
+% 'order_by' => 'LIMIT 1',
+% })
+% )
+% {
+ <TR>
+ <TD ALIGN="right"><% mt('Payment day of month') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->billday %>
+ </TD>
+ </TR>
% }
-% } elsif ( $cust_main->payby eq 'LECB' ) {
-% $cust_main->payinfo =~ /^(\d{3})(\d{3})(\d{4})$/;
-% my $payinfo = "$1-$2-$3";
-
- <% mt('Phone bill billing') |h %>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Phone number') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $payinfo %></TD>
-</TR>
-% } elsif ( $cust_main->payby eq 'BILL' ) {
-
- <% mt('Billing') |h %>
- </TD>
-</TR>
-% if ( $cust_main->payinfo ) {
-
-<TR>
- <TD ALIGN="right"><% mt('P.O.') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payinfo %></TD>
-</TR>
-% }
-
-<TR>
- <TD ALIGN="right"><% mt('Attention') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payname |h %></TD>
-</TR>
-% } elsif ( $cust_main->payby eq 'COMP' ) {
-
- <% mt('Complimentary') |h %>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Authorized by') |h %></TD>
- <TD BGCOLOR="#ffffff"><% $cust_main->payinfo %></TD>
-</TR>
-%
-%#false laziness w/above etc.
-%my( $mon, $year );
-%my $date = $cust_main->paydate || '12-2037';
-%if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
-% ( $mon, $year ) = ( $2, $1 );
-%} elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
-% ( $mon, $year ) = ( $1, $3 );
-%} else {
-% warn "unrecognized expiration date format: $date";
-% ( $mon, $year ) = ( '', '' );
-%}
-%
-
-<TR>
- <TD ALIGN="right"><% mt('Expiration') |h %></TD>
- <TD BGCOLOR="#ffffff"><% "$mon/$year" %></TD>
-</TR>
+% if ( $cust_main->po_number ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Purchase Order #') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->po_number %></TD>
+ </TR>
% }
% my $yes = emt('yes');
@@ -230,13 +90,13 @@
<TR>
<TD ALIGN="right"><% mt('Postal mail invoices') |h %></TD>
<TD BGCOLOR="#ffffff">
- <% ( grep { $_ eq 'POST' } @invoicing_list ) ? $yes : $no %>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Fax invoices') |h %></TD>
- <TD BGCOLOR="#ffffff">
- <% ( grep { $_ eq 'FAX' } @invoicing_list ) ? $yes : $no %>
+ <% ( grep { $_ eq 'POST' } @invoicing_list )
+ ? $yes. ( $cust_main->invoice_attn
+ ? ', attn: '. $cust_main->invoice_attn
+ : ''
+ )
+ : $no
+ %>
</TD>
</TR>
<TR>
@@ -336,12 +196,6 @@
</TABLE>
-<%once>
-
-my $paystate_label = FS::Msgcat::_gettext('paystate');
-$paystate_label = 'Bank state' if $paystate_label =~/^paystate$/;
-
-</%once>
<%init>
my( $cust_main ) = @_;
diff --git a/httemplate/view/cust_main/cust_payby.html b/httemplate/view/cust_main/cust_payby.html
new file mode 100644
index 0000000..3ebb055
--- /dev/null
+++ b/httemplate/view/cust_main/cust_payby.html
@@ -0,0 +1,133 @@
+% if ( @cust_payby ) {
+
+ <FONT CLASS="fsinnerbox-title"><% mt('Payment information') |h %></FONT>
+ <TABLE CLASS="fsinnerbox">
+
+% my $num = 0;
+% foreach my $cust_payby ( @cust_payby ) {
+
+% #one line per piece of info? maybe, but just getting something working
+% # for now
+
+% if ( $cust_payby->payby eq 'CARD' || $cust_payby->payby eq 'DCRD' ) {
+
+% my $auto = $cust_payby->payby eq 'CARD' ? 'automatic' : 'on-demand';
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" BGCOLOR="#ffffff">
+ <% mt("Credit card ([_1])",$auto) |h %>
+ </TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><% mt('Card number') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->paymask %></TD>
+ </TR>
+
+% my( $mon, $year ) = $cust_payby->paydate_mon_year;
+ <TR>
+ <TD ALIGN="right"><% mt('Expiration') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% "$mon/$year" %></TD>
+ </TR>
+
+% if ( $cust_payby->paystart_month ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Start date') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->paystart_month. '/'. $cust_payby->paystart_year %>
+ </TR>
+% } elsif ( $cust_payby->payissue ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Issue #') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->payissue %>
+ </TR>
+% }
+
+ <TR>
+ <TD ALIGN="right"><% mt('Name on card') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->payname %></TD>
+ </TR>
+
+% } elsif ( $cust_payby->payby eq 'CHEK' || $cust_payby->payby eq 'DCHK') {
+
+% my $auto = $cust_payby->payby eq 'CHEK' ? 'automatic' : 'on-demand';
+%
+% my( $account, $aba ) = split('@', $cust_payby->paymask );
+% my $branch = '';
+% ($branch,$aba) = split('\.',$aba)
+% if $conf->config('echeck-country') eq 'CA';
+
+ <TR>
+ <TD COLSPAN=2 ALIGN="center" BGCOLOR="#ffffff">
+ <% mt("Electronic check ([_1])",$auto) |h %>
+ </TD>
+ </TR>
+
+% #false laziness w/edit/cust_main/billing.html and misc/payment.cgi
+% my $routing_label = $conf->config('echeck-country') eq 'US'
+% ? 'ABA/Routing number'
+% : 'Routing number';
+ <TR>
+ <TD ALIGN="right"><% mt($routing_label) |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $aba %></TD>
+ </TR>
+
+% if ( $conf->config('echeck-country') eq 'CA' ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Branch number') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $branch %></TD>
+ </TR>
+% }
+
+ <TR>
+ <TD ALIGN="right"><% mt('Account number') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $account %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><% mt('Account type') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->paytype %></TD>
+ </TR>
+ <TR>
+ <TD ALIGN="right"><% mt('Bank name') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->payname %></TD>
+ </TR>
+
+% if ( $conf->exists('show_bankstate') ) {
+ <TR>
+ <TD ALIGN="right"><% $paystate_label %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_payby->paystate || '&nbsp;&nbsp;&nbsp;' %></TD>
+ </TR>
+% }
+
+% } else {
+ <TR>
+ <TD COLSPAN="2"><FONT COLOR="#FF0000">
+ Unknown cust_pay.payby <% $cust_payby->payby %>
+ </FONT></TD>
+ </TR>
+% }
+
+% unless ( $num++ == $#cust_payby ) {
+ <TR>
+ <TD COLSPAN="2"></TD>
+ </TR>
+ <TR>
+ <TD COLSPAN="2" STYLE="border-top: 1px solid black; padding:2px"></TD>
+ </TR>
+% }
+
+% }
+
+ </TABLE>
+
+% }
+<%once>
+
+my $paystate_label = FS::Msgcat::_gettext('paystate');
+$paystate_label = 'Bank state' if $paystate_label =~/^paystate$/;
+
+</%once>
+<%init>
+
+my( $cust_main ) = @_;
+my $conf = new FS::Conf;
+my @cust_payby = $cust_main->cust_payby;
+
+</%init>
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 9a2332b..9098511 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -92,9 +92,7 @@ if ( el ) el.scrollIntoView(true);
<& /elements/order_pkg_link.html, 'cust_main'=>$cust_main &>
% }
-% if ( $curuser->access_right('One-time charge')
-% && $conf->config('payby-default') ne 'HIDE'
-% ) {
+% if ( $curuser->access_right('One-time charge') ) {
<% $s++ ? ' | ' : '' %>
<& /elements/one_time_charge_link.html, 'custnum'=>$cust_main->custnum &>
% }