fix big in RADIUS session viewing when using an ignored-accounting export
[freeside.git] / FS / FS / part_svc.pm
index 82935dd..e7f205d 100644 (file)
@@ -4,6 +4,9 @@ use strict;
 use vars qw( @ISA );
 use FS::Record qw( qsearch qsearchs fields dbh );
 use FS::part_svc_column;
 use vars qw( @ISA );
 use FS::Record qw( qsearch qsearchs fields dbh );
 use FS::part_svc_column;
+use FS::part_export;
+use FS::export_svc;
+use FS::cust_svc;
 
 @ISA = qw(FS::Record);
 
 
 @ISA = qw(FS::Record);
 
@@ -19,8 +22,12 @@ FS::part_svc - Object methods for part_svc objects
   $record = new FS::part_svc { 'column' => 'value' };
 
   $error = $record->insert;
   $record = new FS::part_svc { 'column' => 'value' };
 
   $error = $record->insert;
+  $error = $record->insert( [ 'pseudofield' ] );
+  $error = $record->insert( [ 'pseudofield' ], \%exportnums );
 
   $error = $new_record->replace($old_record);
 
   $error = $new_record->replace($old_record);
+  $error = $new_record->replace($old_record, '1.3-COMPAT', [ 'pseudofield' ] );
+  $error = $new_record->replace($old_record, '1.3-COMPAT', [ 'pseudofield' ], \%exportnums );
 
   $error = $record->delete;
 
 
   $error = $record->delete;
 
@@ -57,19 +64,40 @@ database, see L<"insert">.
 
 sub table { 'part_svc'; }
 
 
 sub table { 'part_svc'; }
 
-=item insert
+=item insert [ EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ] 
 
 Adds this service definition to the database.  If there is an error, returns
 the error, otherwise returns false.
 
 
 Adds this service definition to the database.  If there is an error, returns
 the error, otherwise returns false.
 
+The following pseudo-fields may be defined, and will be maintained in
+the part_svc_column table appropriately (see L<FS::part_svc_column>).
+
+=over 4
+
 =item I<svcdb>__I<field> - Default or fixed value for I<field> in I<svcdb>.
 
 =item I<svcdb>__I<field> - Default or fixed value for I<field> in I<svcdb>.
 
