X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pkg.pm;h=ed9f2cbc6498dce55200472e8eade9e0f8653654;hb=947c955be56140c4a10b16345c1b15c44b02070a;hp=0b1a291dbab54e0440c07d3f0db11d8ba21a0ba8;hpb=6ed5d51b3a72e2935dd5d084c9e24567150b03ca;p=freeside.git diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 0b1a291db..ed9f2cbc6 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -2,6 +2,7 @@ package FS::cust_pkg; use strict; use vars qw(@ISA $disable_agentcheck @SVCDB_CANCEL_SEQ $DEBUG); +use Tie::IxHash; use FS::UID qw( getotaker dbh ); use FS::Misc qw( send_email ); use FS::Record qw( qsearch qsearchs ); @@ -17,7 +18,7 @@ use FS::reg_code; # need to 'use' these instead of 'require' in sub { cancel, suspend, unsuspend, # setup } -# because they load configuraion by setting FS::UID::callback (see TODO) +# because they load configuration by setting FS::UID::callback (see TODO) use FS::svc_acct; use FS::svc_domain; use FS::svc_www; @@ -264,6 +265,8 @@ suspend is normally updated by the suspend and unsuspend methods. cancel is normally updated by the cancel method (and also the order subroutine in some cases). +Calls + =cut sub replace { @@ -281,7 +284,51 @@ sub replace { local($disable_agentcheck) = 1 if $old->pkgpart == $new->pkgpart; - $new->SUPER::replace($old); + 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; + + #save off and freeze RADIUS attributes for any associated svc_acct records + my @svc_acct = (); + if ( $old->part_pkg->is_prepaid || $new->part_pkg->is_prepaid ) { + + #also check for specific exports? + # to avoid spurious modify export events + @svc_acct = map { $_->svc_x } + grep { $_->part_svc->svcdb eq 'svc_acct' } + $old->cust_svc; + + $_->snapshot foreach @svc_acct; + + } + + my $error = $new->SUPER::replace($old); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + #for prepaid packages, + #trigger export of new RADIUS Expiration attribute when cust_pkg.bill changes + foreach my $old_svc_acct ( @svc_acct ) { + my $new_svc_acct = new FS::svc_acct { $old_svc_acct->hash }; + my $s_error = $new_svc_acct->replace($old_svc_acct); + if ( $s_error ) { + $dbh->rollback if $oldAutoCommit; + return $s_error; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + } =item check @@ -313,7 +360,7 @@ sub check { qsearchs( 'reg_code', { 'code' => $self->reg_code, 'agentnum' => $self->cust_main->agentnum }) ) { - return "Unknown registraiton code"; + return "Unknown registration code"; } } elsif ( $self->promo_code ) { @@ -407,7 +454,7 @@ sub cancel { if ( $remaining_value > 0 ) { my $error = $self->cust_main->credit( $remaining_value, - 'Credit for unused time on'. $self->part_pkg->pkg, + 'Credit for unused time on '. $self->part_pkg->pkg, ); if ($error) { $dbh->rollback if $oldAutoCommit; @@ -778,26 +825,45 @@ Returns a short status string for this package, currently: sub status { my $self = shift; + my $freq = length($self->freq) ? $self->freq : $self->part_pkg->freq; + return 'cancelled' if $self->get('cancel'); return 'suspended' if $self->susp; return 'not yet billed' unless $self->setup; - return 'one-time charge' if $self->part_pkg->freq =~ /^(0|$)/; + return 'one-time charge' if $freq =~ /^(0|$)/; return 'active'; } -=item statuscolor +=item statuses -Returns a hex triplet color string for this package's status. +Class method that returns the list of possible status strings for pacakges +(see L). For example: + + @statuses = FS::cust_pkg->statuses(); =cut -my %statuscolor = ( +tie my %statuscolor, 'Tie::IxHash', 'not yet billed' => '000000', 'one-time charge' => '000000', 'active' => '00CC00', 'suspended' => 'FF9900', 'cancelled' => 'FF0000', -); +; + +sub statuses { + my $self = shift; #could be class... + grep { $_ !~ /^(not yet billed)$/ } #this is a dumb status anyway + # mayble split btw one-time vs. recur + keys %statuscolor; +} + +=item statuscolor + +Returns a hex triplet color string for this package's status. + +=cut + sub statuscolor { my $self = shift; $statuscolor{$self->status}; @@ -1117,7 +1183,7 @@ sub reexport { =back -=head1 CLASS METHOD +=head1 CLASS METHODS =over 4 @@ -1132,6 +1198,17 @@ sub recurring_sql { " where cust_pkg.pkgpart = part_pkg.pkgpart ) "; } +=item onetime_sql + +Returns an SQL expression identifying one-time packages. + +=cut + +sub onetime_sql { " + '0' = ( select freq from part_pkg + where cust_pkg.pkgpart = part_pkg.pkgpart ) +"; } + =item active_sql Returns an SQL expression identifying active packages. @@ -1144,6 +1221,19 @@ sub active_sql { " AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 ) "; } +=item inactive_sql + +Returns an SQL expression identifying inactive packages (one-time packages +that are otherwise unsuspended/uncancelled). + +=cut + +sub inactive_sql { " + ". $_[0]->onetime_sql(). " + AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) + AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 ) +"; } + =item susp_sql =item suspended_sql @@ -1152,11 +1242,13 @@ Returns an SQL expression identifying suspended packages. =cut sub suspended_sql { susp_sql(@_); } -sub susp_sql { " - ". $_[0]->recurring_sql(). " - AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) - AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0 -"; } +sub susp_sql { + #$_[0]->recurring_sql(). ' AND '. + " + ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 ) + AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0 + "; +} =item cancel_sql =item cancelled_sql @@ -1166,10 +1258,10 @@ Returns an SQL exprression identifying cancelled packages. =cut sub cancelled_sql { cancel_sql(@_); } -sub cancel_sql { " - ". $_[0]->recurring_sql(). " - AND cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0 -"; } +sub cancel_sql { + #$_[0]->recurring_sql(). ' AND '. + "cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0"; +} =head1 SUBROUTINES