2 To be called from part_svc.cgi.
3 <& elements/part_svc_column.html,
6 'part_svc' => $part_svc, # the existing part_svc to edit
7 'clone' => 0, # or a svcpart to clone from
12 # the semantics of this could be better
14 # all of these conditions are when NOT to allow that flag choice
15 # don't allow the 'inventory' flags (M, A) to be chosen for
16 # fields that aren't free-text
17 my $inv_sub = sub { $_[0]->{disable_inventory} || $_[0]->{type} ne 'text' };
18 tie my %flag, 'Tie::IxHash',
19 '' => { 'desc' => 'No default', 'condition' => sub { 0 } },
20 'D' => { 'desc' => 'Default',
22 sub { $_[0]->{disable_default } }
24 'F' => { 'desc' => 'Fixed (unchangeable)',
26 sub { $_[0]->{disable_fixed} },
28 'S' => { 'desc' => 'Selectable Choice',
30 sub { $_[0]->{disable_select} },
32 'M' => { 'desc' => 'Manual selection from inventory',
33 'condition' => $inv_sub,
35 'A' => { 'desc' => 'Automatically fill in from inventory',
36 'condition' => $inv_sub,
38 'R' => { 'desc' => 'Manual selection from real estate',
39 'condition' => $inv_sub,
41 'H' => { 'desc' => 'Select from hardware class',
42 'condition' => sub { $_[0]->{type} ne 'select-hardware' },
44 'X' => { 'desc' => 'Excluded',
45 'condition' => sub { 1 }, # obsolete
49 # the semantics of this could be much better
52 not &{ $flag{$f}->{'condition'} }(@_);
55 my %communigate_fields = (
56 'svc_acct' => { map { $_=>1 }
57 qw( file_quota file_maxnum file_maxsize
58 password_selfchange password_recover
60 grep /^cgp_/, fields('svc_acct')
62 'svc_domain' => { map { $_=>1 }
63 qw( max_accounts trailer parent_svcnum ),
64 grep /^(cgp|acct_def)_/, fields('svc_domain')
68 <INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $svcdb %>">
70 %# include export selection
72 part_svc => $part_svc,
76 <FONT CLASS="fsinnerbox-title">Fields</FONT>
77 <& /elements/table-grid.html, cellpadding => 4 &>
79 <TH BGCOLOR="#cccccc">Field</TH>
80 <TH BGCOLOR="#cccccc">Label</TH>
81 <TH BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>
82 <TH BGCOLOR="#cccccc"><% $manual_require ? 'Required?' : '' %></TH>
84 % $part_svc->set('svcpart' => $opt{'clone'}) if $opt{'clone'}; # for now
86 % foreach my $field (@fields) {
87 % my $def = shift @defs;
88 % my $part_svc_column = $part_svc->part_svc_column($field);
89 % my $flag = $part_svc_column->columnflag;
90 % my $formatter = $def->{'format'} || sub { shift };
91 % my $value = &{$formatter}($part_svc_column->columnvalue);
92 <TR CLASS="row<%$i%>">
93 <TD ROWSPAN=2 CLASS="grid" ALIGN="right">
94 <% $def->{'label'} || $field %>
96 <TD ROWSPAN=2 CLASS="grid">
97 <INPUT NAME="<% $svcdb %>__<% $field %>_label"
98 STYLE="text-align: right"
99 VALUE="<% $part_svc_column->columnlabel || $def->{'label'} |h %>">
102 <TD ROWSPAN=1 CLASS="grid">
104 % if ( $def->{'type'} eq 'disabled' ) {
108 % my $name = $svcdb.'__'.$field.'_flag';
109 <SELECT NAME="<%$name%>"
112 onchange="flag_changed(this)">
113 % foreach my $f (keys %flag) {
114 % if ( flag_condition($f, $def, $svcdb, $field) ) {
115 <OPTION VALUE="<%$f%>"<% $flag eq $f ? ' SELECTED' : ''%>>
116 <% $flag{$f}->{desc} %>
121 % } # if $def->{'type'} eq 'disabled'
124 % # value entry/selection
125 % my $name = $svcdb.'__'.$field;
126 % # These are all MANDATORY SELECT types. Regardless of the flag value,
127 % # there will never be a text input (either in svc_* or in part_svc) for
129 % if ( $def->{'type'} eq 'checkbox' ) {
130 <& /elements/checkbox.html,
132 'curr_value' => $value,
135 % } elsif ( $def->{'type'} eq 'select' ) {
137 % if ( $def->{'select_table'} ) {
138 % # set the 'select_svc' flag to enable two-step selection of services
139 % my $comp = '/elements/select-table.html';
140 % $comp = '/elements/select-svc.html' if $def->{'select_svc'};
143 'id' => $name.'_select',
144 'table' => $def->{'select_table'},
145 'name_col' => $def->{'select_label'},
146 'value_col' => $def->{'select_key'},
147 'order_by' => dbdef->table($def->{'select_table'})->primary_key,
148 'multiple' => $def->{'multiple'},
149 'disable_empty' => $def->{'select_allow_empty'} ? undef : 1,
150 'empty_label' => $def->{'select_allow_empty'} ? ' ' : undef,
151 'curr_value' => $value,
152 # these can be switched between multiple and singular,
153 # so put the complete curr_value in an attribute
154 'element_etc' => 'default="'.encode_entities($value).'"',
157 % my (@options, %labels);
158 % if ( $def->{'select_list'} ) {
159 % @options = @{ $def->{'select_list'} };
160 % @labels{@options} = @options;
161 % } elsif ( $def->{'select_hash'} ) {
162 % if ( ref($def->{'select_hash'}) eq 'ARRAY' ) {
163 % tie my %hash, 'Tie::IxHash', @{ $def->{'select_hash'} };
164 % $def->{'select_hash'} = \%hash;
166 % @options = keys( %{ $def->{'select_hash'} } );
167 % %labels = %{ $def->{'select_hash'} };
169 <& /elements/select.html,
171 'id' => $name.'_select',
172 'options' => \@options,
173 'labels' => \%labels,
174 'multiple' => $def->{'multiple'},
175 'curr_value' => $value,
178 % } elsif ( $def->{'type'} =~ /^select-(.*?)(.html)?$/ && $1 ne 'hardware' ) {
179 <& "/elements/select-$1.html",
181 'id' => $name.'_select',
182 'multiple' => $def->{'multiple'},
183 'curr_value' => $value,
185 % } elsif ( $def->{'type'} eq 'communigate_pro-accessmodes' ) {
186 <& /elements/communigate_pro-accessmodes.html,
187 'element_name_prefix' => $name.'_',
188 'curr_value' => $value,
190 % } elsif ( $def->{'type'} eq 'textarea' ) {
192 <TEXTAREA NAME="<%$name%>"><% $value |h %></TEXTAREA>
193 % } elsif ( $def->{'type'} eq 'disabled' ) {
194 <INPUT TYPE="hidden" NAME="<%$name%>" VALUE="">
196 % # the normal case: a text input, and a _select which is an inventory
197 % # or hardware class
202 % my $mode = 'inventory';
204 % if ( $def->{'type'} eq 'select-hardware' ) {
205 % $mode = 'hardware';
208 <& /elements/select-table.html,
209 'field' => $name.'_classnum',
210 'id' => $name.'_select',
211 'table' => $mode.'_class',
212 'name_col' => 'classname',
213 'curr_value' => $value,
214 'empty_label' => "Select $mode class",
215 'multiple' => $multiple,
220 % if ($manual_require &&
221 % (!$def->{'type'} || !(grep {$_ eq $def->{'type'}} ('checkbox','disabled')))
223 <INPUT ID="<% $name.'_required' %>" TYPE="checkbox" NAME="<% $svcdb %>__<% $field %>_required" VALUE="Y"
224 <% ($part_svc_column->required || $def->{'required'}) ? 'CHECKED' : '' %>
225 <% $def->{'required'} ? 'DISABLED' : '' %>
230 <TR CLASS="row<%$i%>">
231 <TD COLSPAN=3 CLASS="def_info">
232 % if ( $def->{def_info} ) {
233 (<% $def->{def_info} %>)
238 % } # foreach my $field
240 % # special case: svc_acct password edit ACL
241 % if ( $svcdb eq 'svc_acct' ) {
242 % push @fields, 'restrict_edit_password';
244 <TD COLSPAN=3 ALIGN="right">
245 <% emt('Require "Provision" access right to edit password') %>
248 <INPUT TYPE="checkbox" NAME="restrict_edit_password" VALUE="Y" \
249 <% $part_svc->restrict_edit_password ? 'CHECKED' : '' %>>
253 % # special case: services with attached routers (false laziness...)
254 % if ( $svcdb eq 'svc_acct'
255 % or $svcdb eq 'svc_broadband'
256 % or $svcdb eq 'svc_dsl'
257 % or $svcdb eq 'svc_circuit' ) {
258 % push @fields, 'has_router';
260 <TD COLSPAN=3 ALIGN="right">
261 <% emt('This service has an attached router') %>
264 <INPUT TYPE="checkbox" NAME="has_router" VALUE="Y" \
265 <% $part_svc->has_router ? 'CHECKED' : '' %>>
270 <& /elements/progress-init.html,
272 [ # form fields to send
274 # qw(svc svcpart classnum selfservice_access disabled preserve exportnum),
277 'process/part_svc.cgi', # target
278 $p.'browse/part_svc.cgi', # redirect landing
281 % $svcpart = '' if $opt{clone};
285 VALUE="<% emt($svcpart ? 'Apply changes' : 'Add service') %>"
286 onclick="fixup_submit('<%$svcdb%>')"
293 my $conf = FS::Conf->new;
295 my $part_svc = $opt{'part_svc'} || FS::part_svc->new;
297 # see if there are communigate exports configured
298 if ( exists $communigate_fields{$svcdb} ) {
299 $communigate = FS::part_export->count("exporttype like 'communigate%'");
302 my $svcpart = $opt{'clone'} || $part_svc->svcpart;
305 if ( defined( dbdef->table($svcdb) ) ) { # when is it ever not defined?
308 and ( $communigate || ! $communigate_fields{$svcdb}->{$_} )
309 and ( !FS::part_svc->svc_table_fields($svcdb)->{$_}->{disable_part_svc_column}
310 || $part_svc->part_svc_column($_)->columnflag )
313 if ( $svcdb eq 'svc_acct'
314 or ( $svcdb eq 'svc_broadband' and $conf->exists('svc_broadband-radius') )
317 push @fields, 'usergroup';
320 my @defs = map { FS::part_svc->svc_table_fields($svcdb)->{$_} } @fields;
321 my $manual_require = FS::part_svc->svc_table_info($svcdb)->{'manual_require'};