sub start_job {
my $self = shift;
- my %param = @_;
+ warn "FS::UI::Web::start_job: ". join(', ', @_) if $DEBUG;
+# my %param = @_;
+ my %param = ();
+ while ( @_ ) {
+ my( $field, $value ) = splice(@_, 0, 2);
+ unless ( exists( $param{$field} ) ) {
+ $param{$field} = $value;
+ } elsif ( ! ref($param{$field}) ) {
+ $param{$field} = [ $param{$field}, $value ];
+ } else {
+ push @{$param{$field}}, $value;
+ }
+ }
warn "FS::UI::Web::start_job\n".
- join('', map " $_ => $param{$_}\n", keys %param )
+ join('', map {
+ if ( ref($param{$_}) ) {
+ " $_ => [ ". join(', ', @{$param{$_}}). " ]\n";
+ } else {
+ " $_ => $param{$_}\n";
+ }
+ } keys %param )
if $DEBUG;
#first get the CGI params shipped off to a job ASAP so an id can be returned
sub table { 'export_svc'; }
-=item insert
+=item insert [ JOB, OFFSET, MULTIPLIER ]
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
+TODOC: JOB, OFFSET, MULTIPLIER
+
=cut
sub insert {
my $self = shift;
- my $error;
+ my( $job, $offset, $mult ) = ( '', 0, 100);
+ $job = shift if @_;
+ $offset = shift if @_;
+ $mult = shift if @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- $error = $self->check;
+ my $error = $self->check;
return $error if $error;
#check for duplicates!
warn "WARNING: No duplicate checking done on merge of $svcdb exports";
}
+ my $done = 0;
+ my $percheck = $mult / scalar(@checks);
foreach my $check ( @checks ) {
+
+ if ( $job ) {
+ $error = $job->update_statustext(int( $offset + ($done+.33) *$percheck ));
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
my @current_svc = $self->part_export->svc_x;
#warn "current: ". scalar(@current_svc). " $current_svc[0]\n";
+
+ if ( $job ) {
+ $error = $job->update_statustext(int( $offset + ($done+.67) *$percheck ));
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
my @new_svc = $self->part_svc->svc_x;
#warn "new: ". scalar(@new_svc). " $new_svc[0]\n";
+
+ if ( $job ) {
+ $error = $job->update_statustext(int( $offset + ($done+1) *$percheck ));
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
my $method = $check->{'method'};
my %cur_svc = map { $_->$method() => $_ } @current_svc;
my @dup_svc = grep { $cur_svc{$_->$method()} } @new_svc;
": ". join(', ', sort $sortby map { $_->$method() } @diff_customer_svc )
;
}
+
+ $done++;
}
#end of duplicate check, whew
package FS::part_svc;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $DEBUG );
use FS::Record qw( qsearch qsearchs fields dbh );
use FS::part_svc_column;
use FS::part_export;
@ISA = qw(FS::Record);
+$DEBUG = 1;
+
=head1 NAME
FS::part_svc - Object methods for part_svc objects
sub table { 'part_svc'; }
-=item insert [ EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ]
+=item insert [ EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF [ , JOB ] ] ]
Adds this service definition to the database. If there is an error, returns
the error, otherwise returns false.
If EXPORTNUMS_HASHREF is specified (keys are exportnums and values are
boolean), the appopriate export_svc records will be inserted.
+TODOC: JOB
+
=cut
sub insert {
my $exportnums = shift;
@exportnums = grep $exportnums->{$_}, keys %$exportnums;
}
+ my $job = '';
+ $job = shift if @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
}
# add export_svc records
-
+ my $slice = 100/scalar(@exportnums) if @exportnums;
+ my $done = 0;
foreach my $exportnum ( @exportnums ) {
my $export_svc = new FS::export_svc ( {
'exportnum' => $exportnum,
'svcpart' => $self->svcpart,
} );
- $error = $export_svc->insert;
+ $error = $export_svc->insert($job, $slice*$done++, $slice);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
# check & make sure the svcpart isn't in cust_svc or pkg_svc (in any packages)?
}
-=item replace OLD_RECORD [ '1.3-COMPAT' [ , EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ] ]
+=item replace OLD_RECORD [ '1.3-COMPAT' [ , EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF [ , JOB ] ] ] ]
Replaces OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
TODOC: EXTRA_FIELDS_ARRAYREF (same as insert method)
+TODOC: JOB
+
=cut
sub replace {
my ( $new, $old ) = ( shift, shift );
+ my $compat = '';
+ my @fields = ();
+ my $exportnums;
+ my $job = '';
+ if ( @_ && $_[0] eq '1.3-COMPAT' ) {
+ shift;
+ $compat = '1.3';
+ @fields = @{shift(@_)} if @_;
+ $exportnums = @_ ? shift : '';
+ $job = shift if @_;
+ } else {
+ return 'non-1.3-COMPAT interface not yet written';
+ #not yet implemented
+ }
return "Can't change svcdb for an existing service definition!"
unless $old->svcdb eq $new->svcdb;
return $error;
}
- if ( @_ && $_[0] eq '1.3-COMPAT' ) {
- shift;
- my @fields = ();
- @fields = @{shift(@_)} if @_;
- my $exportnums = @_ ? shift : '';
+ if ( $compat eq '1.3' ) {
# maintain part_svc_column records
if ( $exportnums ) {
#false laziness w/ edit/process/agent_type.cgi
+ my @new_export_svc = ();
foreach my $part_export ( qsearch('part_export', {}) ) {
my $exportnum = $part_export->exportnum;
my $hashref = {
return $error;
}
} elsif ( ! $export_svc && $exportnums->{$exportnum} ) {
- $export_svc = new FS::export_svc ( $hashref );
- $error = $export_svc->insert;
+ push @new_export_svc, new FS::export_svc ( $hashref );
+ }
+
+ }
+
+ my $slice = 100/scalar(@new_export_svc) if @new_export_svc;
+ my $done = 0;
+ foreach my $export_svc (@new_export_svc) {
+ $error = $export_svc->insert($job, $slice*$done++, $slice);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ if ( $job ) {
+ $error = $job->update_statustext( int( $slice * $done ) );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
}
-
}
}
=back
+=head1 SUBROUTINES
+
+=over 4
+
+=item process
+
+Experimental 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'}} )
+ : '';
+
+ 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 { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ) } @fields;
+ } grep defined( $FS::Record::dbdef->table($_) ),
+ qw( svc_acct svc_domain svc_forward svc_www svc_broadband )
+ )
+ } );
+
+ 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 if $error;
+}
+
=head1 BUGS
Delete is unimplemented.
use strict;
use vars qw( @ISA $DEBUG );
-use Storable qw(thaw);
-use Data::Dumper;
use FS::Record qw( qsearch qsearchs dbh fields );
use FS::rate_detail;
=cut
+use Storable qw(thaw);
+use Data::Dumper;
use MIME::Base64;
sub process {
my $job = shift;
END
foreach my $group ( @all_groups ) {
- $html .= '<OPTION';
+ $html .= qq(<OPTION VALUE="$group");
if ( $sel_groups{$group} ) {
$html .= ' SELECTED';
$sel_groups{$group} = 0;
$html .= ">$group</OPTION>\n";
}
foreach my $group ( grep { $sel_groups{$_} } keys %sel_groups ) {
- $html .= "<OPTION SELECTED>$group</OPTION>\n";
+ $html .= qq(<OPTION VALUE="$group" SELECTED>$group</OPTION>\n);
};
$html .= '</SELECT>';
<%
my $part_svc;
my $clone = '';
-my $error = '';
-if ( $cgi->param('magic') eq 'process' ) {
-
- my $svcpart = $cgi->param('svcpart');
- my $old = qsearchs('part_svc', { 'svcpart' => $svcpart }) if $svcpart;
-
- $cgi->param( 'svc_acct__usergroup',
- join(',', $cgi->param('svc_acct__usergroup') ) );
-
- my $new = new FS::part_svc ( {
- map {
- $_, scalar($cgi->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 { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ) } @fields;
- } grep defined( $FS::Record::dbdef->table($_) ),
- qw( svc_acct svc_domain svc_forward svc_www svc_broadband )
- )
- } );
-
- my %exportnums =
- map { $_->exportnum => ( $cgi->param('exportnum'.$_->exportnum) || '') }
- qsearch('part_export', {} );
-
- if ( $svcpart ) {
- $error = $new->replace($old, '1.3-COMPAT', [ 'usergroup' ], \%exportnums );
- } else {
- $error = $new->insert( [ 'usergroup' ], \%exportnums );
- $svcpart = $new->getfield('svcpart');
- }
-
- unless ( $error ) { #no error, redirect
- #print $cgi->redirect(popurl(3)."browse/part_svc.cgi");
- print $cgi->redirect("${p}browse/part_svc.cgi");
- myexit;
- }
-
- $part_svc = $new; #??
- #$part_svc = new FS::part_svc ( {
- # map { $_, scalar($cgi->param($_)) } fields('part_svc')
- #} );
-
-} elsif ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {#clone
+if ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {#clone
#$cgi->param('clone') =~ /^(\d+)$/ or die "malformed query: $query";
$part_svc = qsearchs('part_svc', { 'svcpart'=>$1 } )
or die "unknown svcpart: $1";
)
%>
-<% if ( $error ) { %>
-<FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT>
-<% } %>
-
<FORM NAME="dummy">
Service Part #<%= $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>
<BR><BR>
Service <INPUT TYPE="text" NAME="svc" VALUE="<%= $hashref->{svc} %>"><BR>
Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<%= $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR>
-<INPUT TYPE="hidden" NAME="magic" VALUE="process">
<INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $hashref->{svcpart} %>">
<BR>
Services are items you offer to your customers.
'form_name' => 'dummy',
#'form_action' => 'process/part_svc.cgi',
'form_action' => 'part_svc.cgi', #self
- 'form_text' => [ qw( magic svc svcpart ) ],
+ 'form_text' => [ qw( svc svcpart ) ],
'form_checkbox' => [ 'disabled' ],
'layer_callback' => sub {
my $layer = shift;
+
my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!;
my $columns = 3;
$part_svc->svcpart($clone) if $clone; #haha, undone below
foreach my $field (@fields) {
my $part_svc_column = $part_svc->part_svc_column($field);
- my $value = $error
- ? $cgi->param("${layer}__${field}")
- : $part_svc_column->columnvalue;
- my $flag = $error
- ? $cgi->param("${layer}__${field}_flag")
- : $part_svc_column->columnflag;
+ my $value = $part_svc_column->columnvalue;
+ my $flag = $part_svc_column->columnflag;
my $def = $defs{$layer}{$field};
my $desc = ref($def) ? $def->{desc} : $def;
$part_svc->svcpart('') if $clone; #undone
$html .= "</TABLE>";
- $html .= '<BR><INPUT TYPE="submit" VALUE="'.
- ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '">';
+ $html .= include('/elements/progress-init.html',
+ $layer, #form name
+ [ qw(svc svcpart disabled exportnum), @fields ],
+ 'process/part_svc.cgi',
+ $p.'browse/part_svc.cgi',
+ $layer,
+ );
+ $html .= '<BR><INPUT NAME="submit" TYPE="button" VALUE="'.
+ ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '" '.
+ ' onClick="document.'. "$layer.submit.disabled=true; ".
+ "fixup(document.$layer); $layer". 'process();">';
+
+ #$html .= '<BR><INPUT TYPE="submit" VALUE="'.
+ # ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '">';
$html;
--- /dev/null
+<%
+my $server = new FS::UI::Web::JSRPC 'FS::part_svc::process';
+$server->process;
+%>
-<% my( $formname, $fields, $action, $success_url ) = @_; %>
+<%
+ my( $formname, $fields, $action, $success_url, $key ) = @_;
+ $key = '' unless defined $key;
+%>
<SCRIPT TYPE="text/javascript" SRC="../elements/jsrsClient.js"></SCRIPT>
<SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws.js"></SCRIPT>
<SCRIPT TYPE="text/javascript">
function OLiframeContent(src, width, height, name) {
return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"'
- +(name?' name="'+name+'" id="'+name+'"':'')+' scrolling="no">'
+ +(name?' name="'+name+'" id="'+name+'"':'')+' scrolling="auto">'
+'<div>[iframe not supported]</div></iframe>');
}
-function process () {
+function <%=$key%>process () {
- document.OneTrueForm.submit.disabled=true;
+ document.<%=$formname%>.submit.disabled=true;
- overlib( 'Submitting job to server...', WIDTH, 420, HEIGHT, 128, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
+ overlib( 'Submitting job to server...', WIDTH, 432, HEIGHT, 136, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
var Hash = new Array();
var x = 0;
var fieldName;
- for (var i = 0; i<document.OneTrueForm.elements.length; i++) {
- fieldName = document.OneTrueForm.elements[i].name;
-// (fieldName.indexOf('rate') > -1)
-// || (fieldName.indexOf('min_') > -1)
-// || (fieldName.indexOf('sec_') > -1)
- if ( <%= join(' || ', map { "(fieldName.indexOf('$_') > -1)" } @$fields ) %>
+ for (var i = 0; i<document.<%=$formname%>.elements.length; i++) {
+ field = document.<%=$formname%>.elements[i];
+ if ( <%= join(' || ', map { "(field.name.indexOf('$_') > -1)" } @$fields ) %>
)
{
- Hash[x++] = fieldName;
- Hash[x++] = document.OneTrueForm.elements[i].value;
+ if ( field.type == 'select-multiple' ) {
+ for (var j=0; j < field.options.length; j++) {
+ if ( field.options[j].selected ) {
+ Hash[x++] = field.name;
+ Hash[x++] = field.options[j].value;
+ }
+ }
+ } else if ( ( field.type != 'radio' && field.type != 'checkbox' )
+ || ( ( field.type == 'radio' || field.type == 'checkbox' )
+ && document.<%=$formname%>.elements[i].checked
+ )
+ )
+ {
+ Hash[x++] = field.name;
+ Hash[x++] = field.value;
+ }
}
}
jsrsPOST = true;
- jsrsExecute( '<%= $action %>', myCallback, 'start_job', Hash );
+ jsrsExecute( '<%= $action %>', <%=$key%>myCallback, 'start_job', Hash );
}
-function myCallback( jobnum ) {
+function <%=$key%>myCallback( jobnum ) {
- overlib( OLiframeContent('<%=$p%>elements/progress-popup.html?jobnum=' + jobnum + ';url=<%=$success_url%>' , 420, 128, 'progress_popup'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
+ overlib( OLiframeContent('<%=$p%>elements/progress-popup.html?jobnum=' + jobnum + ';url=<%=$success_url%>;formname=<%=$formname%>' , 432, 136, 'progress_popup'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 );
}
<%
- my( $jobnum ) = $cgi->param('jobnum');
- my( $url ) = $cgi->param('url');
+ my $jobnum = $cgi->param('jobnum');
+ my $url = $cgi->param('url');
+ my $formname = scalar($cgi->param('formname'));
%>
<HTML>
<HEAD>
document.getElementById("progress_bar").innerHTML = '';
document.getElementById("progress_percent").innerHTML = '<INPUT TYPE="button" VALUE="OK" onClick="parent.nd(1);">';
document.getElementById("progress_jobnum").innerHTML = '';
- parent.document.OneTrueForm.submit.disabled=false;
+ parent.document.<%=$formname%>.submit.disabled=false;
} else {
alert('XXX unknown status returned from server: ' + status);
}