use strict;
use vars qw( $DEBUG $me $ignore_quantity $conf $ticket_system );
-use Carp;
+use Carp qw(cluck);
#use Scalar::Util qw( blessed );
use List::Util qw( max );
use FS::Conf;
use FS::part_export;
use FS::cdr;
use FS::UI::Web;
+use FS::export_cust_svc;
#most FS::svc_ classes are autoloaded in svc_x emthod
use FS::svc_acct; #this one is used in the cache stuff
$ticket_system = $conf->config('ticket_system')
});
+our $cache_enabled = 0;
+
+sub _simplecache {
+ my( $self, $hashref ) = @_;
+ if ( $cache_enabled && $hashref->{'svc'} ) {
+ $self->{'_svcpart'} = FS::part_svc->new($hashref);
+ }
+}
+
sub _cache {
my $self = shift;
my ( $hashref, $cache ) = @_;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
+ # delete associated export_cust_svc
+ foreach my $export_cust_svc (
+ qsearch('export_cust_svc',{ 'svcnum' => $self->svcnum })
+ ) {
+ my $error = $export_cust_svc->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
my $error = $self->SUPER::delete;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
sub part_svc_link {
my $self = shift;
my $agentnum = $self->pkgnum ? $self->cust_pkg->cust_main->agentnum : '';
- FS::part_svc_link->by_agentnum($agentnum, src_svcpart=>$self->svcpart, @_);
+ FS::part_svc_link->by_agentnum($agentnum,
+ src_svcpart=>$self->svcpart,
+ disabled => '',
+ @_
+ );
}
=item display_svcnum
sub part_svc {
my $self = shift;
- $self->{'_svcpart'}
- ? $self->{'_svcpart'}
- : qsearchs( 'part_svc', { 'svcpart' => $self->svcpart } );
+ return $self->{_svcpart} if $self->{_svcpart};
+ cluck 'cust_svc->part_svc called' if $DEBUG;
+ qsearchs( 'part_svc', { 'svcpart' => $self->svcpart } );
}
=item cust_pkg
return $cust_pkg->getfield('cancel') || '';
}
-=item label
+=item label [ LOCALE ]
Returns a list consisting of:
-- The name of this service (from part_svc)
+- The name of this service (from part_svc), optionally localized
- A meaningful identifier (username, domain, or mail alias)
- The table name (i.e. svc_domain) for this service
- svcnum
my($label, $value, $svcdb) = $cust_svc->label;
-=item label_long
+=item label_long [ LOCALE ]
Like the B<label> method, except the second item in the list ("meaningful
identifier") may be longer - typically, a full name is included.
sub _label {
my $self = shift;
my $method = shift;
+ my $locale = shift;
my $svc_x = $self->svc_x
or return "can't find ". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
- $self->$method($svc_x);
+ $self->$method($svc_x, undef, undef, $locale);
}
+# svc_label(_long) takes three arguments: end date, start date, locale
+# and FS::svc_*::label methods must accept those also, if they even care
+
sub svc_label { shift->_svc_label('label', @_); }
sub svc_label_long { shift->_svc_label('label_long', @_); }
sub _svc_label {
my( $self, $method, $svc_x ) = ( shift, shift, shift );
+ my ($end, $start, $locale) = @_;
(
- $self->part_svc->svc,
+ $self->part_svc->svc_locale($locale),
$svc_x->$method(@_),
$self->part_svc->svcdb,
$self->svcnum
=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END
-See L<FS::svc_acct/seconds_since_sqlradacct>. Equivalent to
-$cust_svc->svc_x->seconds_since_sqlradacct, but more efficient. Meaningless
-for records where B<svcdb> is not "svc_acct".
+Equivalent to $cust_svc->svc_x->seconds_since_sqlradacct, but
+more efficient. Meaningless for records where B<svcdb> is not
+svc_acct or svc_broadband.
=cut
-#note: implementation here, POD in FS::svc_acct
sub seconds_since_sqlradacct {
my($self, $start, $end) = @_;
=item attribute_since_sqlradacct TIMESTAMP_START TIMESTAMP_END ATTRIBUTE
See L<FS::svc_acct/attribute_since_sqlradacct>. Equivalent to
-$cust_svc->svc_x->attribute_since_sqlradacct, but more efficient. Meaningless
-for records where B<svcdb> is not "svc_acct".
+$cust_svc->svc_x->attribute_since_sqlradacct, but more efficient.
+Meaningless for records where B<svcdb> is not svc_acct or svc_broadband.
=cut
-#note: implementation here, POD in FS::svc_acct
#(false laziness w/seconds_since_sqlradacct above)
sub attribute_since_sqlradacct {
my($self, $start, $end, $attrib) = @_;
my @or =
map { my $table = $_;
my $search_sql = "FS::$table"->search_sql($string);
+ my $addl_from = "FS::$table"->search_sql_addl_from();
"SELECT $table.svcnum AS svcnum, '$table' AS svcdb ".
- "FROM $table WHERE $search_sql";
+ "FROM $table $addl_from WHERE $search_sql";
}
FS::part_svc->svc_tables;
# check status of cust_pkg
my $cust_pkg = $self->cust_pkg;
- return '' unless $cust_pkg->status eq 'on hold';
+ return '' unless $cust_pkg && $cust_pkg->status eq 'on hold';
# check flag on this svc
# small false laziness with $self->pkg_svc
my $svcdb = $cust_svc->part_svc->svcdb;
$h_search{'hashref'}{'svcnum'} = $svcnum;
$h_search{'table'} = "h_$svcdb";
- my $h_svc_x = qsearchs(\%h_search)
- or next;
- my $class = "FS::$svcdb";
- my $new_svc_x = $class->new({ $h_svc_x->hash });
- my $error = $new_svc_x->insert;
- warn "error repairing svcnum $svcnum ($svcdb) from history:\n$error\n"
- if $error;
+ my $h_svc_x = qsearchs(\%h_search);
+ if ( $h_svc_x ) {
+ my $class = "FS::$svcdb";
+ my $new_svc_x = $class->new({ $h_svc_x->hash });
+ my $error = $new_svc_x->insert;
+ warn "error repairing svcnum $svcnum ($svcdb) from history:\n$error\n"
+ if $error;
+ } else {
+ # can't be fixed, so remove the dangling cust_svc to avoid breaking
+ # stuff
+ my $error = $cust_svc->delete;
+ warn "error cleaning up missing svcnum $svcnum ($svcdb):\n$error\n";
+ }
}
'';