From 947c955be56140c4a10b16345c1b15c44b02070a Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 29 Jun 2006 13:47:44 +0000 Subject: [PATCH] finish at least the automatic provisioning part --- FS/FS/inventory_class.pm | 2 +- FS/FS/svc_Common.pm | 206 ++++++++++++++++++++++++++++++--- httemplate/browse/inventory_class.html | 2 +- httemplate/edit/part_svc.cgi | 7 +- httemplate/edit/svc_acct.cgi | 21 +--- httemplate/edit/svc_broadband.cgi | 9 +- httemplate/edit/svc_domain.cgi | 9 +- httemplate/edit/svc_external.cgi | 9 +- httemplate/edit/svc_forward.cgi | 9 +- httemplate/edit/svc_www.cgi | 9 +- httemplate/search/inventory_item.html | 62 +++++++++- 11 files changed, 268 insertions(+), 77 deletions(-) diff --git a/FS/FS/inventory_class.pm b/FS/FS/inventory_class.pm index 04ee207d3..508889bca 100644 --- a/FS/FS/inventory_class.pm +++ b/FS/FS/inventory_class.pm @@ -120,7 +120,7 @@ sub num_avail { sub num_sql { my( $self, $sql ) = @_; - my $sql = "AND $sql" if length($sql); + $sql = "AND $sql" if length($sql); my $statement = "SELECT COUNT(*) FROM inventory_item WHERE classnum = ? $sql"; my $sth = dbh->prepare($statement) or die dbh->errstr. " preparing $statement"; diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index 962e36a07..f2e1b9adb 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -9,10 +9,12 @@ use FS::cust_svc; use FS::part_svc; use FS::queue; use FS::cust_main; +use FS::inventory_item; +use FS::inventory_class; @ISA = qw( FS::cust_main_Mixin FS::Record ); -$DEBUG = 0; +$DEBUG = 1; =head1 NAME @@ -202,6 +204,12 @@ sub insert { $self->svcpart($cust_svc->svcpart); } + $error = $self->set_auto_inventory; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + $error = $self->SUPER::insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; @@ -297,7 +305,7 @@ sub delete { #new-style exports! unless ( $noexport_hack ) { foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { - my $error = $part_export->export_delete($self); + $error = $part_export->export_delete($self); if ( $error ) { $dbh->rollback if $oldAutoCommit; return "exporting to ". $part_export->exporttype. @@ -306,11 +314,18 @@ sub delete { } } - return $error if $error; + $error = $self->return_inventory; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error returning inventory: $error"; + } my $cust_svc = $self->cust_svc; $error = $cust_svc->delete; - return $error if $error; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -338,7 +353,13 @@ sub replace { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - my $error = $new->SUPER::replace($old); + my $error = $new->set_auto_inventory; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $error = $new->SUPER::replace($old); if ($error) { $dbh->rollback if $oldAutoCommit; return $error; @@ -409,7 +430,7 @@ to test the return). Usually called by the check method. sub setfixed { my $self = shift; - $self->setx('F'); + $self->setx('F', @_); } =item setdefault @@ -422,20 +443,68 @@ the FS::part_svc object (use ref() to test the return). sub setdefault { my $self = shift; - $self->setx('D'); + $self->setx('D', @_ ); +} + +=item set_default_and_fixed + +=cut + +sub set_default_and_fixed { + my $self = shift; + $self->setx( [ 'D', 'F' ], @_ ); } +=item setx FLAG | FLAG_ARRAYREF , [ CALLBACK_HASHREF ] + +Sets fields according to the passed in flag or arrayref of flags. + +Optionally, a hashref of field names and callback coderefs can be passed. +If a coderef exists for a given field name, instead of setting the field, +the coderef is called with the column value (part_svc_column.columnvalue) +as the single parameter. + +=cut + sub setx { my $self = shift; my $x = shift; + my @x = ref($x) ? @$x : ($x); + my %coderef = @_ ? shift : {}; - my $error; - - $error = + my $error = $self->ut_numbern('svcnum') ; return $error if $error; + my $part_svc = $self->part_svc; + return "Unkonwn svcpart" unless $part_svc; + + #set default/fixed/whatever fields from part_svc + + foreach my $part_svc_column ( + grep { my $f = $_->columnflag; grep { $f eq $_ } @x } #columnflag in @x + $part_svc->all_part_svc_column + ) { + + my $columnname = $part_svc_column->columnname; + my $columnvalue = $part_svc_column->columnvalue; + + if ( exists( $coderef{columnname} ) ) { + &{ $coderef{$columnname} }( $self, $columnvalue); + } else { + $self->setfield( $columnname, $columnvalue ); + } + + } + + $part_svc; + +} + +sub part_svc { + my $self = shift; + #get part_svc my $svcpart; if ( $self->get('svcpart') ) { @@ -445,20 +514,129 @@ sub setx { return "Unknown svcnum" unless $cust_svc; $svcpart = $cust_svc->svcpart; } - my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } ); + + qsearchs( 'part_svc', { 'svcpart' => $svcpart } ); + +} + +=item set_auto_inventory + +Sets any fields which auto-populate from inventory (see L). +If there is an error, returns the error, otherwise returns false. + +=cut + +sub set_auto_inventory { + my $self = shift; + + my $error = + $self->ut_numbern('svcnum') + ; + return $error if $error; + + my $part_svc = $self->part_svc; return "Unkonwn svcpart" unless $part_svc; + 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; + #set default/fixed/whatever fields from part_svc my $table = $self->table; foreach my $field ( grep { $_ ne 'svcnum' } $self->fields ) { my $part_svc_column = $part_svc->part_svc_column($field); - if ( $part_svc_column->columnflag eq $x ) { - $self->setfield( $field, $part_svc_column->columnvalue ); + if ( $part_svc_column->columnflag eq 'A' && $self->$field() eq '' ) { + + my $classnum = $part_svc_column->columnvalue; + my $inventory_item = qsearchs({ + 'table' => 'inventory_item', + 'hashref' => { 'classnum' => $classnum, + 'svcnum' => '', + }, + 'extra_sql' => 'LIMIT 1 FOR UPDATE', + }); + + unless ( $inventory_item ) { + $dbh->rollback if $oldAutoCommit; + my $inventory_class = + qsearchs('inventory_class', { 'classnum' => $classnum } ); + return "Can't find inventory_class.classnum $classnum" + unless $inventory_class; + return "Out of ". $inventory_class->classname. "s\n"; #Lingua:: BS + #for pluralizing + } + + $inventory_item->svcnum( $self->svcnum ); + my $ierror = $inventory_item->replace(); + if ( $ierror ) { + $dbh->rollback if $oldAutoCommit; + return "Error provisioning inventory: $ierror"; + + } + + $self->setfield( $field, $inventory_item->item ); + } } - $part_svc; + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; + +} + +=item return_inventory + +=cut + +sub return_inventory { + my $self = shift; + 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; + + foreach my $inventory_item ( $self->inventory_item ) { + $inventory_item->svcnum(''); + my $error = $inventory_item->replace(); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "Error returning inventory: $error"; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; +} + +=item inventory_item + +Returns the inventory items associated with this svc_ record, as +FS::inventory_item objects (see L. + +=cut + +sub inventory_item { + my $self = shift; + qsearch({ + 'table' => 'inventory_item', + 'hashref' => { 'svcnum' => $self->svcnum, }, + }); } =item cust_svc diff --git a/httemplate/browse/inventory_class.html b/httemplate/browse/inventory_class.html index 6da3c9e3c..4a15bf7d4 100644 --- a/httemplate/browse/inventory_class.html +++ b/httemplate/browse/inventory_class.html @@ -8,7 +8,7 @@ tie my %labels, 'Tie::IxHash', my %link = ( 'num_avail' => ';avail=1', - 'num_used' => ';avail=1', + 'num_used' => ';used=1', 'num_total' => '', ); diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index 77011e9dd..0298a5461 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -179,9 +179,10 @@ my %defs = ( 'condition' => sub { ref($_[0]) && $_[0]->{disable_fixed} }, }, - 'M' => { 'desc' => 'Manual selection from inventory', - 'condition' => $inv_sub, - }, +# need to template-ize httemplate/edit/svc_* first +# 'M' => { 'desc' => 'Manual selection from inventory', +# 'condition' => $inv_sub, +# }, 'A' => { 'desc' => 'Automatically fill in from inventory', 'condition' => $inv_sub, }, diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index 1e87c67ad..4b324a501 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -68,18 +68,9 @@ unless ( $svcnum || $cgi->param('error') ) { #adding } } - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - if ( $part_svc_column->columnname eq 'usergroup' ) { - @groups = split(',', $part_svc_column->columnvalue); - } else { - $svc_acct->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } - } + $svc_acct->set_default_and_fixed( { + 'usergroup' => sub { @groups = split(',', shift ); }, + } ); } @@ -274,7 +265,7 @@ if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) { <% foreach my $xid (qw( uid gid )) { %> <% - if ( $part_svc->part_svc_column($xid)->columnflag eq 'F' + if ( $part_svc->part_svc_column($xid)->columnflag =~ /^[FA]$/ || ! $conf->exists("svc_acct-edit_$xid") ) { %> @@ -376,7 +367,7 @@ if ( $part_svc->part_svc_column('shell')->columnflag eq 'F' <% } %> -<% if ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) { %> +<% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { %> @@ -396,7 +387,7 @@ foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) { my $a = $2; %> - <% if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { %> + <% if ( $part_svc->part_svc_column($r)->columnflag =~ /^[FA]$/ ) { %> diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi index cbd0c2c3a..d66cff690 100644 --- a/httemplate/edit/svc_broadband.cgi +++ b/httemplate/edit/svc_broadband.cgi @@ -47,14 +47,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_broadband->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_broadband->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi index f47ba0a8f..1156bf0ba 100755 --- a/httemplate/edit/svc_domain.cgi +++ b/httemplate/edit/svc_domain.cgi @@ -44,14 +44,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_domain->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_domain->set_default_and_fixed; } diff --git a/httemplate/edit/svc_external.cgi b/httemplate/edit/svc_external.cgi index bcfc85e3f..38b3ce1a4 100644 --- a/httemplate/edit/svc_external.cgi +++ b/httemplate/edit/svc_external.cgi @@ -40,14 +40,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_external->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_external->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_forward.cgi b/httemplate/edit/svc_forward.cgi index c1b90a9bd..c32fbd7c1 100755 --- a/httemplate/edit/svc_forward.cgi +++ b/httemplate/edit/svc_forward.cgi @@ -44,14 +44,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_forward->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_forward->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_www.cgi b/httemplate/edit/svc_www.cgi index 3cb752850..280346bb4 100644 --- a/httemplate/edit/svc_www.cgi +++ b/httemplate/edit/svc_www.cgi @@ -42,14 +42,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_www->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_www->set_default_and_fixed; } } diff --git a/httemplate/search/inventory_item.html b/httemplate/search/inventory_item.html index bd74f5619..7049c8841 100644 --- a/httemplate/search/inventory_item.html +++ b/httemplate/search/inventory_item.html @@ -24,7 +24,30 @@ if ( $cgi->param('avail') ) { my $count_query = "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql"; +my $link = sub { + my $inventory_item = shift; + if ( $inventory_item->svcnum ) { + [ "${p}view/svc_acct.cgi?", 'svcnum' ]; + } else { + ''; + } +}; +my $link_cust = sub { + my $inventory_item = shift; + if ( $inventory_item->custnum ) { + [ "${p}view/cust_main.cgi?", 'custnum' ]; + } else { + ''; + } +}; + +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + %><%= include( 'elements/search.html', + 'title' => $title, #less lame to use Lingua:: something to pluralize @@ -33,19 +56,52 @@ my $count_query = 'query' => { 'table' => 'inventory_item', 'hashref' => { 'classnum' => $classnum }, + 'select' => join(', ', + 'inventory_item.*', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), + ), 'extra_sql' => $extra_sql, + 'addl_from' => $addl_from, }, 'count_query' => $count_query, - # XXX proper full service/customer link ala svc_acct - 'header' => [ '#', $inventory_class->classname, 'svcnum' ], + 'header' => [ + '#', + $inventory_class->classname, + 'Service', + FS::UI::Web::cust_header(), + ], 'fields' => [ 'itemnum', 'item', - 'svcnum', #XXX proper full service customer link ala svc_acct + #'svcnum', #XXX proper full service customer link ala svc_acct # "unallocated" ? "available" ? + sub { + #this could be way more efficient with a mixin + # like cust_main_Mixin that let us all all the methods + # on data we already have... + my $inventory_item = shift; + my $cust_svc = $inventory_item->cust_svc; + if ( $cust_svc ) { + my($label, $value) = $cust_svc->label; + "$label: $value"; + } else { + '(available)'; + } + }, + + \&FS::UI::Web::cust_fields, + + ], + + 'links' => [ + '', + '', + $link, + ( map { $link_cust } FS::UI::Web::cust_header() ), ], ) -- 2.11.0