From 9608be1f5c73517fc348f1ab458892b34ed7facb Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 24 Jun 2006 16:41:45 +0000 Subject: [PATCH] Add the ability to link customer service definition fields to inventory classes, with an "automatic/manual" flag. Add the ability for the web interface to maintain these links. Start prettying up the service def. edit in preparation for Bigger Changes. --- FS/FS/part_svc.pm | 21 ++- FS/FS/part_svc_column.pm | 10 +- httemplate/browse/part_svc.cgi | 28 +++- httemplate/edit/part_svc.cgi | 271 ++++++++++++++++++++++++++-------- httemplate/elements/select-table.html | 16 +- httemplate/elements/table-grid.html | 8 +- 6 files changed, 273 insertions(+), 81 deletions(-) diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index 1a478a9cd..7f791947a 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -11,7 +11,7 @@ use FS::cust_svc; @ISA = qw(FS::Record); -$DEBUG = 0; +$DEBUG = 1; =head1 NAME @@ -79,7 +79,7 @@ the part_svc_column table appropriately (see L). =item I__I - Default or fixed value for I in I. -=item I__I_flag - defines I__I action: null, `D' for default, or `F' for fixed. For virtual fields, can also be 'X' for excluded. +=item I__I_flag - defines I__I action: null or empty (no default), `D' for default, `F' for fixed (unchangeable), `M' for manual selection from inventory, or `A' for automatic selection from inventory. For virtual fields, can also be 'X' for excluded. =back @@ -142,7 +142,8 @@ sub insert { } ); my $flag = $self->getfield($svcdb.'__'.$field.'_flag'); - if ( uc($flag) =~ /^([DFX])$/ ) { + #if ( uc($flag) =~ /^([DFMAX])$/ ) { + if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it $part_svc_column->setfield('columnflag', $1); $part_svc_column->setfield('columnvalue', $self->getfield($svcdb.'__'.$field) @@ -260,7 +261,8 @@ sub replace { } ); my $flag = $new->getfield($svcdb.'__'.$field.'_flag'); - if ( uc($flag) =~ /^([DFX])$/ ) { + #if ( uc($flag) =~ /^([DFMAX])$/ ) { + if ( uc($flag) =~ /^([A-Z])$/ ) { #part_svc_column will test it $part_svc_column->setfield('columnflag', $1); $part_svc_column->setfield('columnvalue', $new->getfield($svcdb.'__'.$field) @@ -536,7 +538,16 @@ sub process { map { my $svcdb = $_; my @fields = fields($svcdb); push @fields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge - map { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ) } @fields; + + map { + if ( $param->{ $svcdb.'__'.$_.'_flag' } =~ /^[MA]$/ ) { + $param->{ $svcdb.'__'.$_ } = + delete( $param->{ $svcdb.'__'.$_.'_classnum' } ); + } + ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ); + } + @fields; + } grep defined( dbdef->table($_) ), qw( svc_acct svc_domain svc_forward svc_www svc_broadband ) ) diff --git a/FS/FS/part_svc_column.pm b/FS/FS/part_svc_column.pm index 0450b35ef..fb08eaa0d 100644 --- a/FS/FS/part_svc_column.pm +++ b/FS/FS/part_svc_column.pm @@ -41,7 +41,7 @@ fields are currently supported: =item columnvalue - default or fixed value for the column -=item columnflag - null, D, F, X (virtual fields) +=item columnflag - null or empty (no default), `D' for default, `F' for fixed (unchangeable), `M' for manual selection from inventory, or `A' for automatic selection from inventory. For virtual fields, can also be 'X' for excluded. =back @@ -91,10 +91,16 @@ sub check { ; return $error if $error; - $self->columnflag =~ /^([DFX])$/ + $self->columnflag =~ /^([DFMAX])$/ or return "illegal columnflag ". $self->columnflag; $self->columnflag(uc($1)); + if ( $self->columnflag =~ /^[MA]$/ ) { + $error = + $self->ut_foreign_key( 'columnvalue', 'inventory_class', 'classnum' ); + return $error if $error; + } + $self->SUPER::check; } diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi index eef2676c0..805bd88b9 100755 --- a/httemplate/browse/part_svc.cgi +++ b/httemplate/browse/part_svc.cgi @@ -1,9 +1,15 @@ <% +#code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm my %flag = ( - 'D' => 'Default', - 'F' => 'Fixed', '' => '', + 'D' => 'Default', + 'F' => 'Fixed (unchangeable)', + #'M' => 'Manual selection from inventory', + 'M' => 'Manual selected from inventory', + #'A' => 'Automatically fill in from inventory', + 'A' => 'Automatically filled in from inventory', + 'X' => 'Excluded', ); my %search; @@ -27,6 +33,8 @@ if ( $cgi->param('orderby') eq 'active' ) { @part_svc = sort { lc($a->svc) cmp lc($b->svc) } @part_svc; } +my %inventory_class = (); + %> <%= include("/elements/header.html",'Service Definition Listing', menubar( 'Main Menu' => $p) ) %> @@ -125,7 +133,21 @@ map { qsearchs('part_export', { exportnum => $_->exportnum } ) } qsearch('export <%= $n1 %> <%= $field %> <%= $flag{$flag} %> - <%= $part_svc->part_svc_column($field)->columnvalue%> + + + <% my $value = $part_svc->part_svc_column($field)->columnvalue; + if ( $flag =~ /^[MA]$/ ) { + $inventory_class{$value} + ||= qsearchs('inventory_class', { 'classnum' => $value } ); + %> + <%= $inventory_class{$value} + ? $inventory_class{$value}->classname + : "WARNING: inventory_class.classnum $value not found" %> + <% } else { %> + <%= $value %> + <% } %> + + <% $n1=""; } diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index c5fff25e0..77011e9dd 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -38,28 +38,24 @@ Service
Disable new orders {disabled} eq 'Y' ? ' CHECKED' : '' %>>

-Services are items you offer to your customers. -
  • svc_acct - Shell accounts, POP mailboxes, SLIP/PPP and ISDN accounts +Service definitions are the templates for items you offer to your customers. +
    • svc_acct - Accounts - anything with a username (Mailboxes, PPP accounts, shell accounts, etc.)
    • svc_domain - Domains
    • svc_forward - mail forwarding
    • svc_www - Virtual domain website -
    • svc_broadband - Broadband/High-speed Internet service +
    • svc_broadband - Broadband/High-speed Internet service (always-on)
    • svc_external - Externally-tracked service
    For the selected table, you can give fields default or fixed (unchangable) -values. For example, a SLIP/PPP account may have a default (or perhaps fixed) -slipip of 0.0.0.0, while a POP mailbox will probably have a fixed -blank slipip as well as a fixed shell something like /bin/true or -/usr/bin/passwd. +values, or select an inventory class to manually or automatically fill in +that field.

    <% -my %vfields; - #these might belong somewhere else for other user interfaces #pry need to eventually create stuff that's shared amount UIs my $conf = new FS::Conf; @@ -77,28 +73,42 @@ my %defs = ( select_label => 'city', }, 'username' => { - desc => 'Username', - type => 'disabled', + desc => 'Username', + type => 'text', + disable_default => 1, + disable_fixed => 1, + }, + 'quota' => { + desc => '', + type => 'text', + disable_inventory => 1, }, - 'quota' => '', '_password' => 'Password', 'gid' => 'GID (when blank, defaults to UID)', 'shell' => { - desc =>'Shell (all service definitions should have a default or fixed shell that is present in the shells configuration file, set to blank for no shell tracking)', + #desc =>'Shell (all service definitions should have a default or fixed shell that is present in the shells configuration file, set to blank for no shell tracking)', + desc =>'Shell ( set to blank for no shell tracking)', type =>'select', select_list => [ $conf->config('shells') ], + disable_inventory => 1, }, - 'finger' => 'GECOS', + 'finger' => 'Real name (GECOS)', 'domsvc' => { desc =>'svcnum from svc_domain', type =>'select', select_table => 'svc_domain', select_key => 'svcnum', select_label => 'domain', + disable_inventory => 1, }, 'usergroup' => { desc =>'RADIUS groups', type =>'radius_usergroup_selector', + disable_inventory => 1, + }, + 'seconds' => { desc => '', + type => 'text', + disable_inventory => 1, }, }, 'svc_domain' => { @@ -132,6 +142,7 @@ my %defs = ( }, ); + my %vfields; foreach my $svcdb (grep dbdef->table($_), keys %defs ) { my $self = "FS::$svcdb"->new; $vfields{$svcdb} = {}; @@ -149,6 +160,37 @@ my %defs = ( warn "\$vfields{$svcdb}->{$field} = $pvf"; } #next $field } #next $svcdb + + #code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm + # and generalize the subs + # condition sub is tested to see whether to disable display of this choice + # params: ( $def, $layer, $field ) (see SUB below) + my $inv_sub = sub { + ref($_[0]) && ( $_[0]->{disable_inventory} + || $_[0]->{'type'} ne 'text' ) + }; + tie my %flag, 'Tie::IxHash', + '' => { 'desc' => 'No default', }, + 'D' => { 'desc' => 'Default', + 'condition' => + sub { ref($_[0]) && $_[0]->{disable_default} }, + }, + 'F' => { 'desc' => 'Fixed (unchangeable)', + 'condition' => + sub { ref($_[0]) && $_[0]->{disable_fixed} }, + }, + 'M' => { 'desc' => 'Manual selection from inventory', + 'condition' => $inv_sub, + }, + 'A' => { 'desc' => 'Automatically fill in from inventory', + 'condition' => $inv_sub, + }, + 'X' => { 'desc' => 'Excluded', + 'condition' => + sub { ! $vfields{$_[1]}->{$_[2]} }, + + }, + ; my @dbs = $hashref->{svcdb} ? ( $hashref->{svcdb} ) @@ -174,8 +216,8 @@ my %defs = ( my @part_export = map { qsearch( 'part_export', {exporttype => $_ } ) } keys %{FS::part_export::export_info($layer)}; - $html .= '

    '. table(). - table(). "Exports"; + $html .= '

    '. table(). + "Exports"; foreach my $part_export ( @part_export ) { $html .= 'FieldModifier"; + $html .= include('/elements/table-grid.html', 'cellpadding' => 4 ). + ''. + 'Field'. + 'Modifier'. + ''; + + my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor; + #yucky kludge my @fields = defined( dbdef->table($layer) ) ? grep { $_ ne 'svcnum' } fields($layer) : (); push @fields, 'usergroup' if $layer eq 'svc_acct'; #kludge $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 = $part_svc_column->columnvalue; my $flag = $part_svc_column->columnflag; my $def = $defs{$layer}{$field}; my $desc = ref($def) ? $def->{desc} : $def; + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } - $html .= "$field"; + $html .= qq!!. + $field; $html .= "- $desc" if $desc; $html .= ""; $flag = '' if ref($def) && $def->{type} eq 'disabled'; - $html .= - qq!Off". - ''; - unless ( ref($def) && $def->{type} eq 'disabled' ) { - $html .= - qq!Default ". - qq!Fixed "; - $html .= '
    '; - } - if ( ref($def) ) { - if ( $def->{type} eq 'select' ) { - $html .= qq!'; - } elsif ( $def->{type} eq 'radius_usergroup_selector' ) { - $html .= FS::svc_acct::radius_usergroup_selector( - [ split(',', $value) ], "${layer}__${field}" ); - } elsif ( $def->{type} eq 'disabled' ) { - $html .= - qq!!; - } else { - $html .= 'unknown type'. $def->{type}; - } + + $html .= qq!!; + + if ( ref($def) && $def->{type} eq 'disabled' ) { + + $html .= 'No default'; + } else { - $html .= - qq!!; + + $html .= qq!'; + + $html .= join("\n", + '', + ); + } - if($vfields{$layer}->{$field}) { - $html .= qq!
    Excluded "; + $html .= qq!!; + + my $disabled = $flag ? '' + : 'DISABLED STYLE="background-color: #dddddd"'; + + if ( ! ref($def) || $def->{type} eq 'text' ) { + + my $nodisplay = ' STYLE="display:none"'; + my $is_inv = ( $flag =~ /^[MA]$/ ); + + $html .= + qq!'; + + $html .= include('/elements/select-table.html', + 'element_name' => "${layer}__${field}_classnum", + 'element_etc' => ( $is_inv + ? $disabled + : $nodisplay + ), + 'table' => 'inventory_class', + 'name_col' => 'classname', + 'value' => $value, + 'empty_label' => 'Select inventory class', + ); + + } elsif ( $def->{type} eq 'select' ) { + + $html .= qq!'; + + } elsif ( $def->{type} eq 'radius_usergroup_selector' ) { + + #XXX disable the RADIUS usergroup selector? ugh it sure does need + #an overhaul, people have dum group problems because of it + + $html .= FS::svc_acct::radius_usergroup_selector( + [ split(',', $value) ], "${layer}__${field}" ); + + } elsif ( $def->{type} eq 'disabled' ) { + + $html .= + qq!!; + + } else { + + $html .= 'unknown type'. $def->{type}; + } + $html .= "\n"; - } + + } #foreach my $field (@fields) { + $part_svc->svcpart('') if $clone; #undone $html .= ""; diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index 6c8089b31..36eb4e211 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -8,11 +8,15 @@ # 'value' => 'current_value', # ##opt - # 'empty_label' => '', #better specify it though, the default might change - # 'hashref' => {}, - # 'extra_sql' => '', - # 'records' => \@records, #instead of hashref - # 'pre_options' => [ 'value' => 'option' ], #before normal options + # 'empty_label' => '', #better specify it though, the default might change + # 'hashref' => {}, + # 'extra_sql' => '', + # 'records' => \@records, #instead of hashref + # 'pre_options' => [ 'value' => 'option' ], #before normal options + # 'element_name' => '', #HTML element name, defaults to the name of + # # the primary key column + # 'element_etc' => '', #additional attributes (i.e. "DISABLED") for the + # # +