X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=FS%2FFS%2Fcust_main.pm;h=1b059e6c2e09e91c4ac0a99a6628597a6231b45d;hb=0b81782a6257456e04fb8a5a7faf0dbfbf7bc166;hp=22c16fbaabdbd9c296e5288f085f89a36db1c7fc;hpb=9b37fb82c94a480ef6af2f7b9a8b889d4381e703;p=freeside.git diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 22c16fbaa..1b059e6c2 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -324,6 +324,10 @@ A suggestion to events (see L) to delay until this unix ti Discourage individual CDR printing, empty or `Y' +=item edit_subject + +Allow self-service editing of ticket subjects, empty or 'Y' + =back =head1 METHODS @@ -1681,6 +1685,8 @@ sub check { || $self->ut_alphan('geocode') || $self->ut_floatn('cdr_termination_percentage') || $self->ut_floatn('credit_limit') + || $self->ut_numbern('billday') + || $self->ut_enum('edit_subject', [ '', 'Y' ] ) ; #barf. need message catalogs. i18n. etc. @@ -1847,7 +1853,7 @@ sub check { my $payinfo = $self->payinfo; $payinfo =~ s/\D//g; - $payinfo =~ /^(\d{13,16})$/ + $payinfo =~ /^(\d{13,16}|\d{8,9})$/ or return gettext('invalid_card'); # . ": ". $self->payinfo; $payinfo = $1; $self->payinfo($payinfo); @@ -1909,8 +1915,12 @@ sub check { } elsif ( $check_payinfo && $self->payby =~ /^(CHEK|DCHK)$/ ) { my $payinfo = $self->payinfo; - $payinfo =~ s/[^\d\@]//g; - if ( $conf->exists('echeck-nonus') ) { + $payinfo =~ s/[^\d\@\.]//g; + if ( $conf->exists('cust_main-require-bank-branch') ) { + $payinfo =~ /^(\d+)\@(\d+)\.(\d+)$/ or return 'invalid echeck account@branch.bank'; + $payinfo = "$1\@$2.$3"; + } + elsif ( $conf->exists('echeck-nonus') ) { $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@aba'; $payinfo = "$1\@$2"; } else { @@ -2905,6 +2915,60 @@ sub paydate_monthyear { } } +=item paydate_epoch + +Returns the exact time in seconds corresponding to the payment method +expiration date. For CARD/DCRD customers this is the end of the month; +for others (COMP is the only other payby that uses paydate) it's the start. +Returns 0 if the paydate is empty or set to the far future. + +=cut + +sub paydate_epoch { + my $self = shift; + my ($month, $year) = $self->paydate_monthyear; + return 0 if !$year or $year >= 2037; + if ( $self->payby eq 'CARD' or $self->payby eq 'DCRD' ) { + $month++; + if ( $month == 13 ) { + $month = 1; + $year++; + } + return timelocal(0,0,0,1,$month-1,$year) - 1; + } + else { + return timelocal(0,0,0,1,$month-1,$year); + } +} + +=item paydate_epoch_sql + +Class method. Returns an SQL expression to obtain the payment expiration date +as a number of seconds. + +=cut + +# Special expiration date behavior for non-CARD/DCRD customers has been +# carefully preserved. Do we really use that? +sub paydate_epoch_sql { + my $class = shift; + my $table = shift || 'cust_main'; + my ($case1, $case2); + if ( driver_name eq 'Pg' ) { + $case1 = "EXTRACT( EPOCH FROM CAST( $table.paydate AS TIMESTAMP ) + INTERVAL '1 month') - 1"; + $case2 = "EXTRACT( EPOCH FROM CAST( $table.paydate AS TIMESTAMP ) )"; + } + elsif ( lc(driver_name) eq 'mysql' ) { + $case1 = "UNIX_TIMESTAMP( DATE_ADD( CAST( $table.paydate AS DATETIME ), INTERVAL 1 month ) ) - 1"; + $case2 = "UNIX_TIMESTAMP( CAST( $table.paydate AS DATETIME ) )"; + } + else { return '' } + return "CASE WHEN $table.payby IN('CARD','DCRD') + THEN ($case1) + ELSE ($case2) + END" +} + =item tax_exemption TAXNAME =cut @@ -3409,7 +3473,7 @@ sub charge { sub charge_postal_fee { my $self = shift; - my $pkgpart = $conf->config('postal_invoice-fee_pkgpart'); + my $pkgpart = $conf->config('postal_invoice-fee_pkgpart', $self->agentnum); return '' unless ($pkgpart && grep { $_ eq 'POST' } $self->invoicing_list); my $cust_pkg = new FS::cust_pkg ( { @@ -4213,7 +4277,7 @@ sub balance_date_sql { =item unapplied_payments_date_sql START_TIME [ END_TIME ] Returns an SQL fragment to retreive the total unapplied payments for this -customer, only considering invoices with date earlier than START_TIME, and +customer, only considering payments with date earlier than START_TIME, and optionally not later than END_TIME. Times are specified as SQL fragments or numeric