communigate pro provisioning, RT#7083
[freeside.git] / FS / FS / svc_Common.pm
index 2866bfe..ee270ca 100644 (file)
@@ -1,8 +1,9 @@
 package FS::svc_Common;
 
 use strict;
-use vars qw( @ISA $noexport_hack $DEBUG $me );
-use Carp qw( cluck carp croak ); #specify cluck have to specify them all..
+use vars qw( @ISA $noexport_hack $DEBUG $me
+             $overlimit_missing_cust_svc_nonfatal_kludge );
+use Carp qw( cluck carp croak confess ); #specify cluck have to specify them all
 use Scalar::Util qw( blessed );
 use FS::Record qw( qsearch qsearchs fields dbh );
 use FS::cust_main_Mixin;
@@ -18,6 +19,8 @@ use FS::inventory_class;
 $me = '[FS::svc_Common]';
 $DEBUG = 0;
 
+$overlimit_missing_cust_svc_nonfatal_kludge = 0;
+
 =head1 NAME
 
 FS::svc_Common - Object method for all svc_ records
@@ -151,6 +154,11 @@ sub label {
   $self->svcnum;
 }
 
+sub label_long {
+  my $self = shift;
+  $self->label(@_);
+}
+
 =item check
 
 Checks the validity of fields in this record.
@@ -247,9 +255,11 @@ sub insert {
     $self->svcpart($cust_svc->svcpart);
   }
 
-  my $error =    $self->set_auto_inventory
+  my $error =    $self->preinsert_hook_first
+              || $self->set_auto_inventory
               || $self->check
               || $self->_check_duplicate
+              || $self->preinsert_hook
               || $self->SUPER::insert;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
@@ -316,7 +326,9 @@ sub insert {
 }
 
 #fallbacks
+sub preinsert_hook_first { ''; }
 sub _check_duplcate { ''; }
+sub preinsert_hook { ''; }
 sub table_dupcheck_fields { (); }
 
 =item delete [ , OPTION => VALUE ... ]
@@ -397,7 +409,7 @@ sub replace {
 
   #redundant, but so any duplicate fields are maniuplated as appropriate
   # (svc_phone.phonenum)
-  my $error = $new->check;
+  $error = $new->check;
   if ( $error ) {
     $dbh->rollback if $oldAutoCommit;
     return $error;
@@ -574,6 +586,103 @@ sub part_svc {
 
 }
 
+=item svc_pbx
+
+Returns the FS::svc_pbx record for this service, if any (see L<FS::svc_pbx>).
+
+Only makes sense if the service has a pbxsvc field (currently, svc_phone and
+svc_acct).
+
+=cut
+
+# XXX FS::h_svc_{acct,phone} could have a history-aware svc_pbx override
+
+sub svc_pbx {
+  my $self = shift;
+  return '' unless $self->pbxsvc;
+  qsearchs( 'svc_pbx', { 'svcnum' => $self->pbxsvc } );
+}
+
+=item pbx_title
+
+Returns the title of the FS::svc_pbx record associated with this service, if
+any.
+
+Only makes sense if the service has a pbxsvc field (currently, svc_phone and
+svc_acct).
+
+=cut
+
+sub pbx_title {
+  my $self = shift;
+  my $svc_pbx = $self->svc_pbx or return '';
+  $svc_pbx->title;
+}
+
+=item pbx_select_hash %OPTIONS
+
+Can be called as an object method or a class method.
+
+Returns a hash SVCNUM => TITLE ...  representing the PBXes this customer
+that may be associated with this service.
+
+Currently available options are: I<pkgnum> I<svcpart>
+
+Only makes sense if the service has a pbxsvc field (currently, svc_phone and
+svc_acct).
+
+=cut
+
+#false laziness w/svc_acct::domain_select_hash
+sub pbx_select_hash {
+  my ($self, %options) = @_;
+  my %pbxes = ();
+  my $part_svc;
+  my $cust_pkg;
+
+  if (ref($self)) {
+    $part_svc = $self->part_svc;
+    $cust_pkg = $self->cust_svc->cust_pkg
+      if $self->cust_svc;
+  }
+
+  $part_svc = qsearchs('part_svc', { 'svcpart' => $options{svcpart} })
+    if $options{'svcpart'};
+
+  $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $options{pkgnum} })
+    if $options{'pkgnum'};
+
+  if ($part_svc && ( $part_svc->part_svc_column('pbxsvc')->columnflag eq 'S'
+                  || $part_svc->part_svc_column('pbxsvc')->columnflag eq 'F')) {
+    %pbxes = map { $_->svcnum => $_->title }
+             map { qsearchs('svc_pbx', { 'svcnum' => $_ }) }
+             split(',', $part_svc->part_svc_column('pbxsvc')->columnvalue);
+  } elsif ($cust_pkg) { # && !$conf->exists('svc_acct-alldomains') ) {
+    %pbxes = map { $_->svcnum => $_->title }
+             map { qsearchs('svc_pbx', { 'svcnum' => $_->svcnum }) }
+             map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) }
+             qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum });
+  } else {
+    #XXX agent-virt
+    %pbxes = map { $_->svcnum => $_->title } qsearch('svc_pbx', {} );
+  }
+
+  if ($part_svc && $part_svc->part_svc_column('pbxsvc')->columnflag eq 'D') {
+    my $svc_pbx = qsearchs('svc_pbx',
+      { 'svcnum' => $part_svc->part_svc_column('pbxsvc')->columnvalue } );
+    if ( $svc_pbx ) {
+      $pbxes{$svc_pbx->svcnum}  = $svc_pbx->title;
+    } else {
+      warn "unknown svc_pbx.svcnum for part_svc_column pbxsvc: ".
+           $part_svc->part_svc_column('pbxsvc')->columnvalue;
+
+    }
+  }
+
+  (%pbxes);
+
+}
+
 =item set_auto_inventory
 
 Sets any fields which auto-populate from inventory (see L<FS::part_svc>).
@@ -745,6 +854,25 @@ sub export_links {
   $return;
 }
 
+=item export_getsettings
+
+Runs export_getsettings callbacks and returns the two hashrefs.
+
+=cut
+
+sub export_getsettings {
+  my $self = shift;
+  my %settings = ();
+  my %defaults = ();
+  my $error = $self->export('getsettings', \%settings, \%defaults);
+  if ( $error ) {
+    #XXX bubble this up better
+    warn "error running export_getsetings: $error";
+    return ( {}, {} );
+  }
+  ( \%settings, \%defaults );
+}
+
 =item export HOOK [ EXPORT_ARGS ]
 
 Runs the provided export hook (i.e. "suspend", "unsuspend") for this service.
@@ -793,7 +921,19 @@ Sets or retrieves overlimit date.
 
 sub overlimit {
   my $self = shift;
-  $self->cust_svc->overlimit(@_);
+  #$self->cust_svc->overlimit(@_);
+  my $cust_svc = $self->cust_svc;
+  unless ( $cust_svc ) { #wtf?
+    my $error = "$me overlimit: missing cust_svc record for svc_acct svcnum ".
+                $self->svcnum;
+    if ( $overlimit_missing_cust_svc_nonfatal_kludge ) {
+      cluck "$error; continuing anyway as requested";
+      return '';
+    } else {
+      confess $error;
+    }
+  }
+  $cust_svc->overlimit(@_);
 }
 
 =item cancel