- should finish off the part_svc -> part_export s/one-to-many/many-to-many/
authorivan <ivan>
Fri, 12 Apr 2002 13:22:03 +0000 (13:22 +0000)
committerivan <ivan>
Fri, 12 Apr 2002 13:22:03 +0000 (13:22 +0000)
  transition (closes: Bug#375)
- fixes a nasty export scoping bug with message catalogs, whew

19 files changed:
FS/FS/Msgcat.pm [new file with mode: 0644]
FS/FS/Record.pm
FS/FS/cust_main.pm
FS/FS/cust_main_invoice.pm
FS/FS/msgcat.pm
FS/FS/part_export.pm
FS/FS/svc_acct.pm
FS/MANIFEST
FS/t/Msgcat.t [new file with mode: 0644]
fs_signup/fs_signup_server
htetc/global.asa
htetc/handler.pl
httemplate/browse/part_svc.cgi
httemplate/edit/part_export.cgi
httemplate/edit/part_svc.cgi
httemplate/edit/process/agent_type.cgi
httemplate/edit/process/part_export.cgi
httemplate/edit/process/part_svc.cgi
httemplate/misc/delete-customer.cgi

diff --git a/FS/FS/Msgcat.pm b/FS/FS/Msgcat.pm
new file mode 100644 (file)
index 0000000..625743d
--- /dev/null
@@ -0,0 +1,98 @@
+package FS::Msgcat;
+
+use strict;
+use vars qw( @ISA @EXPORT_OK $conf $locale $debug );
+use Exporter;
+use FS::UID;
+#use FS::Record qw( qsearchs ); # wtf?  won't import...
+use FS::Record;
+use FS::Conf;
+use FS::msgcat;
+
+@ISA = qw(Exporter);
+@EXPORT_OK = qw( gettext geterror );
+
+$FS::UID::callback{'Msgcat'} = sub {
+  $conf = new FS::Conf;
+  $locale = $conf->config('locale') || 'en_US';
+  $debug = $conf->exists('show-msgcat-codes')
+};
+
+=head1 NAME
+
+FS::Msgcat - Message catalog functions
+
+=head1 SYNOPSIS
+
+  use FS::Msgcat qw(gettext geterror);
+
+  #simple interface for retreiving messages...
+  $message = gettext('msgcode');
+  #or errors (includes the error code)
+  $message = geterror('msgcode');
+
+=head1 DESCRIPTION
+
+FS::Msgcat provides functions to use the message catalog.  If you want to
+maintain the message catalog database, see L<FS::msgcat> instead.
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item gettext MSGCODE
+
+Returns the full message for the supplied message code.
+
+=cut
+
+sub gettext {
+  $debug ? geterror(@_) : _gettext(@_);
+}
+
+sub _gettext {
+  my $msgcode = shift;
+  my $msgcat = FS::Record::qsearchs('msgcat', {
+    'msgcode' => $msgcode,
+    'locale' => $locale
+  } );
+  if ( $msgcat ) {
+    $msgcat->msg;
+  } else {
+    warn "WARNING: message for msgcode $msgcode in locale $locale not found";
+    $msgcode;
+  }
+
+}
+
+=item geterror MSGCODE
+
+Returns the full message for the supplied message code, including the message
+code.
+
+=cut
+
+sub geterror {
+  my $msgcode = shift;
+  my $msg = _gettext($msgcode);
+  if ( $msg eq $msgcode ) {
+    "Error code $msgcode (message for locale $locale not found)";
+  } else {
+    "$msg (error code $msgcode)";
+  }
+}
+
+=back
+
+=head1 BUGS
+
+i18n/l10n, eek
+
+=head1 SEE ALSO
+
+L<FS::msgcat>, L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
index 978ea72..cb42b26 100644 (file)
@@ -12,7 +12,7 @@ use DBI qw(:sql_types);
 use DBIx::DBSchema 0.19;
 use FS::UID qw(dbh checkruid getotaker datasrc driver_name);
 use FS::SearchCache;
-use FS::msgcat qw(gettext);
+use FS::Msgcat qw(gettext);
 
 @ISA = qw(Exporter);
 @EXPORT_OK = qw(dbh fields hfields qsearch qsearchs dbdef jsearch);
@@ -572,7 +572,7 @@ sub delete {
   $h_sth->execute or return $h_sth->errstr if $h_sth;
   dbh->commit or croak dbh->errstr if $FS::UID::AutoCommit;
 
-  #no need to needlessly destoy the data either
+  #no need to needlessly destoy the data either (causes problems actually)
   #undef $self; #no need to keep object!
 
   '';
@@ -825,9 +825,12 @@ false.
 
 sub ut_text {
   my($self,$field)=@_;
+  warn "msgcat ". \&msgcat. "\n";
+  warn "notexist ". \&notexist. "\n";
+  warn "AUTOLOAD ". \&AUTOLOAD. "\n";
   $self->getfield($field) =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/]+)$/
     or return gettext('illegal_or_empty_text'). " $field: ".
-              $self->getfield($field);
+               $self->getfield($field);
   $self->setfield($field,$1);
   '';
 }
