event refactor, landing on HEAD!
[freeside.git] / FS / FS / svc_acct.pm
index 48116d7..fc950fa 100644 (file)
@@ -8,8 +8,6 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
              $username_noperiod $username_nounderscore $username_nodash
              $username_uppercase $username_percent
              $password_noampersand $password_noexclamation
-             $welcome_template $welcome_from
-             $welcome_subject $welcome_subject_template $welcome_mimetype
              $warning_template $warning_from $warning_subject $warning_mimetype
              $warning_cc
              $smtpmachine
@@ -26,6 +24,7 @@ use FS::UID qw( datasrc );
 use FS::Conf;
 use FS::Record qw( qsearch qsearchs fields dbh dbdef );
 use FS::Msgcat qw(gettext);
+use FS::UI::bytecount;
 use FS::svc_Common;
 use FS::cust_svc;
 use FS::part_svc;
@@ -66,24 +65,6 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
   $password_noampersand = $conf->exists('password-noexclamation');
   $password_noexclamation = $conf->exists('password-noexclamation');
   $dirhash = $conf->config('dirhash') || 0;
-  if ( $conf->exists('welcome_email') ) {
-    $welcome_template = new Text::Template (
-      TYPE   => 'ARRAY',
-      SOURCE => [ map "$_\n", $conf->config('welcome_email') ]
-    ) or warn "can't create welcome email template: $Text::Template::ERROR";
-    $welcome_from = $conf->config('welcome_email-from'); # || 'your-isp-is-dum'
-    $welcome_subject = $conf->config('welcome_email-subject') || 'Welcome';
-    $welcome_subject_template = new Text::Template (
-      TYPE   => 'STRING',
-      SOURCE => $welcome_subject,
-    ) or warn "can't create welcome email subject template: $Text::Template::ERROR";
-    $welcome_mimetype = $conf->config('welcome_email-mimetype') || 'text/plain';
-  } else {
-    $welcome_template = '';
-    $welcome_from = '';
-    $welcome_subject = '';
-    $welcome_mimetype = '';
-  }
   if ( $conf->exists('warning_email') ) {
     $warning_template = new Text::Template (
       TYPE   => 'ARRAY',
@@ -103,6 +84,7 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
   $smtpmachine = $conf->config('smtpmachine');
   $radius_password = $conf->config('radius-password') || 'Password';
   $radius_ip = $conf->config('radius-ip') || 'Framed-IP-Address';
+  @pw_set = ( 'A'..'Z' ) if $conf->exists('password-generated-allcaps');
 };
 
 @saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
@@ -292,6 +274,53 @@ sub table_info {
                          disable_inventory => 1,
                          disable_select => 1,
                        },
+        'upbytes'   => { label => 'Upload',
+                         type  => 'text',
+                         disable_inventory => 1,
+                         disable_select => 1,
+                         'format' => \&FS::UI::bytecount::display_bytecount,
+                         'parse' => \&FS::UI::bytecount::parse_bytecount,
+                       },
+        'downbytes' => { label => 'Download',
+                         type  => 'text',
+                         disable_inventory => 1,
+                         disable_select => 1,
+                         'format' => \&FS::UI::bytecount::display_bytecount,
+                         'parse' => \&FS::UI::bytecount::parse_bytecount,
+                       },
+        'totalbytes'=> { label => 'Total up and download',
+                         type  => 'text',
+                         disable_inventory => 1,
+                         disable_select => 1,
+                         'format' => \&FS::UI::bytecount::display_bytecount,
+                         'parse' => \&FS::UI::bytecount::parse_bytecount,
+                       },
+        'seconds_threshold'   => { label => 'Seconds',
+                                   type  => 'text',
+                                   disable_inventory => 1,
+                                   disable_select => 1,
+                                 },
+        'upbytes_threshold'   => { label => 'Upload',
+                                   type  => 'text',
+                                   disable_inventory => 1,
+                                   disable_select => 1,
+                                   'format' => \&FS::UI::bytecount::display_bytecount,
+                                   'parse' => \&FS::UI::bytecount::parse_bytecount,
+                                 },
+        'downbytes_threshold' => { label => 'Download',
+                                   type  => 'text',
+                                   disable_inventory => 1,
+                                   disable_select => 1,
+                                   'format' => \&FS::UI::bytecount::display_bytecount,
+                                   'parse' => \&FS::UI::bytecount::parse_bytecount,
+                                 },
+        'totalbytes_threshold'=> { label => 'Total up and download',
+                                   type  => 'text',
+                                   disable_inventory => 1,
+                                   disable_select => 1,
+                                   'format' => \&FS::UI::bytecount::display_bytecount,
+                                   'parse' => \&FS::UI::bytecount::parse_bytecount,
+                                 },
     },
   };
 }
