X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_svc.pm;h=fc6e60594577f0769b2854a83f9943ae3fb7773b;hb=b79a8cb932946c849328a3c117c35821d9d21e66;hp=c4a75f77a99c79ff226a7f0b218ddf5f7005cbbb;hpb=9006e983ebf98b2000a812ab01f99dcb2335534c;p=freeside.git diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index c4a75f77a..fc6e60594 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -109,7 +109,7 @@ If there is an error, returns the error, otherwise returns false. =cut sub cancel { - my $self = shift; + my($self,%opt) = @_; local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; @@ -133,19 +133,26 @@ sub cancel { my $svc = $self->svc_x; if ($svc) { - - my $error = $svc->cancel; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Error canceling service: $error"; - } - $error = $svc->delete; #this deletes this cust_svc record as well - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "Error deleting service: $error"; + if ( %opt && $opt{'date'} ) { + my $error = $svc->expire($opt{'date'}); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "Error expiring service: $error"; + } + } else { + my $error = $svc->cancel; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "Error canceling service: $error"; + } + $error = $svc->delete; #this deletes this cust_svc record as well + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "Error deleting service: $error"; + } } - } else { + } elsif ( !%opt ) { #huh? warn "WARNING: no svc_ record found for svcnum ". $self->svcnum. @@ -251,6 +258,18 @@ sub replace { } } +# #trigger a re-export on pkgnum changes? +# # (of prepaid packages), for Expiration RADIUS attribute +# if ( $new->pkgnum != $old->pkgnum && $new->cust_pkg->part_pkg->is_prepaid ) { +# my $svc_x = $new->svc_x; +# local($FS::Record::nowarn_identical) = 1; +# my $error = $svc_x->export('replace'); +# if ( $error ) { +# $dbh->rollback if $oldAutoCommit; +# return $error if $error; +# } +# } + #my $error = $new->SUPER::replace($old, @_); my $error = $new->SUPER::replace($old); if ( $error ) { @@ -288,22 +307,13 @@ sub check { if ( $self->pkgnum ) { my $cust_pkg = qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } ); return "Unknown pkgnum" unless $cust_pkg; - my $pkg_svc = qsearchs( 'pkg_svc', { - 'pkgpart' => $cust_pkg->pkgpart, - 'svcpart' => $self->svcpart, - }); - # or new FS::pkg_svc ( { 'pkgpart' => $cust_pkg->pkgpart, - # 'svcpart' => $self->svcpart, - # 'quantity' => 0 } ); - my $quantity = $pkg_svc ? $pkg_svc->quantity : 0; - - my @cust_svc = qsearch('cust_svc', { - 'pkgnum' => $self->pkgnum, - 'svcpart' => $self->svcpart, - }); - return "Already ". scalar(@cust_svc). " ". $part_svc->svc. + ($part_svc) = grep { $_->svcpart == $self->svcpart } $cust_pkg->part_svc; + return "No svcpart ". $self->svcpart. + " services in pkgpart ". $cust_pkg->pkgpart + unless $part_svc; + return "Already ". $part_svc->get('num_cust_svc'). " ". $part_svc->svc. " services for pkgnum ". $self->pkgnum - if scalar(@cust_svc) >= $quantity && !$ignore_quantity; + if $part_svc->get('num_avail') == 0 and !$ignore_quantity; } $self->SUPER::check; @@ -363,6 +373,20 @@ sub date_inserted { $self->h_date('insert'); } +=item pkg_cancel_date + +Returns the date this service's package was canceled. This normally only +exists for a service that's been preserved through cancellation with the +part_pkg.preserve flag. + +=cut + +sub pkg_cancel_date { + my $self = shift; + my $cust_pkg = $self->cust_pkg or return; + return $cust_pkg->getfield('cancel') || ''; +} + =item label Returns a list consisting of: @@ -411,7 +435,7 @@ sub _svc_label { =item export_links -Returns a list of html elements associated with this services exports. +Returns a listref of html elements associated with this service's exports. =cut @@ -423,6 +447,21 @@ sub export_links { $svc_x->export_links; } +=item export_getsettings + +Returns two hashrefs of settings associated with this service's exports. + +=cut + +sub export_getsettings { + my $self = shift; + my $svc_x = $self->svc_x + or return "can't find ". $self->part_svc->svcdb. '.svcnum '. $self->svcnum; + + $svc_x->export_getsettings; +} + + =item svc_x Returns the FS::svc_XXX object for this service (i.e. an FS::svc_acct object or @@ -452,18 +491,20 @@ where B is not "svc_acct". =cut -#note: implementation here, POD in FS::svc_acct -sub seconds_since { - my($self, $since) = @_; - my $dbh = dbh; - my $sth = $dbh->prepare(' SELECT SUM(logout-login) FROM session - WHERE svcnum = ? - AND login >= ? - AND logout IS NOT NULL' - ) or die $dbh->errstr; - $sth->execute($self->svcnum, $since) or die $sth->errstr; - $sth->fetchrow_arrayref->[0]; -} +#internal session db deprecated (or at least on hold) +sub seconds_since { 'internal session db deprecated'; }; +##note: implementation here, POD in FS::svc_acct +#sub seconds_since { +# my($self, $since) = @_; +# my $dbh = dbh; +# my $sth = $dbh->prepare(' SELECT SUM(logout-login) FROM session +# WHERE svcnum = ? +# AND login >= ? +# AND logout IS NOT NULL' +# ) or die $dbh->errstr; +# $sth->execute($self->svcnum, $since) or die $sth->errstr; +# $sth->fetchrow_arrayref->[0]; +#} =item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END @@ -512,15 +553,24 @@ sub seconds_since_sqlradacct { warn "$mes finding closed sessions completely within the given range\n" if $DEBUG; + my $realm = ''; + my $realmparam = ''; + if ($part_export->option('process_single_realm')) { + $realm = 'AND Realm = ?'; + $realmparam = $part_export->option('realm'); + } + my $sth = $dbh->prepare("SELECT SUM(acctsessiontime) FROM radacct WHERE UserName = ? + $realm AND $str2time AcctStartTime) >= ? AND $str2time AcctStopTime ) < ? AND $str2time AcctStopTime ) > 0 AND AcctStopTime IS NOT NULL" ) or die $dbh->errstr; - $sth->execute($username, $start, $end) or die $sth->errstr; + $sth->execute($username, ($realm ? $realmparam : ()), $start, $end) + or die $sth->errstr; my $regular = $sth->fetchrow_arrayref->[0]; warn "$mes finding open sessions which start in the range\n" @@ -530,13 +580,19 @@ sub seconds_since_sqlradacct { $query = "SELECT SUM( ? - $str2time AcctStartTime ) ) FROM radacct WHERE UserName = ? + $realm AND $str2time AcctStartTime ) >= ? AND $str2time AcctStartTime ) < ? AND ( ? - $str2time AcctStartTime ) ) < 86400 AND ( $str2time AcctStopTime ) = 0 OR AcctStopTime IS NULL )"; $sth = $dbh->prepare($query) or die $dbh->errstr; - $sth->execute($end, $username, $start, $end, $end) + $sth->execute( $end, + $username, + ($realm ? $realmparam : ()), + $start, + $end, + $end ) or die $sth->errstr. " executing query $query"; my $start_during = $sth->fetchrow_arrayref->[0]; @@ -547,13 +603,20 @@ sub seconds_since_sqlradacct { $sth = $dbh->prepare("SELECT SUM( $str2time AcctStopTime ) - ? ) FROM radacct WHERE UserName = ? + $realm AND $str2time AcctStartTime ) < ? AND $str2time AcctStopTime ) >= ? AND $str2time AcctStopTime ) < ? AND $str2time AcctStopTime ) > 0 AND AcctStopTime IS NOT NULL" ) or die $dbh->errstr; - $sth->execute($start, $username, $start, $start, $end ) or die $sth->errstr; + $sth->execute( $start, + $username, + ($realm ? $realmparam : ()), + $start, + $start, + $end ) + or die $sth->errstr; my $end_during = $sth->fetchrow_arrayref->[0]; warn "$mes finding closed sessions which start before the range but stop after\n" @@ -564,13 +627,15 @@ sub seconds_since_sqlradacct { $sth = $dbh->prepare("SELECT COUNT(*) FROM radacct WHERE UserName = ? + $realm AND $str2time AcctStartTime ) < ? AND ( $str2time AcctStopTime ) >= ? )" # OR AcctStopTime = 0 # OR AcctStopTime IS NULL )" ) or die $dbh->errstr; - $sth->execute($username, $start, $end ) or die $sth->errstr; + $sth->execute($username, ($realm ? $realmparam : ()), $start, $end ) + or die $sth->errstr; my $entire_range = ($end-$start) * $sth->fetchrow_arrayref->[0]; $seconds += $regular + $end_during + $start_during + $entire_range; @@ -631,14 +696,23 @@ sub attribute_since_sqlradacct { warn "$mes SUMing $attrib sessions\n" if $DEBUG; + my $realm = ''; + my $realmparam = ''; + if ($part_export->option('process_single_realm')) { + $realm = 'AND Realm = ?'; + $realmparam = $part_export->option('realm'); + } + my $sth = $dbh->prepare("SELECT SUM($attrib) FROM radacct WHERE UserName = ? + $realm AND $str2time AcctStopTime ) >= ? AND $str2time AcctStopTime ) < ? AND AcctStopTime IS NOT NULL" ) or die $dbh->errstr; - $sth->execute($username, $start, $end) or die $sth->errstr; + $sth->execute($username, ($realm ? $realmparam : ()), $start, $end) + or die $sth->errstr; my $row = $sth->fetchrow_arrayref; $sum += $row->[0] if defined($row->[0]); @@ -682,47 +756,6 @@ sub get_session_history { } -=item get_cdrs_for_update - -Returns (and SELECTs "FOR UPDATE") all unprocessed (freesidestatus NULL) CDR -objects (see L) associated with this service. - -CDRs are associated with svc_phone services via svc_phone.phonenum - -=cut - -sub get_cdrs_for_update { - my($self, %options) = @_; - - my @fields = ( 'charged_party' ); - push @fields, 'src' unless $options{'disable_src'}; - - #CDRs are now associated with svc_phone services via svc_phone.phonenum - #return () unless $self->svc_x->isa('FS::svc_phone'); - return () unless $self->part_svc->svcdb eq 'svc_phone'; - my $number = $self->svc_x->phonenum; - - my $prefix = $options{'default_prefix'}; - - my @where = map " $_ = '$number' ", @fields; - push @where, map " $_ = '$prefix$number' ", @fields - if length($prefix); - if ( $prefix =~ /^\+(\d+)$/ ) { - push @where, map " $_ = '$1$number' ", @fields - } - - my $extra_sql = ' AND ( '. join(' OR ', @where ). ' ) '; - - my @cdrs = - qsearch( { - 'table' => 'cdr', - 'hashref' => { 'freesidestatus' => '', }, - 'extra_sql' => "$extra_sql FOR UPDATE", - } ); - - @cdrs; -} - =back =head1 BUGS