feature to email CSV of CDRs with invoices #5727
[freeside.git] / FS / FS / svc_acct.pm
index 955547b..6f61eae 100644 (file)
@@ -15,6 +15,7 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
              $dirhash
              @saltset @pw_set );
 use Scalar::Util qw( blessed );
+use Math::BigInt;
 use Carp;
 use Fcntl qw(:flock);
 use Date::Format;
@@ -215,9 +216,9 @@ sub table_info {
     'fields' => {
         'dir'       => 'Home directory',
         'uid'       => {
-                         label     => 'UID',
-                        def_label => 'UID (set to fixed and blank for no UIDs)',
-                        type      => 'text',
+                         label    => 'UID',
+                        def_info => 'set to fixed and blank for no UIDs',
+                        type     => 'text',
                       },
         'slipip'    => 'IP address',
     #    'popnum'    => qq!<A HREF="$p/browse/svc_acct_pop.cgi/">POP number</A>!,
@@ -244,15 +245,14 @@ sub table_info {
                        },
         '_password' => 'Password',
         'gid'       => {
-                         label     => 'GID',
-                        def_label => 'GID (when blank, defaults to UID)',
-                        type      => 'text',
+                         label    => 'GID',
+                        def_info => 'when blank, defaults to UID',
+                        type     => 'text',
                       },
         'shell'     => {
-                         #desc =>'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file, set to blank for no shell tracking)',
                         label    => 'Shell',
-                         def_label=> 'Shell (set to blank for no shell tracking)',
-                         type     =>'select',
+                         def_info => 'set to blank for no shell tracking',
+                         type     => 'select',
                          #select_list => [ $conf->config('shells') ],
                          select_list => [ $conf ? $conf->config('shells') : () ],
                          disable_inventory => 1,
@@ -261,7 +261,6 @@ sub table_info {
         'finger'    => 'Real name', # (GECOS)',
         'domsvc'    => {
                          label     => 'Domain',
-                         #def_label => 'svcnum from svc_domain',
                          type      => 'select',
                          select_table => 'svc_domain',
                          select_key   => 'svcnum',
@@ -541,12 +540,13 @@ sub insert {
       my %values = $part_pkg->usage_valuehash;
       my $multiplier = $conf->exists('svc_acct-usage_threshold') 
                          ? 1 - $conf->config('svc_acct-usage_threshold')/100
-                         : 0.20;
+                         : 0.20; #doesn't matter
 
       foreach ( keys %values ) {
         next if $self->getfield($_);
         $self->setfield( $_, $values{$_} );
-        $self->setfield( $_. '_threshold', int( $values{$_} * $multiplier ) );
+        $self->setfield( $_. '_threshold', int( $values{$_} * $multiplier ) )
+          if $conf->exists('svc_acct-usage_threshold');
       }
 
     }
@@ -1025,6 +1025,21 @@ sub check {
   ;
   return $error if $error;
 
+  my $cust_pkg;
+  local $username_letter = $username_letter;
+  if ($self->svcnum) {
+    my $cust_svc = $self->cust_svc
+      or return "no cust_svc record found for svcnum ". $self->svcnum;
+    my $cust_pkg = $cust_svc->cust_pkg;
+  }
+  if ($self->pkgnum) {
+    $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $self->pkgnum } );#complain?
+  }
+  if ($cust_pkg) {
+    $username_letter =
+      $conf->exists('username-letter', $cust_pkg->cust_main->agentnum);
+  }
+
   my $ulen = $usernamemax || $self->dbdef_table->column('username')->length;
   if ( $username_uppercase ) {
     $recref->{username} =~ /^([a-z0-9_\-\.\&\%\:]{$usernamemin,$ulen})$/i
@@ -1426,6 +1441,28 @@ sub radius_reply {
     $reply{'Session-Timeout'} = $self->seconds;
   }
 
+  if ( $conf->exists('radius-chillispot-max') ) {
+    #http://dev.coova.org/svn/coova-chilli/doc/dictionary.chillispot
+
+    #hmm.  just because sqlradius.pm says so?
+    my %whatis = (
+      'input'  => 'up',
+      'output' => 'down',
+      'total'  => 'total',
+    );
+
+    foreach my $what (qw( input output total )) {
+      my $is = $whatis{$what}.'bytes';
+      if ( $self->$is() =~ /\d/ ) {
+        my $big = new Math::BigInt $self->$is();
+        my $att = "Chillispot-Max-\u$what";
+        $reply{"$att-Octets"}    = $big->copy->band(0xffffffff)->bstr;
+        $reply{"$att-Gigawords"} = $big->copy->brsft(32)->bstr;
+      }
+    }
+
+  }
+
   %reply;
 }
 
@@ -1758,6 +1795,38 @@ sub _op_usage {
   die "Can't update $column for svcnum". $self->svcnum
     if $rv == 0;
 
+  #$self->snapshot; #not necessary, we retain the old values
+  #create an object with the updated usage values
+  my $new = qsearchs('svc_acct', { 'svcnum' => $self->svcnum });
+  #call exports
+  my $error = $new->replace($self);
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return "Error replacing: $error";
+  }
+
+  #overlimit_action eq 'cancel' handling
+  my $cust_pkg = $self->cust_svc->cust_pkg;
+  if ( $cust_pkg
+       && $cust_pkg->part_pkg->option('overlimit_action', 1) eq 'cancel' 
+       && $op eq '-' && &{$op2condition{$op}}($self, $column, $amount)
+     )
+  {
+
+    my $error = $cust_pkg->cancel; #XXX should have a reason
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "Error cancelling: $error";
+    }
+
+    #nothing else is relevant if we're cancelling, so commit & return success
+    warn "$me update successful; committing\n"
+      if $DEBUG;
+    $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+    return '';
+
+  }
+
   my $action = $op2action{$op};
 
   if ( &{$op2condition{$op}}($self, $column, $amount) &&
@@ -1889,6 +1958,16 @@ sub set_usage {
       if $rv == 0;
   }
 
+  #$self->snapshot; #not necessary, we retain the old values
+  #create an object with the updated usage values
+  my $new = qsearchs('svc_acct', { 'svcnum' => $self->svcnum });
+  #call exports
+  my $error = $new->replace($self);
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return "Error replacing: $error";
+  }
+
   if ( $reset ) {
     my $error;
 
@@ -2670,6 +2749,8 @@ probably live somewhere else...
 insertion of RADIUS group stuff in insert could be done with child_objects now
 (would probably clean up export of them too)
 
+_op_usage and set_usage bypass the history... maybe they shouldn't
+
 =head1 SEE ALSO
 
 L<FS::svc_Common>, edit/part_svc.cgi from an installed web interface,