fix bug in last_bill method which prevented last_bill dates from being set
[freeside.git] / FS / FS / cust_pkg.pm
index 803fa3c..bd3d1f5 100644 (file)
@@ -1,7 +1,8 @@
 package FS::cust_pkg;
 
 use strict;
-use vars qw(@ISA);
+use vars qw(@ISA $disable_agentcheck);
+use vars qw( $quiet );
 use FS::UID qw( getotaker dbh );
 use FS::Record qw( qsearch qsearchs );
 use FS::cust_svc;
@@ -19,8 +20,17 @@ use FS::svc_domain;
 use FS::svc_www;
 use FS::svc_forward;
 
+# need all this for sending cancel emails in sub cancel
+
+use FS::Conf;
+use Date::Format;
+use Mail::Internet 1.44;
+use Mail::Header;
+
 @ISA = qw( FS::Record );
 
+$disable_agentcheck = 0;
+
 sub _cache {
   my $self = shift;
   my ( $hashref, $cache ) = @_;
@@ -142,10 +152,13 @@ sub insert {
   my $cust_main = $self->cust_main;
   return "Unknown customer ". $self->custnum unless $cust_main;
 
-  my $agent = qsearchs( 'agent', { 'agentnum' => $cust_main->agentnum } );
-  my $pkgpart_href = $agent->pkgpart_hashref;
-  return "agent ". $agent->agentnum. " can't purchase pkgpart ". $self->pkgpart
-    unless $pkgpart_href->{ $self->pkgpart };
+  unless ( $disable_agentcheck ) {
+    my $agent = qsearchs( 'agent', { 'agentnum' => $cust_main->agentnum } );
+    my $pkgpart_href = $agent->pkgpart_hashref;
+    return "agent ". $agent->agentnum.
+           " can't purchase pkgpart ". $self->pkgpart
+      unless $pkgpart_href->{ $self->pkgpart };
+  }
 
   $self->SUPER::insert;
 
@@ -290,7 +303,43 @@ sub cancel {
 
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
+  my $conf = new FS::Conf;
+
+  if ( !$quiet && $conf->exists('emailcancel')
+       && grep { $_ ne 'POST' } $self->cust_main->invoicing_list) {
+  
+      my @invoicing_list = $self->cust_main->invoicing_list;
+  
+      my $invoice_from = $conf->config('invoice_from');
+      my @print_text = map "$_\n", $conf->config('cancelmessage');
+      my $subject = $conf->config('cancelsubject');
+      my $smtpmachine = $conf->config('smtpmachine');
+      
+      if ( grep { $_ ne 'POST' } @invoicing_list ) { #email invoice
+         #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card
+         #$ENV{SMTPHOSTS} = $smtpmachine;
+         $ENV{MAILADDRESS} = $invoice_from;
+         my $header = new Mail::Header ( [
+              "From: $invoice_from",
+             "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ),
+              "Sender: $invoice_from",
+              "Reply-To: $invoice_from",
+              "Date: ". time2str("%a, %d %b %Y %X %z", time),
+              "Subject: $subject",           
+                                     ] );
+         my $message = new Mail::Internet (
+              'Header' => $header,
+              'Body' => [ @print_text ],      
+                                      );
+         $!=0;
+         $message->smtpsend( Host => $smtpmachine )
+             or $message->smtpsend( Host => $smtpmachine, Debug => 1 );
+         #should this return an error?
+         }
+  }
+
   ''; #no errors
+
 }
 
 =item suspend
@@ -428,6 +477,10 @@ Useful for billing metered services.
 
 sub last_bill {
   my $self = shift;
+  if ( $self->dbdef_table->column('last_bill') ) {
+    return $self->setfield('last_bill', $_[0]) if @_;
+    return $self->getfield('last_bill') if $self->getfield('last_bill');
+  }    
   my $cust_bill_pkg = qsearchs('cust_bill_pkg', { 'pkgnum' => $self->pkgnum,
                                                   'edate'  => $self->bill,  } );
   $cust_bill_pkg ? $cust_bill_pkg->sdate : $self->setup || 0;
@@ -511,17 +564,11 @@ sub seconds_since {
 
 }
 
-=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END DATASRC DB_USERNAME DB_PASSWORD
+=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END
 
 Returns the numbers of seconds all accounts (see L<FS::svc_acct>) in this
 package have been online between TIMESTAMP_START (inclusive) and TIMESTAMP_END
-(exclusive), according to an external SQL radacct table, such as those
-generated by ICRADIUS or FreeRADIUS.  Sessions which started in the specified
-range but are still open are counted from session start to the end of the
-range.  Also, sessions which end in the range but started earlier are counted
-from the start of the range to session end.  Finally, sessions which start
-before the range but end after (or are still open) are counted for the entire
-range.
+(exclusive).
 
 TIMESTAMP_START and TIMESTAMP_END are specified as UNIX timestamps; see
 L<perlfunc/"time">.  Also see L<Time::Local> and L<Date::Parse> for conversion
@@ -531,23 +578,56 @@ functions.
 =cut
 
 sub seconds_since_sqlradacct {
-  my($self, $start, $end, $datasrc, $db_user, $db_pass) = @_;
-
-  my $dbh = DBI->connect($datasrc, $db_user, $db_pass)
-    or die "can't connect to $datasrc: ". $DBI::errstr;
+  my($self, $start, $end) = @_;
 
   my $seconds = 0;
 
   foreach my $cust_svc (
-    grep { $_->part_svc->svcdb eq 'svc_acct' } $self->cust_svc
+    grep {
+      my $part_svc = $_->part_svc;
+      $part_svc->svcdb eq 'svc_acct'
+        && scalar($part_svc->part_export('sqlradius'));
+    } $self->cust_svc
   ) {
-    $seconds += $cust_svc->seconds_since_sqlradacct($start, $end, $dbh);
+    $seconds += $cust_svc->seconds_since_sqlradacct($start, $end);
   }
 
   $seconds;
 
 }
 
+=item attribute_since_sqlradacct TIMESTAMP_START TIMESTAMP_END ATTRIBUTE
+
+Returns the sum of the given attribute for all accounts (see L<FS::svc_acct>)
+in this package for sessions ending between TIMESTAMP_START (inclusive) and
+TIMESTAMP_END
+(exclusive).
+
+TIMESTAMP_START and TIMESTAMP_END are specified as UNIX timestamps; see
+L<perlfunc/"time">.  Also see L<Time::Local> and L<Date::Parse> for conversion
+functions.
+
+=cut
+
+sub attribute_since_sqlradacct {
+  my($self, $start, $end, $attrib) = @_;
+
+  my $sum = 0;
+
+  foreach my $cust_svc (
+    grep {
+      my $part_svc = $_->part_svc;
+      $part_svc->svcdb eq 'svc_acct'
+        && scalar($part_svc->part_export('sqlradius'));
+    } $self->cust_svc
+  ) {
+    $sum += $cust_svc->attribute_since_sqlradacct($start, $end, $attrib);
+  }
+
+  $sum;
+
+}
+
 =back
 
 =head1 SUBROUTINES
@@ -728,10 +808,6 @@ sub order {
 
 =back
 
-=head1 VERSION
-
-$Id: cust_pkg.pm,v 1.26 2002-10-14 06:17:14 ivan Exp $
-
 =head1 BUGS
 
 sub order is not OO.  Perhaps it should be moved to FS::cust_main and made so?
@@ -741,12 +817,12 @@ In sub order, the @pkgparts array (passed by reference) is clobbered.
 Also in sub order, no money is adjusted.  Once FS::part_pkg defines a standard
 method to pass dates to the recur_prog expression, it should do so.
 
-FS::svc_acct, FS::svc_domain, FS::svc_www and FS::svc_forward are loaded via
-'use' at compile time, rather than via 'require' in sub
-{ setup, suspend, unsuspend, cancel } because they use %FS::UID::callback to
-load configuration values.  Probably need a subroutine which decides what to
-do based on whether or not we've fetched the user yet, rather than a hash.
-See FS::UID and the TODO.
+FS::svc_acct, FS::svc_domain, FS::svc_www, FS::svc_ip and FS::svc_forward are
+loaded via 'use' at compile time, rather than via 'require' in sub { setup,
+suspend, unsuspend, cancel } because they use %FS::UID::callback to load
+configuration values.  Probably need a subroutine which decides what to do
+based on whether or not we've fetched the user yet, rather than a hash.  See
+FS::UID and the TODO.
 
 Now that things are transactional should the check in the insert method be
 moved to check ?