@@ -467,6 +496,7 @@ sub insert {
 
   if ( $cust_pkg ) {
     my $cust_main = $cust_pkg->cust_main;
+    my $agentnum = $cust_main->agentnum;
 
     if (   $conf->exists('emailinvoiceautoalways')
         || $conf->exists('emailinvoiceauto')
@@ -478,7 +508,25 @@ sub insert {
     }
 
     #welcome email
-    my $to = '';
+    my ($to,$welcome_template,$welcome_from,$welcome_subject,$welcome_subject_template,$welcome_mimetype)
+      = ('','','','','','');
+
+    if ( $conf->exists('welcome_email', $agentnum) ) {
+      $welcome_template = new Text::Template (
+        TYPE   => 'ARRAY',
+        SOURCE => [ map "$_\n", $conf->config('welcome_email', $agentnum) ]
+      ) or warn "can't create welcome email template: $Text::Template::ERROR";
+      $welcome_from = $conf->config('welcome_email-from', $agentnum);
+        # || 'your-isp-is-dum'
+      $welcome_subject = $conf->config('welcome_email-subject', $agentnum)
+        || 'Welcome';
+      $welcome_subject_template = new Text::Template (
+        TYPE   => 'STRING',
+        SOURCE => $welcome_subject,
+      ) or warn "can't create welcome email subject template: $Text::Template::ERROR";
+      $welcome_mimetype = $conf->config('welcome_email-mimetype', $agentnum)
+        || 'text/plain';
+    }
     if ( $welcome_template && $cust_pkg ) {
       my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list );
       if ( $to ) {
@@ -609,6 +657,12 @@ sub delete {
     }
   }
 
+  my $error = $self->SUPER::delete;
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
   foreach my $radius_usergroup (
     qsearch('radius_usergroup', { 'svcnum' => $self->svcnum } )
   ) {
@@ -619,12 +673,6 @@ sub delete {
     }
   }
 
-  my $error = $self->SUPER::delete;
-  if ( $error ) {
-    $dbh->rollback if $oldAutoCommit;
-    return $error;
-  }
-
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
   '';
 }
@@ -731,7 +779,7 @@ sub replace {
     }
   }
 
-  $error = $new->SUPER::replace($old);
+  $error = $new->SUPER::replace($old, @_);
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error if $error;
@@ -797,7 +845,7 @@ Called by the suspend method of FS::cust_pkg (see L<FS::cust_pkg>).
 sub suspend {
   my $self = shift;
   return "can't suspend system account" if $self->_check_system;
-  $self->SUPER::suspend;
+  $self->SUPER::suspend(@_);
 }
 
 =item unsuspend
@@ -819,7 +867,7 @@ sub unsuspend {
     return $error if $error;
   }
 
-  $self->SUPER::unsuspend;
+  $self->SUPER::unsuspend(@_);
 }
 
 =item cancel
@@ -850,7 +898,7 @@ sub cancel {
     }
   }
 
-  $self->SUPER::cancel;
+  $self->SUPER::cancel(@_);
 }
 
 
