radacct update: use sqlradius for datasrc, not plandata options (whew)
[freeside.git] / FS / FS / cust_pkg.pm
index b7633c1..55ee37d 100644 (file)
@@ -9,12 +9,12 @@ use FS::part_pkg;
 use FS::cust_main;
 use FS::type_pkgs;
 use FS::pkg_svc;
+use FS::cust_bill_pkg;
 
 # need to 'use' these instead of 'require' in sub { cancel, suspend, unsuspend,
 # setup }
 # because they load configuraion by setting FS::UID::callback (see TODO)
 use FS::svc_acct;
-use FS::svc_acct_sm;
 use FS::svc_domain;
 use FS::svc_www;
 use FS::svc_forward;
@@ -91,7 +91,7 @@ inherits from FS::Record.  The following fields are currently supported:
 
 =item setup - date
 
-=item bill - date
+=item bill - date (next bill date)
 
 =item susp - date
 
@@ -145,7 +145,7 @@ sub insert {
   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 $pkgpart_href->{ $self->pkgpart };
 
   $self->SUPER::insert;
 
@@ -225,11 +225,11 @@ sub check {
     return "Unknown customer ". $self->custnum unless $self->cust_main;
   }
 
-  return "Unknown pkgpart"
+  return "Unknown pkgpart: ". $self->pkgpart
     unless qsearchs( 'part_pkg', { 'pkgpart' => $self->pkgpart } );
 
   $self->otaker(getotaker) unless $self->otaker;
-  $self->otaker =~ /^(\w{0,16})$/ or return "Illegal otaker";
+  $self->otaker =~ /^([\w\.\-]{0,16})$/ or return "Illegal otaker";
   $self->otaker($1);
 
   if ( $self->dbdef_table->column('manual_flag') ) {
@@ -268,33 +268,11 @@ sub cancel {
   foreach my $cust_svc (
     qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } )
   ) {
-    my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $cust_svc->svcpart } );
-
-    $part_svc->svcdb =~ /^([\w\-]+)$/ or do {
-      $dbh->rollback if $oldAutoCommit;
-      return "Illegal svcdb value in part_svc!";
-    };
-    my $svcdb = $1;
-    require "FS/$svcdb.pm";
-
-    my $svc = qsearchs( $svcdb, { 'svcnum' => $cust_svc->svcnum } );
-    if ($svc) {
-      $error = $svc->cancel;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return "Error cancelling service: $error" 
-      }
-      $error = $svc->delete;
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return "Error deleting service: $error";
-      }
-    }
+    my $error = $cust_svc->cancel;
 
-    $error = $cust_svc->delete;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
-      return "Error deleting cust_svc: $error";
+      return "Error cancelling cust_svc: $error";
     }
 
   }
@@ -441,6 +419,20 @@ sub unsuspend {
   ''; #no errors
 }
 
+=item last_bill
+
+Returns the last bill date, or if there is no last bill date, the setup date.
+Useful for billing metered services.
+
+=cut
+
+sub last_bill {
+  my $self = shift;
+  my $cust_bill_pkg = qsearchs('cust_bill_pkg', { 'pkgnum' => $self->pkgnum,
+                                                  'edate'  => $self->bill,  } );
+  $cust_bill_pkg ? $cust_bill_pkg->sdate : $self->setup || 0;
+}
+
 =item part_pkg
 
 Returns the definition for this billing item, as an FS::part_pkg object (see
@@ -498,7 +490,7 @@ sub cust_main {
 =item seconds_since TIMESTAMP
 
 Returns the number of seconds all accounts (see L<FS::svc_acct>) in this
-package have been online since TIMESTAMP.
+package have been online since TIMESTAMP, according to the session monitor.
 
 TIMESTAMP is specified as a UNIX timestamp; see L<perlfunc/"time">.  Also see
 L<Time::Local> and L<Date::Parse> for conversion functions.
@@ -519,6 +511,34 @@ sub seconds_since {
 
 }
 
+=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).
+
+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 seconds_since_sqlradacct {
+  my($self, $start, $end) = @_;
+
+  my $seconds = 0;
+
+  foreach my $cust_svc (
+    grep { $_->part_svc->svcdb eq 'svc_acct' } $self->cust_svc
+  ) {
+    $seconds += $cust_svc->seconds_since_sqlradacct($start, $end);
+  }
+
+  $seconds;
+
+}
+
 =back
 
 =head1 SUBROUTINES
@@ -701,7 +721,7 @@ sub order {
 
 =head1 VERSION
 
-$Id: cust_pkg.pm,v 1.19 2002-04-22 20:47:21 ivan Exp $
+$Id: cust_pkg.pm,v 1.27 2002-10-17 14:16:17 ivan Exp $
 
 =head1 BUGS
 
@@ -712,11 +732,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_acct_sm, and FS::svc_domain 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 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 ?