add cust_pkg_ref option to charge
[freeside.git] / FS / FS / cust_main.pm
index 501fca4..9d40e73 100644 (file)
@@ -2462,7 +2462,7 @@ An array ref of specific packages (objects) to attempt billing, instead trying a
 
 =item not_pkgpart
 
-A hashref of pkgparts to exclude from this billing run.
+A hashref of pkgparts to exclude from this billing run (can also be specified as a comma-separated scalar).
 
 =item invoice_time
 
@@ -2489,6 +2489,10 @@ sub bill {
   my $invoice_time = $options{'invoice_time'} || $time;
 
   $options{'not_pkgpart'} ||= {};
+  $options{'not_pkgpart'} = { map { $_ => 1 }
+                                  split(/\s*,\s*/, $options{'not_pkgpart'})
+                            }
+    unless ref($options{'not_pkgpart'});
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -2782,8 +2786,8 @@ sub bill {
   my @cust_bill = $self->cust_bill;
   my $balance = $self->balance;
   my $previous_balance = scalar(@cust_bill)
-                           ?  $cust_bill[$#cust_bill]->billing_balance
-                           :  0;
+                           ? ( $cust_bill[$#cust_bill]->billing_balance || 0 )
+                           : 0;
 
   $previous_balance += $cust_bill[$#cust_bill]->charged
     if scalar(@cust_bill);
@@ -3036,7 +3040,7 @@ sub _make_lines {
       ###
 
       my $error = 
-        $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg, $options{invoice_time}, $real_pkgpart);
+        $self->_handle_taxes($part_pkg, $taxlisthash, $cust_bill_pkg, $cust_pkg, $options{invoice_time}, $real_pkgpart, \%options);
       return $error if $error;
 
       push @$cust_bill_pkgs, $cust_bill_pkg;
@@ -3057,6 +3061,7 @@ sub _handle_taxes {
   my $cust_pkg = shift;
   my $invoice_time = shift;
   my $real_pkgpart = shift;
+  my $options = shift;
 
   my %cust_bill_pkg = ();
   my %taxes = ();
@@ -3064,8 +3069,8 @@ sub _handle_taxes {
   my @classes;
   #push @classes, $cust_bill_pkg->usage_classes if $cust_bill_pkg->type eq 'U';
   push @classes, $cust_bill_pkg->usage_classes if $cust_bill_pkg->usage;
-  push @classes, 'setup' if $cust_bill_pkg->setup;
-  push @classes, 'recur' if $cust_bill_pkg->recur;
+  push @classes, 'setup' if ($cust_bill_pkg->setup && !$options->{cancel});
+  push @classes, 'recur' if ($cust_bill_pkg->recur && !$options->{cancel});
 
   if ( $self->tax !~ /Y/i && $self->payby ne 'COMP' ) {
 
@@ -7164,6 +7169,9 @@ New-style, with a hashref of options:
                                     #vendor taxation
                                     'taxproduct' => 2,  #part_pkg_taxproduct
                                     'override'   => {}, #XXX describe
+
+                                    #will be filled in with the new object
+                                    'cust_pkg_ref' => \$cust_pkg,
                                   }
                                 );
 
@@ -7179,6 +7187,7 @@ sub charge {
   my ( $pkg, $comment, $additional );
   my ( $setuptax, $taxclass );   #internal taxes
   my ( $taxproduct, $override ); #vendor (CCH) taxes
+  my $cust_pkg_ref = '';
   if ( ref( $_[0] ) ) {
     $amount     = $_[0]->{amount};
     $quantity   = exists($_[0]->{quantity}) ? $_[0]->{quantity} : 1;
@@ -7192,6 +7201,7 @@ sub charge {
     $additional = $_[0]->{additional} || [];
     $taxproduct = $_[0]->{taxproductnum};
     $override   = { '' => $_[0]->{tax_override} };
+    $cust_pkg_ref = exists($_[0]->{cust_pkg_ref}) ? $_[0]->{cust_pkg_ref} : '';
   } else {
     $amount     = shift;
     $quantity   = 1;
@@ -7263,6 +7273,8 @@ sub charge {
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
+  } elsif ( $cust_pkg_ref ) {
+    ${$cust_pkg_ref} = $cust_pkg;
   }
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -7305,6 +7317,7 @@ Returns all the invoices (see L<FS::cust_bill>) for this customer.
 
 sub cust_bill {
   my $self = shift;
+  map { $_ } #return $self->num_cust_bill unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch('cust_bill', { 'custnum' => $self->custnum, } )
 }
@@ -7336,6 +7349,7 @@ Returns all the statements (see L<FS::cust_statement>) for this customer.
 
 sub cust_statement {
   my $self = shift;
+  map { $_ } #return $self->num_cust_statement unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch('cust_statement', { 'custnum' => $self->custnum, } )
 }
@@ -7348,6 +7362,7 @@ Returns all the credits (see L<FS::cust_credit>) for this customer.
 
 sub cust_credit {
   my $self = shift;
+  map { $_ } #return $self->num_cust_credit unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_credit', { 'custnum' => $self->custnum } )
 }
@@ -7361,6 +7376,7 @@ package when using experimental package balances.
 
 sub cust_credit_pkgnum {
   my( $self, $pkgnum ) = @_;
+  map { $_ } #return $self->num_cust_credit_pkgnum($pkgnum) unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_credit', { 'custnum' => $self->custnum,
                               'pkgnum'  => $pkgnum,
@@ -7376,10 +7392,26 @@ Returns all the payments (see L<FS::cust_pay>) for this customer.
 
 sub cust_pay {
   my $self = shift;
+  return $self->num_cust_pay unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_pay', { 'custnum' => $self->custnum } )
 }
 
+=item num_cust_pay
+
+Returns the number of payments (see L<FS::cust_pay>) for this customer.  Also
+called automatically when the cust_pay method is used in a scalar context.
+
+=cut
+
+sub num_cust_pay {
+  my $self = shift;
+  my $sql = "SELECT COUNT(*) FROM cust_pay WHERE custnum = ?";
+  my $sth = dbh->prepare($sql) or die dbh->errstr;
+  $sth->execute($self->custnum) or die $sth->errstr;
+  $sth->fetchrow_arrayref->[0];
+}
+
 =item cust_pay_pkgnum
 
 Returns all the payments (see L<FS::cust_pay>) for this customer's specific
@@ -7389,6 +7421,7 @@ package when using experimental package balances.
 
 sub cust_pay_pkgnum {
   my( $self, $pkgnum ) = @_;
+  map { $_ } #return $self->num_cust_pay_pkgnum($pkgnum) unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_pay', { 'custnum' => $self->custnum,
                            'pkgnum'  => $pkgnum,
@@ -7404,6 +7437,7 @@ Returns all voided payments (see L<FS::cust_pay_void>) for this customer.
 
 sub cust_pay_void {
   my $self = shift;
+  map { $_ } #return $self->num_cust_pay_void unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_pay_void', { 'custnum' => $self->custnum } )
 }
@@ -7416,6 +7450,7 @@ Returns all batched payments (see L<FS::cust_pay_void>) for this customer.
 
 sub cust_pay_batch {
   my $self = shift;
+  map { $_ } #return $self->num_cust_pay_batch unless wantarray;
   sort { $a->paybatchnum <=> $b->paybatchnum }
     qsearch( 'cust_pay_batch', { 'custnum' => $self->custnum } )
 }
@@ -7463,6 +7498,7 @@ Returns all the refunds (see L<FS::cust_refund>) for this customer.
 
 sub cust_refund {
   my $self = shift;
+  map { $_ } #return $self->num_cust_refund unless wantarray;
   sort { $a->_date <=> $b->_date }
     qsearch( 'cust_refund', { 'custnum' => $self->custnum } )
 }