have the UI use full country names, and state names outside the US...
[freeside.git] / FS / FS / cust_main.pm
index b5ccf5a..a2eb724 100644 (file)
@@ -16,6 +16,7 @@ BEGIN {
 }
 use Digest::MD5 qw(md5_base64);
 use Date::Format;
+use Date::Parse;
 #use Date::Manip;
 use String::Approx qw(amatch);
 use Business::CreditCard 0.28;
@@ -118,8 +119,6 @@ FS::cust_main - Object methods for cust_main records
   $error = $record->collect;
   $error = $record->collect %options;
   $error = $record->collect 'invoice_time'   => $time,
-                            'batch_card'     => 'yes',
-                            'report_badcard' => 'yes',
                           ;
 
 =head1 DESCRIPTION
@@ -285,6 +284,8 @@ sub paymask {
 
 =item referral_custnum - referring customer number
 
+=item spool_cdr - Enable individual CDR spooling, empty or `Y'
+
 =back
 
 =head1 METHODS
@@ -335,7 +336,7 @@ Currently available options are: I<depend_jobnum> and I<noexport>.
 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).
 This can be used to defer provisioning until some action completes (such
-as running the customer's credit card sucessfully).
+as running the customer's credit card successfully).
 
 The I<noexport> option is deprecated.  If I<noexport> is set true, no
 provisioning jobs (exports) are scheduled.  (You can schedule them later with
@@ -479,7 +480,7 @@ Currently available options are: I<depend_jobnum> and I<noexport>.
 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).
 This can be used to defer provisioning until some action completes (such
-as running the customer's credit card sucessfully).
+as running the customer's credit card successfully).
 
 The I<noexport> option is deprecated.  If I<noexport> is set true, no
 provisioning jobs (exports) are scheduled.  (You can schedule them later with
@@ -1258,7 +1259,11 @@ sub check {
 
     my $payinfo = $self->payinfo;
     $payinfo =~ s/[^\d\@]//g;
-    $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba';
+    if ( $conf->exists('echeck-nonus') ) {
+      $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account@aba';
+    } else {
+      $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba';
+    }
     $payinfo = "$1\@$2";
     $self->payinfo($payinfo);
     $self->paycvv('') if $self->dbdef_table->column('paycvv');
@@ -1306,7 +1311,7 @@ sub check {
   }
 
   if ( $self->paydate eq '' || $self->paydate eq '-' ) {
-    return "Expriation date required"
+    return "Expiration date required"
       unless $self->payby =~ /^(BILL|PREPAY|CHEK|DCHK|LECB|CASH|WEST|MCRD)$/;
     $self->paydate('');
   } else {
@@ -1337,8 +1342,10 @@ sub check {
     $self->payname($1);
   }
 
-  $self->tax =~ /^(Y?)$/ or return "Illegal tax: ". $self->tax;
-  $self->tax($1);
+  foreach my $flag (qw( tax spool_cdr )) {
+    $self->$flag() =~ /^(Y?)$/ or return "Illegal $flag: ". $self->$flag();
+    $self->$flag($1);
+  }
 
   $self->otaker(getotaker) unless $self->otaker;
 
@@ -1641,6 +1648,7 @@ sub bill {
 
   my( $total_setup, $total_recur ) = ( 0, 0 );
   my %tax;
+  my @precommit_hooks = ();
 
   foreach my $cust_pkg (
     qsearch('cust_pkg', { 'custnum' => $self->custnum } )
@@ -1674,7 +1682,7 @@ sub bill {
       $setup = eval { $cust_pkg->calc_setup( $time ) };
       if ( $@ ) {
         $dbh->rollback if $oldAutoCommit;
-        return $@;
+        return "$@ running calc_setup for $cust_pkg\n";
       }
 
       $cust_pkg->setfield('setup', $time) unless $cust_pkg->setup;
@@ -1696,10 +1704,13 @@ sub bill {
       # XXX shared with $recur_prog
       $sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
 
-      $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details ) };
+      #over two params!  lets at least switch to a hashref for the rest...
+      my %param = ( 'precommit_hooks' => \@precommit_hooks, );
+
+      $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details, \%param ) };
       if ( $@ ) {
         $dbh->rollback if $oldAutoCommit;
-        return $@;
+        return "$@ running calc_recur for $cust_pkg\n";
       }
 
       #change this bit to use Date::Manip? CAREFUL with timezones (see
@@ -1886,7 +1897,7 @@ sub bill {
                   $dbh->rollback if $oldAutoCommit;
                   return "fatal: can't lookup exising exemption: ". dbh->errstr;
                 };
-                my $existing_exemption = $sth->fetchrow_arrayref->[0];
+                my $existing_exemption = $sth->fetchrow_arrayref->[0] || 0;
                 
                 my $remaining_exemption =
                   $tax->exempt_amount - $existing_exemption;
@@ -1971,6 +1982,16 @@ sub bill {
     $dbh->rollback if $oldAutoCommit;
     return "can't update charged for invoice #$invnum: $error";
   }
+
+  foreach my $hook ( @precommit_hooks ) { 
+    eval {
+      &{$hook}; #($self) ?
+    };
+    if ( $@ ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "$@ running precommit hook $hook\n";
+    }
+  }
   
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   ''; #no error
@@ -2001,17 +2022,11 @@ for conversion functions.
 retry - Retry card/echeck/LEC transactions even when not scheduled by invoice
 events.
 
-retry_card - Deprecated alias for 'retry'
-
-batch_card - This option is deprecated.  See the invoice events web interface
-to control whether cards are batched or run against a realtime gateway.
-
-report_badcard - This option is deprecated.
-
-force_print - This option is deprecated; see the invoice events web interface.
-
 quiet - set true to surpress email card/ACH decline notices.
 
+freq - "1d" for the traditional, daily events (the default), or "1m" for the
+new monthly events
+
 =cut
 
 sub collect {
@@ -2052,6 +2067,13 @@ sub collect {
     }
   }
 
+  my $extra_sql = '';
+  if ( defined $options{'freq'} && $options{'freq'} eq '1m' ) {
+    $extra_sql = " AND freq = '1m' ";
+  } else {
+    $extra_sql = " AND ( freq = '1d' OR freq IS NULL OR freq = '' ) ";
+  }
+
   foreach my $cust_bill ( $self->open_cust_bill ) {
 
     # don't try to charge for the same invoice if it's already in a batch
@@ -2073,8 +2095,12 @@ sub collect {
                                 'status'    => 'done',
                                                                    } )
              }
-          qsearch('part_bill_event', { 'payby'    => $self->payby,
-                                       'disabled' => '',           } )
+          qsearch( {
+            'table'     => 'part_bill_event',
+            'hashref'   => { 'payby'    => $self->payby,
+                             'disabled' => '',           },
+            'extra_sql' => $extra_sql,
+          } )
     ) {
 
       last if $cust_bill->owed <= 0  # don't run subsequent events if owed<=0
@@ -2208,7 +2234,7 @@ if set, will override the value from the customer record.
 I<description> is a free-text field passed to the gateway.  It defaults to
 "Internet services".
 
-If an I<invnum> is specified, this payment (if sucessful) is applied to the
+If an I<invnum> is specified, this payment (if successful) is applied to the
 specified invoice.  If you don't specify an I<invnum> you might want to
 call the B<apply_payments> method.
 
@@ -2462,7 +2488,7 @@ sub realtime_bop {
     $capture->submit();
 
     unless ( $capture->is_success ) {
-      my $e = "Authorization sucessful but capture failed, custnum #".
+      my $e = "Authorization successful but capture failed, custnum #".
               $self->custnum. ': '.  $capture->result_code.
               ": ". $capture->error_message;
       warn $e;
@@ -2642,7 +2668,7 @@ gateway is attempted.
 #I<zip>, I<payinfo> and I<paydate> are also available.  Any of these options,
 #if set, will override the value from the customer record.
 
-#If an I<invnum> is specified, this payment (if sucessful) is applied to the
+#If an I<invnum> is specified, this payment (if successful) is applied to the
 #specified invoice.  If you don't specify an I<invnum> you might want to
 #call the B<apply_payments> method.
 
@@ -3961,8 +3987,6 @@ sub batch_import {
   my $pkgpart = $param->{pkgpart};
   my @fields = @{$param->{fields}};
 
-  eval "use Date::Parse;";
-  die $@ if $@;
   eval "use Text::CSV_XS;";
   die $@ if $@;
 
@@ -4068,8 +4092,6 @@ sub batch_charge {
   my $fh = $param->{filehandle};
   my @fields = @{$param->{fields}};
 
-  eval "use Date::Parse;";
-  die $@ if $@;
   eval "use Text::CSV_XS;";
   die $@ if $@;