fix attribute importing bugs that borked the passwords
[freeside.git] / FS / FS / part_svc.pm
index e64f09a..aacc3ab 100644 (file)
@@ -2,8 +2,10 @@ package FS::part_svc;
 
 use strict;
 use vars qw( @ISA );
 
 use strict;
 use vars qw( @ISA );
-use FS::Record qw( qsearchs fields dbh );
+use FS::Record qw( qsearch qsearchs fields dbh );
 use FS::part_svc_column;
 use FS::part_svc_column;
+use FS::part_export;
+use FS::export_svc;
 
 @ISA = qw(FS::Record);
 
 
 @ISA = qw(FS::Record);
 
@@ -40,9 +42,7 @@ FS::Record.  The following fields are currently supported:
 =item svcdb - table used for this service.  See L<FS::svc_acct>,
 L<FS::svc_domain>, and L<FS::svc_forward>, among others.
 
 =item svcdb - table used for this service.  See L<FS::svc_acct>,
 L<FS::svc_domain>, and L<FS::svc_forward>, among others.
 
-=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 disabled - Disabled flag, empty or `Y'
 
 =back
 
 
 =back
 
@@ -59,18 +59,25 @@ database, see L<"insert">.
 
 sub table { 'part_svc'; }
 
 
 sub table { 'part_svc'; }
 
-=item insert
+=item insert EXTRA_FIELDS_ARRAYREF
 
 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.
+
+TODOC:
+
 =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.
+
+TODOC: EXTRA_FIELDS_ARRAYREF
 
 =cut
 
 sub insert {
   my $self = shift;
 
 =cut
 
 sub insert {
   my $self = shift;
+  my @fields = ();
+  @fields = @{shift(@_)} if @_;
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
 
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
@@ -97,7 +104,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', {
@@ -106,7 +113,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)
@@ -117,7 +124,7 @@ sub insert {
         $error = $part_svc_column->insert;
       }
     } else {
         $error = $part_svc_column->insert;
       }
     } else {
-      $error = $part_svc_column->delete;
+      $error = $previous ? $previous->delete : '';
     }
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
     }
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
@@ -142,11 +149,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 ] ]
 
 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
+
 =cut
 
 sub replace {
 =cut
 
 sub replace {
@@ -155,7 +166,68 @@ sub replace {
   return "Can't change svcdb for an existing service definition!"
     unless $old->svcdb eq $new->svcdb;
 
   return "Can't change svcdb for an existing service definition!"
     unless $old->svcdb eq $new->svcdb;
 
-  $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;
+
+  my $error = $new->SUPER::replace( $old );
+  if ( $error ) {
+    $dbh->rollback if $oldAutoCommit;
+    return $error;
+  }
+
+  if ( @_ && $_[0] eq '1.3-COMPAT' ) {
+    shift;
+    my @fields = ();
+    @fields = @{shift(@_)} if @_;
+
+    my $svcdb = $new->svcdb;
+    foreach my $field (
+      grep { $_ ne 'svcnum'
+             && defined( $new->getfield($svcdb.'__'.$_.'_flag') )
+           } (fields($svcdb),@fields)
+    ) {
+      my $part_svc_column = $new->part_svc_column($field);
+      my $previous = qsearchs('part_svc_column', {
+        'svcpart'    => $new->svcpart,
+        'columnname' => $field,
+      } );
+
+      my $flag = $new->getfield($svcdb.'__'.$field.'_flag');
+      if ( uc($flag) =~ /^([DFX])$/ ) {
+        $part_svc_column->setfield('columnflag', $1);
+        $part_svc_column->setfield('columnvalue',
+          $new->getfield($svcdb.'__'.$field)
+        );
+        if ( $previous ) {
+          $error = $part_svc_column->replace($previous);
+        } else {
+          $error = $part_svc_column->insert;
+        }
+      } else {
+        $error = $previous ? $previous->delete : '';
+      }
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
+      }
+    }
+  } else {
+    $dbh->rollback if $oldAutoCommit;
+    return 'non-1.3-COMPAT interface not yet written';
+    #not yet implemented
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  '';
 }
 
 =item check
 }
 
 =item check
@@ -175,37 +247,14 @@ sub check {
     $self->ut_numbern('svcpart')
     || $self->ut_text('svc')
     || $self->ut_alpha('svcdb')
     $self->ut_numbern('svcpart')
     || $self->ut_text('svc')
     || $self->ut_alpha('svcdb')
+    || $self->ut_enum('disabled', [ '', 'Y' ] )
   ;
   return $error if $error;
 
   my @fields = eval { fields( $recref->{svcdb} ) }; #might die
   return "Unknown svcdb!" unless @fields;
 
   ;
   return $error if $error;
 
   my @fields = eval { fields( $recref->{svcdb} ) }; #might die
   return "Unknown svcdb!" unless @fields;
 
-#  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
@@ -216,23 +265,43 @@ 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,
                                };
 }
 
-=back
+=item all_part_svc_column
 
 
-=head1 VERSION
+=cut
 
 
-$Id: part_svc.pm,v 1.3 2001-09-06 20:41:59 ivan Exp $
+sub all_part_svc_column {
+  my $self = shift;
+  qsearch('part_svc_column', { 'svcpart' => $self->svcpart } );
+}
+
+=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;
+  my %search;
+  $search{'exporttype'} = shift if @_;
+  map { qsearchs('part_export', { 'exportnum' => $_->exportnum, %search } ) }
+    qsearch('export_svc', { 'svcpart' => $self->svcpart } );
+}
+
+=back
 
 =head1 BUGS
 
 
 =head1 BUGS
 
@@ -241,11 +310,13 @@ 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
 
 =head1 SEE ALSO
 
-L<FS::Record>, L<FS::part_pkg>, L<FS::pkg_svc>, L<FS::cust_svc>,
-L<FS::svc_acct>, L<FS::svc_forward>, L<FS::svc_domain>, schema.html from the
-base documentation.
+L<FS::Record>, L<FS::part_svc_column>, L<FS::part_pkg>, L<FS::pkg_svc>,
+L<FS::cust_svc>, L<FS::svc_acct>, L<FS::svc_forward>, L<FS::svc_domain>,
+schema.html from the base documentation.
 
 =cut
 
 
 =cut