+=head1 SUBROUTINES
+
+=over 4
+
+=item process
+
+Job-queue processor for web interface adds/edits
+
+=cut
+
+use Storable qw(thaw);
+use Data::Dumper;
+use MIME::Base64;
+sub process {
+ my $job = shift;
+
+ my $param = thaw(decode_base64(shift));
+ warn Dumper($param) if $DEBUG;
+
+ my $old = qsearchs('part_svc', { 'svcpart' => $param->{'svcpart'} })
+ if $param->{'svcpart'};
+
+ $param->{'svc_acct__usergroup'} =
+ ref($param->{'svc_acct__usergroup'})
+ ? join(',', @{$param->{'svc_acct__usergroup'}} )
+ : $param->{'svc_acct__usergroup'};
+
+ my $new = new FS::part_svc ( {
+ map {
+ $_ => $param->{$_};
+ # } qw(svcpart svc svcdb)
+ } ( fields('part_svc'),
+ map { my $svcdb = $_;
+ my @fields = fields($svcdb);
+ push @fields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
+
+ map {
+ if ( $param->{ $svcdb.'__'.$_.'_flag' } =~ /^[MA]$/ ) {
+ $param->{ $svcdb.'__'.$_ } =
+ delete( $param->{ $svcdb.'__'.$_.'_classnum' } );
+ }
+ if ( $param->{ $svcdb.'__'.$_.'_flag' } =~ /^S$/ ) {
+ $param->{ $svcdb.'__'.$_} =
+ ref($param->{ $svcdb.'__'.$_})
+ ? join(',', @{$param->{ $svcdb.'__'.$_ }} )
+ : $param->{ $svcdb.'__'.$_ };
+ }
+ ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' );
+ }
+ @fields;
+
+ } grep defined( dbdef->table($_) ),
+ qw( svc_acct svc_domain svc_forward svc_www svc_broadband
+ svc_phone svc_external
+ )
+ )
+ } );
+
+ my %exportnums =
+ map { $_->exportnum => ( $param->{'exportnum'.$_->exportnum} || '') }
+ qsearch('part_export', {} );
+
+ my $error;
+ if ( $param->{'svcpart'} ) {
+ $error = $new->replace( $old,
+ '1.3-COMPAT',
+ [ 'usergroup' ],
+ \%exportnums,
+ $job
+ );
+ } else {
+ $error = $new->insert( [ 'usergroup' ],
+ \%exportnums,
+ $job,
+ );
+ $param->{'svcpart'} = $new->getfield('svcpart');
+ }
+
+ die "$error\n" if $error;
+}
+
+=item process_bulk_cust_svc
+
+Job-queue processor for web interface bulk customer service changes
+
+=cut
+
+use Storable qw(thaw);
+use Data::Dumper;
+use MIME::Base64;
+sub process_bulk_cust_svc {
+ my $job = shift;