index e1a5173..fd1ccd7 100644 (file)
@@ -26,7 +26,7 @@ use FS::queue;
 use FS::part_pkg;
 use FS::part_bill_event;
 use FS::cust_bill_event;
-use FS::msgcat qw(gettext);
+use FS::Msgcat qw(gettext);
 
 @ISA = qw( FS::Record );
 
index b82e2e7..a5533a0 100644 (file)
@@ -7,7 +7,7 @@ use FS::Record qw( qsearchs );
 use FS::Conf;
 use FS::cust_main;
 use FS::svc_acct;
-use FS::msgcat qw(gettext);
+use FS::Msgcat qw(gettext);
 
 @ISA = qw( FS::Record );
 
@@ -170,7 +170,7 @@ sub address {
 
 =head1 VERSION
 
-$Id: cust_main_invoice.pm,v 1.11 2002-04-10 13:42:48 ivan Exp $
+$Id: cust_main_invoice.pm,v 1.12 2002-04-12 13:22:02 ivan Exp $
 
 =head1 BUGS
 
index 3eca14b..fa10d34 100644 (file)
@@ -1,20 +1,12 @@
 package FS::msgcat;
 
 use strict;
-use vars qw( @ISA @EXPORT_OK $conf $locale $debug );
+use vars qw( @ISA );
 use Exporter;
 use FS::UID;
 use FS::Record qw( qsearchs );
-use FS::Conf;
 
 @ISA = qw(FS::Record);
-@EXPORT_OK = qw( gettext geterror );
-
-$FS::UID::callback{'msgcat'} = sub {
-  $conf = new FS::Conf;
-  $locale = $conf->config('locale') || 'en_US';
-  $debug = $conf->exists('show-msgcat-codes')
-};
 
 =head1 NAME
 
@@ -22,14 +14,8 @@ FS::msgcat - Object methods for message catalog entries
 
 =head1 SYNOPSIS
 
-  use FS::msgcat qw(gettext);
-
-  #simple interface for retreiving messages...
-  $message = gettext('msgcode');
-  #or errors (includes the error code)
-  $message = geterror('msgcode');
+  use FS::msgcat;
 
-  #maintenance stuff
   $record = new FS::msgcat \%hash;
   $record = new FS::msgcat { 'column' => 'value' };
 
@@ -58,6 +44,8 @@ from FS::Record.  The following fields are currently supported:
 
 =back
 
+If you just want to B<use> message catalogs, see L<FS::Msgcat>.
+
 =head1 METHODS
 
 =over 4
@@ -130,61 +118,13 @@ sub check {
 
 =back
 
-=head1 SUBROUTINES
-
-=over 4
-
-=item gettext MSGCODE
-
-Returns the full message for the supplied message code.
-
-=cut
-
-sub gettext {
-  $debug ? geterror(@_) : _gettext(@_);
-}
-
-sub _gettext {
-  my $msgcode = shift;
-  my $msgcat = qsearchs('msgcat', {
-    'msgcode' => $msgcode,
-    'locale' => $locale
-  } );
-  if ( $msgcat ) {
-    $msgcat->msg;
-  } else {
-    warn "WARNING: message for msgcode $msgcode in locale $locale not found";
-    $msgcode;
-  }
-
-}
-
-=item geterror MSGCODE
-
-Returns the full message for the supplied message code, including the message
-code.
-
-=cut
-
-sub geterror {
-  my $msgcode = shift;
-  my $msg = _gettext($msgcode);
-  if ( $msg eq $msgcode ) {
-    "Error code $msgcode (message for locale $locale not found)";
-  } else {
-    "$msg (error code $msgcode)";
-  }
-}
-
-=back
-
 =head1 BUGS
 
 i18n/l10n, eek
 
 =head1 SEE ALSO
 
-L<FS::Record>, schema.html from the base documentation.
+L<FS::Msgcat>, L<FS::Record>, schema.html from the base documentation.
 
 =cut
 
index 8af413b..835f531 100644 (file)
@@ -1,13 +1,15 @@
 package FS::part_export;
 
 use strict;
-use vars qw( @ISA );
+use vars qw( @ISA @EXPORT_OK %exports );
+use Exporter;
 use FS::Record qw( qsearch qsearchs dbh );
 use FS::part_svc;
 use FS::part_export_option;
 use FS::export_svc;
 
 @ISA = qw(FS::Record);
+@EXPORT_OK = qw(export_info);
 
 =head1 NAME
 
@@ -428,10 +430,118 @@ sub _export_delete {
 
 =back
 
+=head1 SUBROUTINES
+
+=over 4
+
+=item export_info [ SVCDB ]
+
+Returns a hash reference of the exports for the given I<svcdb>, or if no
+I<svcdb> is specified, for all exports.  The keys of the hash are
+I<exporttype>s and the values are again hash references containing information
+on the export:
+
+  'desc'     => 'Description',
+  'options'  => {
+                  'option'  => { label=>'Option Label' },
+                  'option2' => { label=>'Another label' },
+                },
+  'nodomain' => 'Y', #or ''
+  'notes'    => 'Additional notes',
+
+=cut
+
+sub export_info {
+  #warn $_[0];
+  return $exports{$_[0]} if @_;
+  #{ map { %{$exports{$_}} } keys %exports };
+  my $r = { map { %{$exports{$_}} } keys %exports };
+}
+
+=item exporttype2svcdb EXPORTTYPE
+
+Returns the applicable I<svcdb> for an I<exporttype>.
+
+=cut
+
+sub exporttype2svcdb {
+  my $exporttype = $_[0];
+  foreach my $svcdb ( keys %exports ) {
+    return $svcdb if grep { $exporttype eq $_ } keys %{$exports{$svcdb}};
+  }
+  '';
+}
+
+%exports = (
+  'svc_acct' => {
+    'sysvshell' => {
+      'desc' =>
+        'Batch export of /etc/passwd and /etc/shadow files (Linux/SysV)',
+      'options' => {},
+    },
+    'bsdshell' => {
+      'desc' =>
+        'Batch export of /etc/passwd and /etc/master.passwd files (BSD)',
+      'options' => {},
+    },
+#    'nis' => {
+#      'desc' =>
+#        'Batch export of /etc/global/passwd and /etc/global/shadow for NIS ',
+#      'options' => {},
+#    },
+    'bsdshell' => {
+      'desc' =>
+        'Batch export of /etc/passwd and /etc/master.passwd files (BSD)',
+      'options' => {},
+    },
+    'textradius' => {
+      'desc' => 'Batch export of a text /etc/raddb/users file (Livingston, Cistron)',
+    },
+    'sqlradius' => {
+      'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
+      'options' => {
+        'datasrc'  => { label=>'DBI data source' },
+        'username' => { label=>'Database username' },
+        'password' => { label=>'Database password' },
+      },
+      'nodomain' => 'Y',
+      'notes' => 'Not specifying datasrc will export to the freeside database? (no...  notes on MySQL replication, DBI::Proxy, etc., from Conf.pm && export.html etc., reset with bin/sqlradius_reset',
+    },
+    'cyrus' => {
+      'desc' => 'Real-time export to Cyrus IMAP server',
+    },
+    'cp' => {
+      'desc' => 'Real-time export to Critical Path Account Provisioning Protocol',
+    },
+    'infostreet' => {
+      'desc' => 'Real-time export to InfoStreet streetSmartAPI',
+      'options' => {
+        'url'      => { label=>'XML-RPC Access URL', },
+        'login'    => { label=>'InfoStreet login', },
+        'password' => { label=>'InfoStreet password', },
+        'groupID'  => { label=>'InfoStreet groupID', },
+      },
+      'nodomain' => 'Y',
+      'notes' => 'Real-time export to <a href="http://www.infostreet.com/">InfoStreet</a> streetSmartAPI.  Requires installation of <a href="http://search.cpan.org/search?dist=Frontier-Client">Frontier::Client</a> from CPAN.',
+    }
+  },
+
+  'svc_domain' => {},
+
+  'svc_acct_sm' => {},
+
+  'svc_forward' => {},
+
+  'svc_www' => {},
+
+);
+
+=back
+
 =head1 NEW EXPORT CLASSES
 
-Should be added to httemplate/edit/part_export.cgi and a module should
-be FS/FS/part_export/ (an example may be found in eg/export_template.pm)
+Should be added to the %export hash here, and a module should be added in
+FS/FS/part_export/ (an example may be found in eg/export_template.pm)
 
 =head1 BUGS
 
index 030ffbe..38e24c1 100644 (file)
@@ -28,7 +28,7 @@ use FS::svc_domain;
 use FS::raddb;
 use FS::queue;
 use FS::radius_usergroup;
-use FS::msgcat qw(gettext);
+use FS::Msgcat qw(gettext);
 
 @ISA = qw( FS::svc_Common );
 
index 440c755..1c90dfc 100644 (file)
@@ -27,6 +27,7 @@ FS/UI/CGI.pm
 FS/UI/Gtk.pm
 FS/UI/agent.pm
 FS/UID.pm
+FS/Msgcat.pm
 FS/agent.pm
 FS/agent_type.pm
 FS/cust_bill.pm
@@ -80,6 +81,8 @@ t/CGI.t
 t/Conf.t
 t/ConfItem.t
 t/Record.t
+t/UID.t
+t/Msgcat.t
 t/cust_bill.t
 t/cust_bill_event.t
 t/cust_bill_pay.t
@@ -124,5 +127,4 @@ t/type_pkgs.t
 t/queue.t
 t/queue_arg.t
 t/msgcat.t
-t/UID.t
 t/raddb.t
diff --git a/FS/t/Msgcat.t b/FS/t/Msgcat.t
new file mode 100644 (file)
index 0000000..29e71b3
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::Msgcat;
+$loaded=1;
+print "ok 1\n";
index ebf424c..41fed9a 100755 (executable)
@@ -13,7 +13,7 @@ use FS::Conf;
 use FS::Record qw( qsearch qsearchs );
 use FS::cust_main_county;
 use FS::cust_main;
-use FS::msgcat qw(gettext);
+use FS::Msgcat qw(gettext);
 
 use vars qw( $opt $Debug );
 
index 0576951..62f4544 100644 (file)
@@ -15,6 +15,7 @@ use FS::Record qw(qsearch qsearchs fields dbdef);
 use FS::Conf;
 use FS::CGI qw(header menubar popurl table itable ntable idiot eidiot
                small_custview myexit);
+use FS::Msgcat qw(gettext geterror);
 
 use FS::agent;
 use FS::agent_type;
@@ -48,7 +49,8 @@ use FS::svc_www;
 use FS::type_pkgs;
 use FS::part_export;
 use FS::part_export_option;
-use FS::msgcat qw(gettext geterror);
+use FS::export_svc;
+use FS::msgcat;
 
 sub Script_OnStart {
   $Response->AddHeader('Pragma' => 'no-cache');
index 2f8146e..056efa8 100644 (file)
@@ -72,6 +72,7 @@ sub handler
       use FS::Conf;
       use FS::CGI qw(header menubar popurl table itable ntable idiot eidiot
                      small_custview myexit);
+      use FS::Msgcat qw(gettext geterror);
 
       use FS::agent;
       use FS::agent_type;
@@ -105,7 +106,8 @@ sub handler
       use FS::type_pkgs;
       use FS::part_export;
       use FS::part_export_option;
-      use FS::msgcat qw(gettext geterror);
+      use FS::export_svc;
+      use FS::msgcat;
 
       *CGI::redirect = sub {
         my( $self, $location ) = @_;
index c8adebc..4c9b1bd 100755 (executable)
@@ -66,8 +66,12 @@ function part_export_areyousure(href) {
       <%= $hashref->{svcdb} %></TD>
     <TD ROWSPAN=<%= $rowspan %>><%= itable() %>
 <%
-  my @part_export = qsearch('part_export', { svcpart => $part_svc->svcpart } );
-  foreach my $part_export ( @part_export ) {
+#  my @part_export =
+map { qsearchs('part_export', { exportnum => $_->exportnum } ) } qsearch('export_svc', { svcpart => $part_svc->svcpart } ) ;
+  foreach my $part_export (
+    map { qsearchs('part_export', { exportnum => $_->exportnum } ) } 
+      qsearch('export_svc', { svcpart => $part_svc->svcpart } )
+  ) {
 %>
       <TR>
         <TD><A HREF="<%= $p %>edit/part_export.cgi?<%= $part_export->exportnum %>"><%= $part_export->exporttype %> to <%= $part_export->machine %></A></TD></TR>
index f312740..77b80d0 100644 (file)
@@ -21,76 +21,10 @@ if ( $cgi->param('error') ) {
 }
 $action ||= $part_export->exportnum ? 'Edit' : 'Add';
 
-my %exports = (
-  'svc_acct' => {
-    'sysvshell' => {
-      'desc' =>
-        'Batch export of /etc/passwd and /etc/shadow files (Linux/SysV)',
-      'options' => {},
-    },
-    'bsdshell' => {
-      'desc' =>
-        'Batch export of /etc/passwd and /etc/master.passwd files (BSD)',
-      'options' => {},
-    },
-#    'nis' => {
-#      'desc' =>
-#        'Batch export of /etc/global/passwd and /etc/global/shadow for NIS ',
-#      'options' => {},
-#    },
-    'bsdshell' => {
-      'desc' =>
-        'Batch export of /etc/passwd and /etc/master.passwd files (BSD)',
-      'options' => {},
-    },
-    'textradius' => {
-      'desc' => 'Batch export of a text /etc/raddb/users file (Livingston, Cistron)',
-    },
-    'sqlradius' => {
-      'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
-      'options' => {
-        'datasrc'  => { label=>'DBI data source' },
-        'username' => { label=>'Database username' },
-        'password' => { label=>'Database password' },
-      },
-      'nodomain' => 'Y',
-      'notes' => 'Not specifying datasrc will export to the freeside database? (no...  notes on MySQL replication, DBI::Proxy, etc., from Conf.pm && export.html etc., reset with bin/sqlradius_reset',
-    },
-    'cyrus' => {
-      'desc' => 'Real-time export to Cyrus IMAP server',
-    },
-    'cp' => {
-      'desc' => 'Real-time export to Critical Path Account Provisioning Protocol',
-    },
-    'infostreet' => {
-      'desc' => 'Real-time export to InfoStreet streetSmartAPI',
-      'options' => {
-        'url'      => { label=>'XML-RPC Access URL', },
-        'login'    => { label=>'InfoStreet login', },
-        'password' => { label=>'InfoStreet password', },
-        'groupID'  => { label=>'InfoStreet groupID', },
-      },
-      'nodomain' => 'Y',
-      'notes' => 'Real-time export to <a href="http://www.infostreet.com/">InfoStreet</a> streetSmartAPI.  Requires installation of <a href="http://search.cpan.org/search?dist=Frontier-Client">Frontier::Client</a> from CPAN.',
-    }
-  },
-
-  'svc_domain' => {},
-
-  'svc_acct_sm' => {},
-
-  'svc_forward' => {},
-
-  'svc_www' => {},
-
-);
-
-#my $svcdb = $part_export->part_svc->svcdb;
-#YUCK
-my $svcdb = 'svc_acct';
+#my $exports = FS::part_export::export_info($svcdb);
+my $exports = FS::part_export::export_info();
 
-my %layers = map { $_ => "$_ - ". $exports{$svcdb}{$_}{desc} }
-               keys %{$exports{$svcdb}};
+my %layers = map { $_ => "$_ - ". $exports->{$_}{desc} } keys %$exports;
 $layers{''}='';
 
 my $widget = new HTML::Widgets::SelectLayers(
@@ -105,9 +39,9 @@ my $widget = new HTML::Widgets::SelectLayers(
     my $layer = shift;
     my $html = qq!<INPUT TYPE="hidden" NAME="exporttype" VALUE="$layer">!.
                ntable("#cccccc",2);
-    foreach my $option ( keys %{$exports{$svcdb}->{$layer}{options}} ) {
+    foreach my $option ( keys %{$exports->{$layer}{options}} ) {
 #    foreach my $option ( qw(url login password groupID ) ) {
-      my $optinfo = $exports{$svcdb}->{$layer}{options}{$option};
+      my $optinfo = $exports->{$layer}{options}{$option};
       my $label = $optinfo->{label};
       my $value = $cgi->param($option) || $part_export->option($option);
       $html .= qq!<TR><TD ALIGN="right">$label</TD><TD>!.
@@ -117,10 +51,10 @@ my $widget = new HTML::Widgets::SelectLayers(
     $html .= '</TABLE>';
 
     $html .= '<INPUT TYPE="hidden" NAME="options" VALUE="'.
-             join(',', keys %{$exports{$svcdb}->{$layer}{options}} ). '">';
+             join(',', keys %{$exports->{$layer}{options}} ). '">';
 
     $html .= '<INPUT TYPE="hidden" NAME="nodomain" VALUE="'.
-             $exports{$svcdb}->{$layer}{nodomain}. '">';
+             $exports->{$layer}{nodomain}. '">';
 
     $html .= '<INPUT TYPE="submit" VALUE="'.
              ( $part_export->exportnum ? "Apply changes" : "Add export" ).
index b4900a0..e9c571f 100755 (executable)
@@ -132,8 +132,30 @@ my %defs = (
     'form_checkbox'  => [ 'disabled' ],
     'layer_callback' => sub {
       my $layer = shift;
-      my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!.
-                 table(). "<TH>Field</TH><TH COLSPAN=2>Modifier</TH>";
+      my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!;
+
+      my $columns = 3;
+      my $count = 0;
+      my @part_export =
+        grep { $layer eq FS::part_export::exporttype2svcdb($_->exporttype) }
+          qsearch( 'part_export', {} );
+      $html .= '<BR><BR>'. table().
+               table(). "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>";
+      foreach my $part_export ( @part_export ) {
+        $html .= '<TD><INPUT TYPE="checkbox"'.
+                 ' NAME="exportnum'. $part_export->exportnum. '"  VALUE="1" ';
+        $html .= 'CHECKED'
+          if qsearchs( 'export_svc', {
+                                       exportnum => $part_export->exportnum,
+                                       svcpart   => $part_svc->svcpart       });
+        $html .= '> '. $part_export->exporttype. ' to '. $part_export->machine.
+                 '</TD>';
+        $count++;
+        $html .= '</TR><TR>' unless $count % $columns;
+      }
+      $html .= '</TR></TABLE><BR><BR>';
+
+      $html .=  table(). "<TH>Field</TH><TH COLSPAN=2>Modifier</TH>";
       #yucky kludge
       my @fields = defined( $FS::Record::dbdef->table($layer) )
                       ? grep { $_ ne 'svcnum' } fields($layer)
index 67aacfd..5165945 100755 (executable)
@@ -22,6 +22,7 @@ if ( $error ) {
   print $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string );
 } else {
 
+  #false laziness w/ edit/process/part_svc.cgi
   foreach my $part_pkg (qsearch('part_pkg',{})) {
     my($pkgpart)=$part_pkg->getfield('pkgpart');
 
index 34eb699..6b4d007 100644 (file)
@@ -5,7 +5,7 @@ my $exportnum = $cgi->param('exportnum');
 my $old = qsearchs('part_export', { 'exportnum'=>$exportnum } ) if $exportnum;
 
 #fixup options
-warn join('-', split(',',$cgi->param('options')));
+#warn join('-', split(',',$cgi->param('options')));
 my %options = map { $_=>$cgi->param($_) } split(',',$cgi->param('options'));
 
 my $new = new FS::part_export ( {
@@ -16,9 +16,9 @@ my $new = new FS::part_export ( {
 
 my $error;
 if ( $exportnum ) {
-  warn $old;
-  warn $exportnum;
-  warn $new->machine;
+  #warn $old;
+  #warn $exportnum;
+  #warn $new->machine;
   $error = $new->replace($old,\%options);
 } else {
   $error = $new->insert(\%options);
index 31ab134..859670b 100755 (executable)
@@ -33,6 +33,29 @@ if ( $error ) {
   $cgi->param('error', $error);
   print $cgi->redirect(popurl(2). "part_svc.cgi?". $cgi->query_string );
 } else {
+
+  #false laziness w/ edit/process/agent_type.cgi
+  foreach my $part_export (qsearch('part_export',{})) {
+    my $exportnum = $part_export->exportnum;
+    my $export_svc = qsearchs('export_svc', {
+      'exportnum' => $part_export->exportnum,
+      'svcpart'   => $new->svcpart,
+    } );
+    if ( $export_svc && ! $cgi->param("exportnum". $part_export->exportnum) ) {
+      $error = $export_svc->delete;
+      die $error if $error;
+    } elsif ( $cgi->param("exportnum". $part_export->exportnum)
+              && ! $export_svc ) {
+      $export_svc = new FS::export_svc ( {
+        'exportnum' => $part_export->exportnum,
+        'svcpart'   => $new->svcpart,
+      } );
+      $error = $export_svc->insert;
+      die $error if $error;
+    }
+
+  }
+
   print $cgi->redirect(popurl(3)."browse/part_svc.cgi");
 }
 
index 5088fef..7016c91 100755 (executable)
@@ -43,4 +43,18 @@ canceled service with you.  For that, cancel all of the customer's packages.
 </form></body></html>
 END
 
+#Deleting a customer you have financial records on (i.e. credits) is
+#typically considered fraudulant bookkeeping.  Remember, deleting   
+#customers should ONLY be used for completely bogus records.  You should
+#NOT delete real customers who simply discontinue service.
+#
+#For real customers who simply discontinue service, cancel all of the
+#customer's packages.  Customers with all cancelled packages are not  
+#billed.  There is no need to take further action to prevent billing on
+#customers with all cancelled packages.
+#
+#Also see the "hidecancelledcustomers" and "hidecancelledpackages"
+#configuration options, which will allow you to surpress the display of
+#cancelled customers and packages, respectively.
+
 %>