% %my $part_svc; %my $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"; % $clone = $part_svc->svcpart; % $part_svc->svcpart(''); %} elsif ( $cgi->keywords ) { #edit % my($query) = $cgi->keywords; % $query =~ /^(\d+)$/ or die "malformed query: $query"; % $part_svc=qsearchs('part_svc', { 'svcpart'=>$1 } ) % or die "unknown svcpart: $1"; %} else { #adding % $part_svc = new FS::part_svc {}; %} % %my $action = $part_svc->svcpart ? 'Edit' : 'Add'; %my $hashref = $part_svc->hashref; %# my $p_svcdb = $part_svc->svcdb || 'svc_acct'; % % % #" onLoad=\"visualize()\"" % <% include("/elements/header.html","$action Service Definition", menubar( 'Main Menu' => $p, 'View all service definitions' => "${p}browse/part_svc.cgi" ), ) %>
Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>

Service
Disable new orders {disabled} eq 'Y' ? ' CHECKED' : '' %>>

Service definitions are the templates for items you offer to your customers. For the selected table, you can give fields default or fixed (unchangable) values, or select an inventory class to manually or automatically fill in that field.

% % %#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; %my %defs = ( % % 'svc_acct' => { % 'dir' => 'Home directory', % 'uid' => 'UID (set to fixed and blank for no UIDs)', % 'slipip' => 'IP address', %# 'popnum' => qq!POP number!, % 'popnum' => { % desc => 'Access number', % type => 'select', % select_table => 'svc_acct_pop', % select_key => 'popnum', % select_label => 'city', % }, % 'username' => { % desc => 'Username', % type => 'text', % disable_default => 1, % disable_fixed => 1, % }, % 'quota' => { % desc => '', % type => 'text', % disable_inventory => 1, % }, % '_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 ( set to blank for no shell tracking)', % type =>'select', % select_list => [ $conf->config('shells') ], % disable_inventory => 1, % }, % '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' => { % 'domain' => 'Domain', % }, % % 'svc_forward' => { % 'srcsvc' => 'service from which mail is to be forwarded', % 'dstsvc' => 'service to which mail is to be forwarded', % 'dst' => 'someone@another.domain.com to use when dstsvc is 0', % }, % %# 'svc_charge' => { %# 'amount' => 'amount', %# }, %# 'svc_wo' => { %# 'worker' => 'Worker', %# '_date' => 'Date', %# }, % % 'svc_www' => { % #'recnum' => '', % #'usersvc' => '', % }, % % 'svc_broadband' => { % 'speed_down' => 'Maximum download speed for this service in Kbps. 0 denotes unlimited.', % 'speed_up' => 'Maximum upload speed for this service in Kbps. 0 denotes unlimited.', % 'ip_addr' => 'IP address. Leave blank for automatic assignment.', % 'blocknum' => 'Address block.', % }, % % 'svc_phone' => { % 'countrycode' => { desc => 'Country code', % type => 'text', % disable_inventory => 1, % }, % 'phonenum' => 'Phone number', % 'pin' => { desc => 'Personal Identification Number', % type => 'text', % disable_inventory => 1, % }, % }, % % 'svc_external' => { % #'id' => '', % #'title' => '', % }, % %); % % my %vfields; % foreach my $svcdb (grep dbdef->table($_), keys %defs ) { % my $self = "FS::$svcdb"->new; % $vfields{$svcdb} = {}; % foreach my $field ($self->virtual_fields) { # svc_Common::virtual_fields with a null svcpart returns all of them % my $pvf = $self->pvf($field); % my @list = $pvf->list; % if (scalar @list) { % $defs{$svcdb}->{$field} = { desc => $pvf->label, % type => 'select', % select_list => \@list }; % } else { % $defs{$svcdb}->{$field} = $pvf->label; % } #endif % $vfields{$svcdb}->{$field} = $pvf; % 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} }, % }, %# 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, % }, % 'X' => { 'desc' => 'Excluded', % 'condition' => % sub { ! $vfields{$_[1]}->{$_[2]} }, % % }, % ; % % my @dbs = $hashref->{svcdb} % ? ( $hashref->{svcdb} ) % : qw( svc_acct svc_domain svc_forward svc_www svc_broadband svc_phone svc_external ); % % tie my %svcdb, 'Tie::IxHash', map { $_=>$_ } grep dbdef->table($_), @dbs; % my $widget = new HTML::Widgets::SelectLayers( % #'selected_layer' => $p_svcdb, % 'selected_layer' => $hashref->{svcdb} || 'svc_acct', % 'options' => \%svcdb, % 'form_name' => 'dummy', % #'form_action' => 'process/part_svc.cgi', % 'form_action' => 'part_svc.cgi', #self % 'form_text' => [ qw( svc svcpart ) ], % 'form_checkbox' => [ 'disabled' ], % 'layer_callback' => sub { % my $layer = shift; % % my $html = qq!!; % % my $columns = 3; % my $count = 0; % my @part_export = % map { qsearch( 'part_export', {exporttype => $_ } ) } % keys %{FS::part_export::export_info($layer)}; % $html .= '

'. table(). % "Exports"; % foreach my $part_export ( @part_export ) { % $html .= 'svcpart ) #null svcpart search causing error % && qsearchs( 'export_svc', { % exportnum => $part_export->exportnum, % svcpart => $clone || $part_svc->svcpart }); % $html .= '>'. $part_export->exportnum. ': '. $part_export->exporttype. % ' to '. $part_export->machine. ''; % $count++; % $html .= '' unless $count % $columns; % } % $html .= '

'; % % $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 .= qq!!. % $field; % $html .= "- $desc" if $desc; % $html .= ""; % $flag = '' if ref($def) && $def->{type} eq 'disabled'; % % $html .= qq!!; % % if ( ref($def) && $def->{type} eq 'disabled' ) { % % $html .= 'No default'; % % } else { % % $html .= qq!'; % % $html .= join("\n", % '', % ); % % } % % $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 .= ""; % % $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 .= '
'; % % #$html .= '
'; % % $html; % % }, % ); % % Table <% $widget->html %>