5 if ( $cgi->param('magic') eq 'process' ) {
7 my $svcpart = $cgi->param('svcpart');
8 my $old = qsearchs('part_svc', { 'svcpart' => $svcpart }) if $svcpart;
10 $cgi->param( 'svc_acct__usergroup',
11 join(',', $cgi->param('svc_acct__usergroup') ) );
13 my $new = new FS::part_svc ( {
15 $_, scalar($cgi->param($_));
16 # } qw(svcpart svc svcdb)
17 } ( fields('part_svc'),
19 my @fields = fields($svcdb);
20 push @fields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
21 map { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ) } @fields;
22 } grep defined( $FS::Record::dbdef->table($_) ),
23 qw( svc_acct svc_domain svc_forward svc_www svc_broadband )
28 map { $_->exportnum => ( $cgi->param('exportnum'.$_->exportnum) || '') }
29 qsearch('part_export', {} );
32 $error = $new->replace($old, '1.3-COMPAT', [ 'usergroup' ], \%exportnums );
34 $error = $new->insert( [ 'usergroup' ], \%exportnums );
35 $svcpart = $new->getfield('svcpart');
38 unless ( $error ) { #no error, redirect
39 #print $cgi->redirect(popurl(3)."browse/part_svc.cgi");
40 print $cgi->redirect("${p}browse/part_svc.cgi");
45 #$part_svc = new FS::part_svc ( {
46 # map { $_, scalar($cgi->param($_)) } fields('part_svc')
49 } elsif ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {#clone
50 #$cgi->param('clone') =~ /^(\d+)$/ or die "malformed query: $query";
51 $part_svc = qsearchs('part_svc', { 'svcpart'=>$1 } )
52 or die "unknown svcpart: $1";
53 $clone = $part_svc->svcpart;
54 $part_svc->svcpart('');
55 } elsif ( $cgi->keywords ) { #edit
56 my($query) = $cgi->keywords;
57 $query =~ /^(\d+)$/ or die "malformed query: $query";
58 $part_svc=qsearchs('part_svc', { 'svcpart'=>$1 } )
59 or die "unknown svcpart: $1";
61 $part_svc = new FS::part_svc {};
64 my $action = $part_svc->svcpart ? 'Edit' : 'Add';
65 my $hashref = $part_svc->hashref;
66 # my $p_svcdb = $part_svc->svcdb || 'svc_acct';
69 #" onLoad=\"visualize()\""
72 <%= header("$action Service Definition",
73 menubar( 'Main Menu' => $p,
74 'View all service definitions' => "${p}browse/part_svc.cgi"
80 <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT>
85 Service Part #<%= $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>
87 Service <INPUT TYPE="text" NAME="svc" VALUE="<%= $hashref->{svc} %>"><BR>
88 Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<%= $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR>
89 <INPUT TYPE="hidden" NAME="magic" VALUE="process">
90 <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $hashref->{svcpart} %>">
92 Services are items you offer to your customers.
93 <UL><LI>svc_acct - Shell accounts, POP mailboxes, SLIP/PPP and ISDN accounts
94 <LI>svc_domain - Domains
95 <LI>svc_acct_sm - <B>deprecated</B> (use svc_forward for new installations) Virtual domain mail aliasing.
96 <LI>svc_forward - mail forwarding
97 <LI>svc_www - Virtual domain website
98 <!-- <LI>svc_charge - One-time charges (Partially unimplemented)
99 <LI>svc_wo - Work orders (Partially unimplemented)
102 For the selected table, you can give fields default or fixed (unchangable)
103 values. For example, a SLIP/PPP account may have a default (or perhaps fixed)
104 <B>slipip</B> of <B>0.0.0.0</B>, while a POP mailbox will probably have a fixed
105 blank <B>slipip</B> as well as a fixed shell something like <B>/bin/true</B> or
106 <B>/usr/bin/passwd</B>.
110 #these might belong somewhere else for other user interfaces
111 #pry need to eventually create stuff that's shared amount UIs
112 my $conf = new FS::Conf;
115 'dir' => 'Home directory',
116 'uid' => 'UID (set to fixed and blank for dial-only)',
117 'slipip' => 'IP address (Set to fixed and blank to disable dialin, or, set a value to be exported to RADIUS Framed-IP-Address. Use the special value <code>0e0</code> [zero e zero] to enable export to RADIUS without a Framed-IP-Address.)',
118 # 'popnum' => qq!<A HREF="$p/browse/svc_acct_pop.cgi/">POP number</A>!,
120 desc => 'Access number',
122 select_table => 'svc_acct_pop',
123 select_key => 'popnum',
124 select_label => 'city',
131 '_password' => 'Password',
132 'gid' => 'GID (when blank, defaults to UID)',
134 desc =>'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file)',
136 select_list => [ $conf->config('shells') ],
140 desc =>'svcnum from svc_domain',
142 select_table => 'svc_domain',
143 select_key => 'svcnum',
144 select_label => 'domain',
147 desc =>'ICRADIUS/FreeRADIUS groups',
148 type =>'radius_usergroup_selector',
152 'domain' => 'Domain',
155 'domuser' => 'domuser@virtualdomain.com',
156 'domuid' => 'UID where domuser@virtualdomain.com mail is forwarded',
157 'domsvc' => 'svcnum from svc_domain for virtualdomain.com',
160 'srcsvc' => 'service from which mail is to be forwarded',
161 'dstsvc' => 'service to which mail is to be forwarded',
162 'dst' => 'someone@another.domain.com to use when dstsvc is 0',
165 'amount' => 'amount',
168 'worker' => 'Worker',
177 my @dbs = $hashref->{svcdb}
178 ? ( $hashref->{svcdb} )
179 : qw( svc_acct svc_domain svc_acct_sm svc_forward svc_www );
181 tie my %svcdb, 'Tie::IxHash', map { $_=>$_ } @dbs;
182 my $widget = new HTML::Widgets::SelectLayers(
183 #'selected_layer' => $p_svcdb,
184 'selected_layer' => $hashref->{svcdb} || 'svc_acct',
185 'options' => \%svcdb,
186 'form_name' => 'dummy',
187 #'form_action' => 'process/part_svc.cgi',
188 'form_action' => 'part_svc.cgi', #self
189 'form_text' => [ qw( magic svc svcpart ) ],
190 'form_checkbox' => [ 'disabled' ],
191 'layer_callback' => sub {
193 my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!;
198 map { qsearch( 'part_export', {exporttype => $_ } ) }
199 keys %{FS::part_export::export_info($layer)};
200 $html .= '<BR><BR>'. table().
201 table(). "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>";
202 foreach my $part_export ( @part_export ) {
203 $html .= '<TD><INPUT TYPE="checkbox"'.
204 ' NAME="exportnum'. $part_export->exportnum. '" VALUE="1" ';
206 if ( $clone || $part_svc->svcpart ) #null svcpart search causing error
207 && qsearchs( 'export_svc', {
208 exportnum => $part_export->exportnum,
209 svcpart => $clone || $part_svc->svcpart });
210 $html .= '>'. $part_export->exportnum. ': '. $part_export->exporttype.
211 ' to '. $part_export->machine. '</TD>';
213 $html .= '</TR><TR>' unless $count % $columns;
215 $html .= '</TR></TABLE><BR><BR>';
217 $html .= table(). "<TH>Field</TH><TH COLSPAN=2>Modifier</TH>";
219 my @fields = defined( $FS::Record::dbdef->table($layer) )
220 ? grep { $_ ne 'svcnum' } fields($layer)
222 push @fields, 'usergroup' if $layer eq 'svc_acct'; #kludge
223 $part_svc->svcpart($clone) if $clone; #haha, undone below
224 foreach my $field (@fields) {
225 my $part_svc_column = $part_svc->part_svc_column($field);
227 ? $cgi->param("${layer}__${field}")
228 : $part_svc_column->columnvalue;
230 ? $cgi->param("${layer}__${field}_flag")
231 : $part_svc_column->columnflag;
232 my $def = $defs{$layer}{$field};
233 my $desc = ref($def) ? $def->{desc} : $def;
235 $html .= "<TR><TD>$field";
236 $html .= "- <FONT SIZE=-1>$desc</FONT>" if $desc;
238 $flag = '' if ref($def) && $def->{type} eq 'disabled';
240 qq!<TD><INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE=""!.
241 ' CHECKED'x($flag eq ''). ">Off</TD>".
243 unless ( ref($def) && $def->{type} eq 'disabled' ) {
245 qq!<INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE="D"!.
246 ' CHECKED'x($flag eq 'D'). ">Default ".
247 qq!<INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE="F"!.
248 ' CHECKED'x($flag eq 'F'). ">Fixed ".
252 if ( $def->{type} eq 'select' ) {
253 $html .= qq!<SELECT NAME="${layer}__${field}">!;
254 $html .= '<OPTION> </OPTION>' unless $value;
255 if ( $def->{select_table} ) {
256 foreach my $record ( qsearch( $def->{select_table}, {} ) ) {
257 my $rvalue = $record->getfield($def->{select_key});
258 $html .= qq!<OPTION VALUE="$rvalue"!.
259 ( $rvalue==$value ? ' SELECTED>' : '>' ).
260 $record->getfield($def->{select_label}). '</OPTION>';
262 } else { # select_list
263 foreach my $item ( @{$def->{select_list}} ) {
264 $html .= qq!<OPTION VALUE="$item"!.
265 ( $item eq $value ? ' SELECTED>' : '>' ).
269 $html .= '</SELECT>';
270 } elsif ( $def->{type} eq 'radius_usergroup_selector' ) {
271 $html .= FS::svc_acct::radius_usergroup_selector(
272 [ split(',', $value) ], "${layer}__${field}" );
273 } elsif ( $def->{type} eq 'disabled' ) {
275 qq!<INPUT TYPE="hidden" NAME="${layer}__${field}" VALUE="">!;
277 $html .= '<font color="#ff0000">unknown type'. $def->{type};
281 qq!<INPUT TYPE="text" NAME="${layer}__${field}" VALUE="$value">!;
283 $html .= "</TD></TR>\n";
285 $part_svc->svcpart('') if $clone; #undone
288 $html .= '<BR><INPUT TYPE="submit" VALUE="'.
289 ($hashref->{svcpart} ? 'Apply changes' : 'Add service'). '">';
297 Table <%= $widget->html %>