add option for multi-process billing to queue additional jobs for the same customer...
[freeside.git] / FS / FS / Cron / bill.pm
index d046930..b0d1f32 100644 (file)
@@ -22,7 +22,8 @@ use FS::Log;
 #  -s: re-charge setup fees
 #  -v: enable debugging
 #  -l: debugging level
-#  -m: Experimental multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+#  -m: Multi-process mode uses the job queue for multi-process and/or multi-machine billing.
+#  -q: Multi-process mode: queue additional job instead of skipping
 #  -r: Multi-process mode dry run option
 #  -g: Don't bill these pkgparts
 
@@ -100,6 +101,7 @@ sub bill {
           'resetup'      => ( $opt{'s'} ? $opt{'s'} : 0 ),
           'not_pkgpart'  => $opt{'g'}, #$not_pkgpart,
           'one_recur'    => $opt{'o'},
+          'no_prepaid'   => 1,
       );
 
       if ( $opt{'m'} ) {
@@ -108,12 +110,15 @@ sub bill {
           warn "DRY RUN: would add custnum $custnum for queued_bill\n";
         } else {
 
+          my @waiting = qsearch( 'queue', {
+                                  'job'     => 'FS::cust_main::queued_bill',
+                                   'custnum' => $custnum,
+                                   'status'  => 'new',
+                                 }
+                              );
+
           #avoid queuing another job if there's one still waiting to run
-          next if qsearch( 'queue', { 'job'     => 'FS::cust_main::queued_bill',
-                                      'custnum' => $custnum,
-                                      'status'  => 'new',
-                                    }
-                         );
+          next if @waiting && ! $opt{'q'};
 
           #add job to queue that calls bill_and_collect with options
           my $queue = new FS::queue {
@@ -122,6 +127,12 @@ sub bill {
             'priority' => 99, #don't get in the way of provisioning jobs
           };
           my $error = $queue->insert( 'custnum'=>$custnum, %args );
+          die $error if $error;
+
+          #wait until the earler jobs complete
+          foreach $waiting_queue (@waiting) {
+            $queue->depend_insert($waiting_queue->jobnum);
+          }
 
         }
 
@@ -131,7 +142,12 @@ sub bill {
         if ( $disable_bill ) {
           $cust_main->collect( %args, 'debug' => $debug );
         } else {
-          $cust_main->bill_and_collect( %args, 'debug' => $debug );
+          my $error = $cust_main->bill_and_collect( %args, 'fatal' => 'return',
+                                                           'debug' => $debug, );
+          if ( $error ) {
+            $log->error($error);
+            warn $error; #die $error;
+          }
         }
 
       }
@@ -160,8 +176,6 @@ sub bill {
 #      with today's date, regardless of the pretend date used to pre-generate
 #      the invoices.
 #
-#  -p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
-#
 #  -a: Only process customers with the specified agentnum
 #
 #  -v: enable debugging
@@ -189,8 +203,6 @@ sub bill_where {
 
   push @search, "( cust_main.archived != 'Y' OR archived IS NULL )"; #disable?
 
-  push @search, "cust_main.payby    = '". $opt{'p'}. "'"
-    if $opt{'p'};
   push @search, "cust_main.agentnum IN ( ". $opt{'a'}. " ) "
     if $opt{'a'};
 
@@ -209,6 +221,8 @@ sub bill_where {
   my $conf = new FS::Conf;
   my $billtime = $conf->exists('next-bill-ignore-time') ? day_end($time) : $time;
 
+  # corresponds to perl checks in FS::cust_main::Billing sub bill
+  #  ("bill setup" and "bill recurring fee")
   # select * from cust_main where
   my $where_pkg = <<"END";
     EXISTS(
@@ -217,7 +231,7 @@ sub bill_where {
           AND ( cancel IS NULL OR cancel = 0 )
           AND (    ( ( cust_pkg.setup IS NULL OR cust_pkg.setup =  0 )
                      AND ( start_date IS NULL OR start_date = 0
-                           OR ( start_date IS NOT NULL AND start_date <= $^T )
+                           OR ( start_date IS NOT NULL AND start_date <= $billtime )
                          )
                    )
                 OR ( freq != '0' AND ( bill IS NULL OR bill  <= $billtime ) )
@@ -233,7 +247,8 @@ END
     my $eventtable = $_;
 
     # joins and where clauses to test event conditions
-    my $join  = FS::part_event_condition->join_conditions_sql(  $eventtable );
+    my $join  = FS::part_event_condition->join_conditions_sql(  $eventtable,
+                                                                'time'=>$time );
     my $where = FS::part_event_condition->where_conditions_sql( $eventtable,
                                                                 'time'=>$time,
                                                               );