From: Mark Wells Date: Wed, 17 Apr 2013 04:12:17 +0000 (-0700) Subject: for exports with per-service machine selection, make sure there is always a machine... X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=90d53f2bfaac6b65afb211e81c1f9aa160da9e1c for exports with per-service machine selection, make sure there is always a machine selected, #17194, #22524 --- diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index bbf3b42fe..9f68a41de 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -2729,9 +2729,10 @@ sub tables_hashref { 'columns' => [ 'exportnum', 'serial', '', '', '', '', 'exportname', 'varchar', 'NULL', $char_d, '', '', - 'machine', 'varchar', 'NULL', $char_d, '', '', + 'machine', 'varchar', 'NULL', $char_d, '', '', 'exporttype', 'varchar', '', $char_d, '', '', 'nodomain', 'char', 'NULL', 1, '', '', + 'default_machine','int', 'NULL', '', '', '', ], 'primary_key' => 'exportnum', 'unique' => [], diff --git a/FS/FS/export_svc.pm b/FS/FS/export_svc.pm index 0370f5f0b..b08f8f7c3 100644 --- a/FS/FS/export_svc.pm +++ b/FS/FS/export_svc.pm @@ -5,6 +5,7 @@ use vars qw( @ISA ); use FS::Record qw( qsearch qsearchs dbh ); use FS::part_export; use FS::part_svc; +use FS::svc_export_machine; @ISA = qw(FS::Record); @@ -209,6 +210,19 @@ sub insert { } #end of duplicate check, whew $error = $self->SUPER::insert; + + my $part_export = $self->part_export; + if ( !$error and $part_export->default_machine ) { + foreach my $cust_svc ( $self->part_svc->cust_svc ) { + my $svc_export_machine = FS::svc_export_machine->new({ + 'exportnum' => $self->exportnum, + 'svcnum' => $cust_svc->svcnum, + 'machinenum' => $part_export->default_machine, + }); + $error ||= $svc_export_machine->insert; + } + } + if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -251,7 +265,23 @@ Delete this record from the database. =cut -# the delete method can be inherited from FS::Record +sub delete { + my $self = shift; + my $dbh = dbh; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + + my $error = $self->SUPER::delete; + foreach ($self->svc_export_machine) { + $error ||= $_->delete; + } + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + $dbh->commit or die $dbh->errstr if $oldAutoCommit; +} + =item replace OLD_RECORD @@ -307,6 +337,24 @@ sub part_svc { qsearchs( 'part_svc', { 'svcpart' => $self->svcpart } ); } +=item svc_export_machine + +Returns all export hostname records (L) for this +combination of svcpart and exportnum. + +=cut + +sub svc_export_machine { + my $self = shift; + qsearch({ + 'table' => 'svc_export_machine', + 'select' => 'svc_export_machine.*', + 'addl_from' => 'JOIN cust_svc USING (svcnum)', + 'hashref' => { 'exportnum' => $self->exportnum }, + 'extra_sql' => ' AND cust_svc.svcpart = '.$self->svcpart, + }); +} + =back =head1 BUGS diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 15ce9c059..28cb1419d 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -125,31 +125,14 @@ sub insert { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - my $error = $self->SUPER::insert(@_); + my $error = $self->SUPER::insert(@_) + || $self->replace; + # use replace to do all the part_export_machine and default_machine stuff if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; } - #kinda false laziness with process_m2name - my @machines = map { $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ } - grep /\S/, - split /[\n\r]{1,2}/, - $self->part_export_machine_textarea; - - foreach my $machine ( @machines ) { - - my $part_export_machine = new FS::part_export_machine { - 'exportnum' => $self->exportnum, - 'machine' => $machine, - }; - $error = $part_export_machine->insert; - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } @@ -217,6 +200,7 @@ or modified. sub replace { my $self = shift; + my $old = $self->replace_old; local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; @@ -228,12 +212,7 @@ sub replace { my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; - - my $error = $self->SUPER::replace(@_); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } + my $error; if ( $self->part_export_machine_textarea ) { @@ -258,6 +237,10 @@ sub replace { } } + if ( $self->default_machine_name eq $machine ) { + $self->default_machine( $part_export_machine{$machine}->machinenum ); + } + delete $part_export_machine{$machine}; #so we don't disable it below } else { @@ -272,11 +255,13 @@ sub replace { return $error; } + if ( $self->default_machine_name eq $machine ) { + $self->default_machine( $part_export_machine->machinenum ); + } } } - foreach my $part_export_machine ( values %part_export_machine ) { $part_export_machine->disabled('Y'); $error = $part_export_machine->replace; @@ -286,6 +271,48 @@ sub replace { } } + if ( $old->machine ne '_SVC_MACHINE' ) { + # then set up the default for any already-attached export_svcs + foreach my $export_svc ( $self->export_svc ) { + my @svcs = qsearch('cust_svc', { 'svcpart' => $export_svc->svcpart }); + foreach my $cust_svc ( @svcs ) { + my $svc_export_machine = FS::svc_export_machine->new({ + 'exportnum' => $self->exportnum, + 'svcnum' => $cust_svc->svcnum, + 'machinenum' => $self->default_machine, + }); + $error ||= $svc_export_machine->insert; + } + } + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } # if switching to selectable hosts + + } elsif ( $old->machine eq '_SVC_MACHINE' ) { + # then we're switching from selectable to non-selectable + foreach my $svc_export_machine ( + qsearch('svc_export_machine', { 'exportnum' => $self->exportnum }) + ) { + $error ||= $svc_export_machine->delete; + } + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + } + + $error = $self->SUPER::replace(@_); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + if ( $self->machine eq '_SVC_MACHINE' and ! $self->default_machine ) { + $dbh->rollback if $oldAutoCommit; + return "no default export host selected"; } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -308,6 +335,13 @@ sub check { || $self->ut_domainn('machine') || $self->ut_alpha('exporttype') ; + + if ( $self->machine eq '_SVC_MACHINE' ) { + $error ||= $self->ut_numbern('default_machine') + } else { + $self->set('default_machine', ''); + } + return $error if $error; $self->nodomain =~ /^(Y?)$/ or return "Illegal nodomain: ". $self->nodomain; @@ -471,7 +505,9 @@ sub _rebless { $self; } -=item svc_machine +=item svc_machine SVC_X + +Return the export hostname for SVC_X. =cut @@ -483,14 +519,33 @@ sub svc_machine { my $svc_export_machine = qsearchs('svc_export_machine', { 'svcnum' => $svc_x->svcnum, 'exportnum' => $self->exportnum, - }) - #would only happen if you add this export to existing services without a - #machine set then try to run exports without setting it... right? - or die "No hostname selected for ".($self->exportname || $self->exporttype); + }); + + if (!$svc_export_machine) { + warn "No hostname selected for ".($self->exportname || $self->exporttype); + return $self->default_export_machine->machine; + } return $svc_export_machine->part_export_machine->machine; } +=item default_export_machine + +Return the default export hostname for this export. + +=cut + +sub default_export_machine { + my $self = shift; + my $machinenum = $self->default_machine; + if ( $machinenum ) { + my $default_machine = FS::part_export_machine->by_key($machinenum); + return $default_machine->machine if $default_machine; + } + # this should not happen + die "no default export hostname for export ".$self->exportnum; +} + #these should probably all go away, just let the subclasses define em =item export_insert SVC_OBJECT @@ -703,6 +758,55 @@ sub _upgrade_data { #class method $error = $opt->replace; die $error if $error; } + # for exports that have selectable hostnames, make sure all services + # have a hostname selected + foreach my $part_export ( + qsearch('part_export', { 'machine' => '_SVC_MACHINE' }) + ) { + + my $exportnum = $part_export->exportnum; + my $machinenum = $part_export->default_machine; + if (!$machinenum) { + my ($first) = $part_export->part_export_machine; + if (!$first) { + # user intervention really is required. + die "Export $exportnum has no hostname options defined.\n". + "You must correct this before upgrading.\n"; + } + # warn about this, because we might not choose the right one + warn "Export $exportnum (". $part_export->exporttype. + ") has no default hostname. Setting to ".$first->machine."\n"; + $machinenum = $first->machinenum; + $part_export->set('default_machine', $machinenum); + my $error = $part_export->replace; + die $error if $error; + } + + # the service belongs to a service def that uses this export + # and there is not a hostname selected for this export for that service + my $join = ' JOIN export_svc USING ( svcpart )'. + ' LEFT JOIN svc_export_machine'. + ' ON ( cust_svc.svcnum = svc_export_machine.svcnum'. + ' AND export_svc.exportnum = svc_export_machine.exportnum )'; + + my @svcs = qsearch( { + 'select' => 'cust_svc.*', + 'table' => 'cust_svc', + 'addl_from' => $join, + 'extra_sql' => ' WHERE svcexportmachinenum IS NULL'. + ' AND export_svc.exportnum = '.$part_export->exportnum, + } ); + foreach my $cust_svc (@svcs) { + my $svc_export_machine = FS::svc_export_machine->new({ + 'exportnum' => $exportnum, + 'machinenum' => $machinenum, + 'svcnum' => $cust_svc->svcnum, + }); + my $error = $svc_export_machine->insert; + die $error if $error; + } + } + # pass downstream my %exports_in_use; $exports_in_use{ref $_} = 1 foreach qsearch('part_export', {}); diff --git a/FS/FS/svc_export_machine.pm b/FS/FS/svc_export_machine.pm index 10f7b6821..7ca20ccb6 100644 --- a/FS/FS/svc_export_machine.pm +++ b/FS/FS/svc_export_machine.pm @@ -40,6 +40,10 @@ fields are currently supported: primary key +=item exportnum + +Export definition, see L + =item svcnum Customer service, see L diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi index 4dd253be8..2897cf39d 100644 --- a/httemplate/edit/part_export.cgi +++ b/httemplate/edit/part_export.cgi @@ -2,6 +2,34 @@ <% include('/elements/error.html') %> +
@@ -58,7 +86,6 @@ my $widget = new HTML::Widgets::SelectLayers( 'form_name' => 'dummy', 'form_action' => 'process/part_export.cgi', 'form_text' => [qw( exportnum exportname )], -# 'form_checkbox' => [qw()], 'html_between' => "\n", 'layer_callback' => sub { my $layer = shift; @@ -87,7 +114,8 @@ my $widget = new HTML::Widgets::SelectLayers( if ( $exports->{$layer}{svc_machine} ) { my( $N_CHK, $Y_CHK) = ( 'CHECKED', '' ); my( $machine_DISABLED, $pem_DISABLED) = ( '', 'DISABLED' ); - my $part_export_machine = ''; + my @part_export_machine; + my $default_machine = ''; if ( $cgi->param('svc_machine') eq 'Y' || $machine eq '_SVC_MACHINE' ) @@ -97,38 +125,43 @@ my $widget = new HTML::Widgets::SelectLayers( $machine_DISABLED = 'DISABLED'; $pem_DISABLED = ''; $machine = ''; - $part_export_machine = - $cgi->param('part_export_machine') - || join "\n", + @part_export_machine = $cgi->param('part_export_machine'); + if (!@part_export_machine) { + @part_export_machine = map $_->machine, grep ! $_->disabled, $part_export->part_export_machine; + } + $default_machine = + $cgi->param('default_machine_name') + || $part_export->default_export_machine; } - my $oc = qq(onChange="${layer}_svc_machine_changed(this)"); + my $oc = qq(onChange="svc_machine_changed(this, '$layer')"); $html .= qq[
- Selected in each customer service from these choices - - - +
+ Selected in each customer service from these choices: + +
+ Default: + ' } else { $html .= qq(). ''; diff --git a/httemplate/edit/process/part_export.cgi b/httemplate/edit/process/part_export.cgi index bcb9c0df1..e0c470675 100644 --- a/httemplate/edit/process/part_export.cgi +++ b/httemplate/edit/process/part_export.cgi @@ -56,6 +56,7 @@ my $new = new FS::part_export ( { if ( $cgi->param('svc_machine') eq 'Y' ) { $new->machine('_SVC_MACHINE'); $new->part_export_machine_textarea( $cgi->param('part_export_machine') ); + $new->default_machine_name( $cgi->param('default_machine_name') ); } my $error;