$radius_password $radius_ip
$dirhash
@saltset @pw_set );
+use Math::BigInt;
use Carp;
use Fcntl qw(:flock);
use Date::Format;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- my $error = $self->check;
- return $error if $error;
-
- if ( $self->svcnum && qsearchs('cust_svc',{'svcnum'=>$self->svcnum}) ) {
- my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
- unless ( $cust_svc ) {
- $dbh->rollback if $oldAutoCommit;
- return "no cust_svc record found for svcnum ". $self->svcnum;
- }
- $self->pkgnum($cust_svc->pkgnum);
- $self->svcpart($cust_svc->svcpart);
- }
-
- $error = $self->_check_duplicate;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- # set usage fields and thresholds if unset but set in a package def
- if ( $self->pkgnum ) {
- my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
- my $part_pkg = $cust_pkg->part_pkg if $cust_pkg;
- if ( $part_pkg && $part_pkg->can('usage_valuehash') ) {
-
- my %values = $part_pkg->usage_valuehash;
- my $multiplier = $conf->exists('svc_acct-usage_threshold')
- ? 1 - $conf->config('svc_acct-usage_threshold')/100
- : 0.20;
-
- foreach ( keys %values ) {
- next if $self->getfield($_);
- $self->setfield( $_, $values{$_} );
- $self->setfield( $_. '_threshold', int( $values{$_} * $multiplier ) );
- }
-
- }
- }
-
my @jobnums;
- $error = $self->SUPER::insert(
+ my $error = $self->SUPER::insert(
'jobnums' => \@jobnums,
'child_objects' => $self->child_objects,
%options,
''; #no error
}
+# set usage fields and thresholds if unset but set in a package def
+sub preinsert_hook_first {
+ my $self = shift;
+
+ return '' unless $self->pkgnum;
+
+ my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
+ my $part_pkg = $cust_pkg->part_pkg if $cust_pkg;
+ return '' unless $part_pkg && $part_pkg->can('usage_valuehash');
+
+ my %values = $part_pkg->usage_valuehash;
+ my $multiplier = $conf->exists('svc_acct-usage_threshold')
+ ? 1 - $conf->config('svc_acct-usage_threshold')/100
+ : 0.20; #doesn't matter
+
+ foreach ( keys %values ) {
+ next if $self->getfield($_);
+ $self->setfield( $_, $values{$_} );
+ $self->setfield( $_. '_threshold', int( $values{$_} * $multiplier ) )
+ if $conf->exists('svc_acct-usage_threshold');
+ }
+
+ ''; #no error
+}
+
=item delete
Deletes this account from the database. If there is an error, returns the
$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();
+ $big = new Math::BigInt '0' if $big->is_neg();
+ my $att = "Chillispot-Max-\u$what";
+ $reply{"$att-Octets"} = $big->copy->band(0xffffffff)->bstr;
+ $reply{"$att-Gigawords"} = $big->copy->brsft(32)->bstr;
+ }
+ }
+
+ }
+
%reply;
}
my $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password'; $check{$pw_attrib} = $password;
my $cust_svc = $self->cust_svc;
- die "FATAL: no cust_svc record for svc_acct.svcnum ". $self->svcnum. "\n"
- unless $cust_svc;
- my $cust_pkg = $cust_svc->cust_pkg;
- if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill ) {
- $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
+ if ( $cust_svc ) {
+ my $cust_pkg = $cust_svc->cust_pkg;
+ if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill ) {
+ $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
+ }
+ } else {
+ warn "WARNING: no cust_svc record for svc_acct.svcnum ". $self->svcnum.
+ "; can't set Expiration\n"
+ unless $cust_svc;
}
%check;
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) &&
( $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);
- my $other = new FS::svc_acct $self->hashref;
- my $groups = &{ $self->_fieldhandlers->{'usergroup'} }
- ($self, $part_export->option('overlimit_groups'));
- $other->usergroup( $groups );
- if ($action eq 'suspend'){
- $new = $other; $old = $self;
- }else{
- $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";
- }
- }
+
+ my $error = $self->_op_overlimit($action);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
}
+
}
if ( $conf->exists("svc_acct-usage_$action")
}
+sub _op_overlimit {
+ my( $self, $action ) = @_;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $cust_pkg = $self->cust_svc->cust_pkg;
+
+ my $agent_overlimit =
+ $cust_pkg
+ ? $conf->config('overlimit_groups', $cust_pkg->cust_main->agentnum )
+ : '';
+
+ foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
+
+ my $groups = $agent_overlimit || $part_export->option('overlimit_groups');
+ next unless $groups;
+
+ my $gref = &{ $self->_fieldhandlers->{'usergroup'} }( $self, $groups );
+
+ my $other = new FS::svc_acct $self->hashref;
+ $other->usergroup( $gref );
+
+ my($new,$old);
+ if ($action eq 'suspend') {
+ $new = $other;
+ $old = $self;
+ } else { # $action eq 'unsuspend'
+ $new = $self;
+ $old = $other;
+ }
+
+ my $error = $part_export->export_replace($new, $old)
+ || $self->overlimit($action);
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error replacing radius groups: $error";
+ }
+
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
sub set_usage {
my( $self, $valueref, %options ) = @_;
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;
-
- 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;
- }
+ my $error = '';
+
+ $error = $self->_op_overlimit('unsuspend')
+ if $self->overlimit;;
+
+ $error ||= $self->cust_svc->cust_pkg->unsuspend
+ if $conf->exists("svc_acct-usage_unsuspend");
+
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return "Error unsuspending: $error";
}
+
}
warn "$me update successful; committing\n"
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,