-=item I<svcdb>__I<field>_flag - defines I<svcdb>__I<field> action: null, `D' for default, or `F' for fixed
+=item I<svcdb>__I<field>_flag - defines I<svcdb>__I<field> action: null, `D' for default, or `F' for fixed.  For virtual fields, can also be 'X' for excluded.
+
+=back
+
+If you want to add part_svc_column records for fields that do not exist as
+(real or virtual) fields in the I<svcdb> table, make sure to list then in 
+EXTRA_FIELDS_ARRAYREF also.
+
+If EXPORTNUMS_HASHREF is specified (keys are exportnums and values are
+boolean), the appopriate export_svc records will be inserted.
 
 =cut
 
 sub insert {
   my $self = shift;
 
 =cut
 
 sub insert {
   my $self = shift;
+  my @fields = ();
+  my @exportnums = ();
+  @fields = @{shift(@_)} if @_;
+  if ( @_ ) {
+    my $exportnums = shift;
+    @exportnums = grep $exportnums->{$_}, keys %$exportnums;
+  }
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -88,6 +116,8 @@ sub insert {
     return $error;
   }
 
     return $error;
   }
 
+  # add part_svc_column records
+
   my $svcdb = $self->svcdb;
 #  my @rows = map { /^${svcdb}__(.*)$/; $1 }
 #    grep ! /_flag$/,
   my $svcdb = $self->svcdb;
 #  my @rows = map { /^${svcdb}__(.*)$/; $1 }
 #    grep ! /_flag$/,
@@ -96,7 +126,7 @@ sub insert {
   foreach my $field (
     grep { $_ ne 'svcnum'
            && defined( $self->getfield($svcdb.'__'.$_.'_flag') )
   foreach my $field (
     grep { $_ ne 'svcnum'
            && defined( $self->getfield($svcdb.'__'.$_.'_flag') )
-         } fields($svcdb)
+         } (fields($svcdb), @fields)
   ) {
     my $part_svc_column = $self->part_svc_column($field);
     my $previous = qsearchs('part_svc_column', {
   ) {
     my $part_svc_column = $self->part_svc_column($field);
     my $previous = qsearchs('part_svc_column', {
@@ -105,7 +135,7 @@ sub insert {
     } );
 
     my $flag = $self->getfield($svcdb.'__'.$field.'_flag');
     } );
 
     my $flag = $self->getfield($svcdb.'__'.$field.'_flag');
-    if ( uc($flag) =~ /^([DF])$/ ) {
+    if ( uc($flag) =~ /^([DFX])$/ ) {
       $part_svc_column->setfield('columnflag', $1);
       $part_svc_column->setfield('columnvalue',
         $self->getfield($svcdb.'__'.$field)
       $part_svc_column->setfield('columnflag', $1);
       $part_svc_column->setfield('columnvalue',
         $self->getfield($svcdb.'__'.$field)
@@ -125,6 +155,20 @@ sub insert {
 
   }
 
 
   }
 
+  # add export_svc records
+
+  foreach my $exportnum ( @exportnums ) {
+    my $export_svc = new FS::export_svc ( {
+      'exportnum' => $exportnum,
+      'svcpart'   => $self->svcpart,
+    } );
+    $error = $export_svc->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return $error;
+    }
+  }
+
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   '';
   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
 
   '';
@@ -132,7 +176,7 @@ sub insert {
 
 =item delete
 
 
 =item delete
 
-Currently unimplemented.
+Currently unimplemented.  Set the "disabled" field instead.
 
 =cut
 
 
 =cut
 
@@ -141,11 +185,15 @@ sub delete {
 # check & make sure the svcpart isn't in cust_svc or pkg_svc (in any packages)?
 }
 
 # check & make sure the svcpart isn't in cust_svc or pkg_svc (in any packages)?
 }
 
-=item replace OLD_RECORD
+=item replace OLD_RECORD [ '1.3-COMPAT' [ , EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ] ]
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
 
 Replaces OLD_RECORD with this one in the database.  If there is an error,
 returns the error, otherwise returns false.
 
+TODOC: 1.3-COMPAT
+
+TODOC: EXTRA_FIELDS_ARRAYREF (same as insert method)
+
 =cut
 
 sub replace {
 =cut
 
 sub replace {
@@ -172,11 +220,18 @@ sub replace {
   }
 
   if ( @_ && $_[0] eq '1.3-COMPAT' ) {
   }
 
   if ( @_ && $_[0] eq '1.3-COMPAT' ) {
+    shift;
+    my @fields = ();
+    @fields = @{shift(@_)} if @_;
+    my $exportnums = @_ ? shift : '';
+
+   # maintain part_svc_column records
+
     my $svcdb = $new->svcdb;
     foreach my $field (
       grep { $_ ne 'svcnum'
              && defined( $new->getfield($svcdb.'__'.$_.'_flag') )
     my $svcdb = $new->svcdb;
     foreach my $field (
       grep { $_ ne 'svcnum'
              && defined( $new->getfield($svcdb.'__'.$_.'_flag') )
-           } fields($svcdb)
+           } (fields($svcdb),@fields)
     ) {
       my $part_svc_column = $new->part_svc_column($field);
       my $previous = qsearchs('part_svc_column', {
     ) {
       my $part_svc_column = $new->part_svc_column($field);
       my $previous = qsearchs('part_svc_column', {
@@ -185,7 +240,7 @@ sub replace {
       } );
 
       my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
       } );
 
       my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
-      if ( uc($flag) =~ /^([DF])$/ ) {
+      if ( uc($flag) =~ /^([DFX])$/ ) {
         $part_svc_column->setfield('columnflag', $1);
         $part_svc_column->setfield('columnvalue',
           $new->getfield($svcdb.'__'.$field)
         $part_svc_column->setfield('columnflag', $1);
         $part_svc_column->setfield('columnvalue',
           $new->getfield($svcdb.'__'.$field)
@@ -203,6 +258,39 @@ sub replace {
         return $error;
       }
     }
         return $error;
       }
     }
+
+    # maintain export_svc records
+
+    if ( $exportnums ) {
+
+      #false laziness w/ edit/process/agent_type.cgi
+      foreach my $part_export ( qsearch('part_export', {}) ) {
+        my $exportnum = $part_export->exportnum;
+        my $hashref = {
+          'exportnum' => $exportnum,
+          'svcpart'   => $new->svcpart,
+        };
+        my $export_svc = qsearchs('export_svc', $hashref);
+
+        if ( $export_svc && ! $exportnums->{$exportnum} ) {
+          $error = $export_svc->delete;
+          if ( $error ) {
+            $dbh->rollback if $oldAutoCommit;
+            return $error;
+          }
+        } elsif ( ! $export_svc && $exportnums->{$exportnum} ) {
+          $export_svc = new FS::export_svc ( $hashref );
+          $error = $export_svc->insert;
+          if ( $error ) {
+            $dbh->rollback if $oldAutoCommit;
+            return $error;
+          }
+        }
+        
+      }
+
+    }
+
   } else {
     $dbh->rollback if $oldAutoCommit;
     return 'non-1.3-COMPAT interface not yet written';
   } else {
     $dbh->rollback if $oldAutoCommit;
     return 'non-1.3-COMPAT interface not yet written';
@@ -238,32 +326,7 @@ sub check {
   my @fields = eval { fields( $recref->{svcdb} ) }; #might die
   return "Unknown svcdb!" unless @fields;
 
   my @fields = eval { fields( $recref->{svcdb} ) }; #might die
   return "Unknown svcdb!" unless @fields;
 
-##REPLACED BY part_svc_column
-#  my $svcdb;
-#  foreach $svcdb ( qw(
-#    svc_acct svc_acct_sm svc_domain
-#  ) ) {
-#    my @rows = map { /^${svcdb}__(.*)$/; $1 }
-#      grep ! /_flag$/,
-#        grep /^${svcdb}__/,
-#          fields('part_svc');
-#    foreach my $row (@rows) {
-#      unless ( $svcdb eq $recref->{svcdb} ) {
-#        $recref->{$svcdb.'__'.$row}='';
-#        $recref->{$svcdb.'__'.$row.'_flag'}='';
-#        next;
-#      }
-#      $recref->{$svcdb.'__'.$row.'_flag'} =~ /^([DF]?)$/
-#        or return "Illegal flag for $svcdb $row";
-#      $recref->{$svcdb.'__'.$row.'_flag'} = $1;
-#
-#      my $error = $self->ut_anything($svcdb.'__'.$row);
-#      return $error if $error;
-#
-#    }
-#  }
-
-  ''; #no error
+  $self->SUPER::check;
 }
 
 =item part_svc_column COLUMNNAME
 }
 
 =item part_svc_column COLUMNNAME
@@ -274,12 +337,12 @@ COLUMNNAME, or a new part_svc_column object if none exists.
 =cut
 
 sub part_svc_column {
 =cut
 
 sub part_svc_column {
-  my $self = shift;
-  my $columnname = shift;
-  qsearchs('part_svc_column',  {
-                                 'svcpart'    => $self->svcpart,
-                                 'columnname' => $columnname,
-                               }
+  my( $self, $columnname) = @_;
+  $self->svcpart &&
+    qsearchs('part_svc_column',  {
+                                   'svcpart'    => $self->svcpart,
+                                   'columnname' => $columnname,
+                                 }
   ) or new FS::part_svc_column {
                                  'svcpart'    => $self->svcpart,
                                  'columnname' => $columnname,
   ) or new FS::part_svc_column {
                                  'svcpart'    => $self->svcpart,
                                  'columnname' => $columnname,
@@ -295,21 +358,44 @@ sub all_part_svc_column {
   qsearch('part_svc_column', { 'svcpart' => $self->svcpart } );
 }
 
   qsearch('part_svc_column', { 'svcpart' => $self->svcpart } );
 }
 
-=item part_export
+=item part_export [ EXPORTTYPE ]
+
+Returns all exports (see L<FS::part_export>) for this service, or, if an
+export type is specified, only returns exports of the given type.
 
 =cut
 
 sub part_export {
   my $self = shift;
 
 =cut
 
 sub part_export {
   my $self = shift;
-  my %search = ( 'svcpart' => $self->svcpart );
-  qsearch('part_export', \%search);
+  my %search;
+  $search{'exporttype'} = shift if @_;
+  map { qsearchs('part_export', { 'exportnum' => $_->exportnum, %search } ) }
+    qsearch('export_svc', { 'svcpart' => $self->svcpart } );
 }
 
 }
 
-=back
+=item cust_svc
 
 
-=head1 VERSION
+Returns a list of associated FS::cust_svc records.
 
 
-$Id: part_svc.pm,v 1.10 2002-03-20 21:31:49 ivan Exp $
+=cut
+
+sub cust_svc {
+  my $self = shift;
+  qsearch('cust_svc', { 'svcpart' => $self->svcpart } );
+}
+
+=item svc_x
+
+Returns a list of associated FS::svc_* records.
+
+=cut
+
+sub svc_x {
+  my $self = shift;
+  map { $_->svc_x } $self->cust_svc;
+}
+
+=back
 
 =head1 BUGS
 
 
 =head1 BUGS
 
@@ -318,6 +404,8 @@ Delete is unimplemented.
 The list of svc_* tables is hardcoded.  When svc_acct_pop is renamed, this
 should be fixed.
 
 The list of svc_* tables is hardcoded.  When svc_acct_pop is renamed, this
 should be fixed.
 
+all_part_svc_column method should be documented
+
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::part_svc_column>, L<FS::part_pkg>, L<FS::pkg_svc>,
 =head1 SEE ALSO
 
 L<FS::Record>, L<FS::part_svc_column>, L<FS::part_pkg>, L<FS::pkg_svc>,