@@ -949,7 +997,7 @@ sub check {
         $recref->{shell} = (grep $_ eq $recref->{shell}, @shells)[0];
       } else {
         return "Illegal shell \`". $self->shell. "\'; ".
-               $conf->dir. "/shells contains: @shells";
+               "shells configuration value contains: @shells";
       }
     } else {
       $recref->{shell} = '/bin/sync';
@@ -1588,7 +1636,10 @@ sub _op_usage {
 
   my $action = $op2action{$op};
 
-  if ( &{$op2condition{$op}}($self, $column, $amount) ) {
+  if ( &{$op2condition{$op}}($self, $column, $amount) &&
+        ( $action eq 'suspend'   && !$self->overlimit 
+       || $action eq 'unsuspend' &&  $self->overlimit ) 
+     ) {
     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
       if ($part_export->option('overlimit_groups')) {
         my ($new,$old);
@@ -1602,6 +1653,7 @@ sub _op_usage {
           $new = $self; $old = $other;
         }
         my $error = $part_export->export_replace($new, $old);
+        $error ||= $self->overlimit($action);
         if ( $error ) {
           $dbh->rollback if $oldAutoCommit;
           return "Error replacing radius groups in export, ${op}: $error";
@@ -1614,6 +1666,7 @@ sub _op_usage {
        && &{$op2condition{$op}}($self, $column, $amount)    ) {
     #my $error = $self->$action();
     my $error = $self->cust_svc->cust_pkg->$action();
+    # $error ||= $self->overlimit($action);
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
       return "Error ${action}ing: $error";
@@ -1672,6 +1725,7 @@ sub set_usage {
   my $dbh = dbh;
 
   my $reset = 0;
+  my %handyhash = ();
   foreach my $field (keys %$valueref){
     $reset = 1 if $valueref->{$field};
     $self->setfield($field, $valueref->{$field});
@@ -1683,12 +1737,48 @@ sub set_usage {
                            )
                        )
                      );
+    $handyhash{$field} = $self->getfield($field);
+    $handyhash{$field.'_threshold'} = $self->getfield($field.'_threshold');
   }
-  my $error = $self->replace;
-  die $error if $error;
+  #my $error = $self->replace;   #NO! we avoid the call to ->check for
+  #die $error if $error;         #services not explicity changed via the UI
+
+  my $sql = "UPDATE svc_acct SET " .
+    join (',', map { "$_ =  ?" } (keys %handyhash) ).
+    " WHERE svcnum = ?";
 
-  if ( $conf->exists("svc_acct-usage_unsuspend") && $reset ) {
-    my $error = $self->cust_svc->cust_pkg->unsuspend;
+  warn "$me $sql\n"
+    if $DEBUG;
+
+  if (scalar(keys %handyhash)) {
+    my $sth = $dbh->prepare( $sql )
+      or die "Error preparing $sql: ". $dbh->errstr;
+    my $rv = $sth->execute((values %handyhash), $self->svcnum);
+    die "Error executing $sql: ". $sth->errstr
+      unless defined($rv);
+    die "Can't update usage for svcnum ". $self->svcnum
+      if $rv == 0;
+  }
+
+  if ( $reset ) {
+    my $error;
+
+    if ($self->overlimit) {
+      $error = $self->overlimit('unsuspend');
+      foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
+        if ($part_export->option('overlimit_groups')) {
+          my $old = new FS::svc_acct $self->hashref;
+          my $groups = &{ $self->_fieldhandlers->{'usergroup'} }
+                         ($self, $part_export->option('overlimit_groups'));
+          $old->usergroup( $groups );
+          $error ||= $part_export->export_replace($self, $old);
+        }
+      }
+    }
+
+    if ( $conf->exists("svc_acct-usage_unsuspend")) {
+      $error ||= $self->cust_svc->cust_pkg->unsuspend;
+    }
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
       return "Error unsuspending: $error";
@@ -2220,7 +2310,7 @@ sub send_email {
 =cut
 
 sub check_and_rebuild_fuzzyfiles {
-  my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+  my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
   -e "$dir/svc_acct.username"
     or &rebuild_fuzzyfiles;
 }
@@ -2233,7 +2323,7 @@ sub rebuild_fuzzyfiles {
 
   use Fcntl qw(:flock);
 
-  my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+  my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
 
   #username
 
@@ -2259,7 +2349,7 @@ sub rebuild_fuzzyfiles {
 =cut
 
 sub all_username {
-  my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+  my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
   open(USERNAMECACHE,"<$dir/svc_acct.username")
     or die "can't open $dir/svc_acct.username: $!";
   my @array = map { chomp; $_; } <USERNAMECACHE>;
@@ -2278,7 +2368,7 @@ sub append_fuzzyfiles {
 
   use Fcntl qw(:flock);
 
-  my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+  my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
 
   open(USERNAME,">>$dir/svc_acct.username")
     or die "can't open $dir/svc_acct.username: $!";
@@ -2387,7 +2477,6 @@ sub reached_threshold {
 
       my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } 
                                $cust_main->invoicing_list,
-                               $svc_acct->email,
                                ($opt{'to'} ? $opt{'to'} : ())
                    );
 
@@ -2402,8 +2491,12 @@ sub reached_threshold {
                         'last'      => $cust_main->getfield('last'),
                         'pkg'       => $cust_pkg->part_pkg->pkg,
                         'column'    => $opt{'column'},
-                        'amount'    => $svc_acct->getfield($opt{'column'}),
-                        'threshold' => $threshold,
+                        'amount'    => $opt{'column'} =~/bytes/
+                                       ? FS::UI::bytecount::display_bytecount($svc_acct->getfield($opt{'column'}))
+                                       : $svc_acct->getfield($opt{'column'}),
+                        'threshold' => $opt{'column'} =~/bytes/
+                                       ? FS::UI::bytecount::display_bytecount($threshold)
+                                       : $threshold,
                       } );