communigate (phase 2): Account Preferences (& Domain::Account Defaults:Preferences...
[freeside.git] / httemplate / edit / svc_acct.cgi
index e0610b2..5c2d5f4 100755 (executable)
@@ -1,137 +1,7 @@
-%
-%
-%my $conf = new FS::Conf;
-%my @shells = $conf->config('shells');
-%
-%my $curuser = $FS::CurrentUser::CurrentUser;
-%
-%my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct, @groups);
-%if ( $cgi->param('error') ) {
-%
-%  $svc_acct = new FS::svc_acct ( {
-%    map { $_, scalar($cgi->param($_)) } fields('svc_acct')
-%  } );
-%  $svcnum = $svc_acct->svcnum;
-%  $pkgnum = $cgi->param('pkgnum');
-%  $svcpart = $cgi->param('svcpart');
-%  $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
-%  die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
-%  @groups = $cgi->param('radius_usergroup');
-%
-%} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
-%
-%  $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
-%  $pkgnum = $1;
-%  $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
-%  $svcpart = $1;
-%
-%  $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
-%  die "No part_svc entry!" unless $part_svc;
-%
-%    $svc_acct = new FS::svc_acct({svcpart => $svcpart}); 
-%
-%    $svcnum='';
-%
-%} else { #editing
-%
-%  my($query) = $cgi->keywords;
-%  $query =~ /^(\d+)$/ or die "unparsable svcnum";
-%  $svcnum=$1;
-%  $svc_acct=qsearchs('svc_acct',{'svcnum'=>$svcnum})
-%    or die "Unknown (svc_acct) svcnum!";
-%
-%  my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
-%    or die "Unknown (cust_svc) svcnum!";
-%
-%  $pkgnum=$cust_svc->pkgnum;
-%  $svcpart=$cust_svc->svcpart;
-%
-%  $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
-%  die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
-%
-%  @groups = $svc_acct->radius_groups;
-%
-%}
-%
-%my( $cust_pkg, $cust_main ) = ( '', '' );
-%if ( $pkgnum ) {
-%  $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } );
-%  $cust_main = $cust_pkg->cust_main;
-%}
-%
-%unless ( $svcnum || $cgi->param('error') ) { #adding
-%
-%  #set gecos
-%  if ($cust_main) {
-%    unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) {
-%      $svc_acct->setfield('finger',
-%        $cust_main->getfield('first') . " " . $cust_main->getfield('last')
-%      );
-%    }
-%  }
-%
-%  $svc_acct->set_default_and_fixed( {
-%    #false laziness w/svc-acct::_fieldhandlers
-%    'usergroup' => sub { 
-%                         my( $self, $groups ) = @_;
-%                         if ( ref($groups) eq 'ARRAY' ) {
-%                           @groups = @$groups;
-%                           $groups;
-%                         } elsif ( length($groups) ) {
-%                           @groups = split(/\s*,\s*/, $groups);
-%                           [ @groups ];
-%                         } else {
-%                           @groups = ();
-%                           [];
-%                         }
-%                       }
-%  } );
-%
-%}
-%
-%#fixed radius groups always override & display
-%if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) {
-%  @groups = split(',', $part_svc->part_svc_column('usergroup')->columnvalue);
-%}
-%
-%my $action = $svcnum ? 'Edit' : 'Add';
-%
-%my $svc = $part_svc->getfield('svc');
-%
-%my $otaker = getotaker;
-%
-%my $username = $svc_acct->username;
-%my $password;
-%if ( $svc_acct->_password ) {
-%  if ( $conf->exists('showpasswords') || ! $svcnum ) {
-%    $password = $svc_acct->_password;
-%  } else {
-%    $password = "*HIDDEN*";
-%  }
-%} else {
-%  $password = '';
-%}
-%
-%my $ulen = 
-%  $conf->exists('usernamemax')
-%  ? $conf->config('usernamemax')
-%  : dbdef->table('svc_acct')->column('username')->length;
-%my $ulen2 = $ulen+2;
-%
-%my $pmax = $conf->config('passwordmax') || 8;
-%my $pmax2 = $pmax+2;
-%
-%my $p1 = popurl(1);
-%
-%
-
+<% include('/elements/header.html', "$action $svc account") %>
 
-<% include("/elements/header.html","$action $svc account") %>
-% if ( $cgi->param('error') ) { 
+<% include('/elements/error.html') %>
 
-  <FONT SIZE="+1" COLOR="#ff0000">Error: <% $cgi->param('error') %></FONT>
-  <BR><BR>
-% } 
 % if ( $cust_main ) { 
 
   <% include( '/elements/small_custview.html', $cust_main, '', 1,
   <BR>
 % } 
 
+<SCRIPT TYPE="text/javascript">
+function randomPass() {
+  var i=0;
+  var pw_set='<% join('', 'a'..'z', 'A'..'Z', '0'..'9' ) %>';
+  var pass='';
+  while(i < 8) {
+    i++;
+    pass += pw_set.charAt(Math.floor(Math.random() * pw_set.length));
+  }
+  document.OneTrueForm.clear_password.value = pass;
+}
+</SCRIPT>
 
 <FORM NAME="OneTrueForm" ACTION="<% $p1 %>process/svc_acct.cgi" METHOD=POST>
 <INPUT TYPE="hidden" NAME="svcnum" VALUE="<% $svcnum %>">
@@ -161,16 +43,22 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
   </TD>
 </TR>
 
+%if ( $part_svc->part_svc_column('_password')->columnflag ne 'F' ) {
 <TR>
   <TD ALIGN="right">Password</TD>
   <TD>
-    <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
-    (blank to generate)
+    <INPUT TYPE="text" NAME="clear_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
+    <INPUT TYPE="button" VALUE="Generate" onclick="randomPass();">
   </TD>
 </TR>
+%}else{
+    <INPUT TYPE="hidden" NAME="clear_password" VALUE="<% $password %>">
+%}
+<INPUT TYPE="hidden" NAME="_password_encoding" VALUE="<% $svc_acct->_password_encoding %>">
 %
 %my $sec_phrase = $svc_acct->sec_phrase;
-%if ( $conf->exists('security_phrase') ) {
+%if ( $conf->exists('security_phrase') 
+%  && $part_svc->part_svc_column('sec_phrase')->columnflag ne 'F' ) {
 %
 
 
@@ -207,38 +95,11 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
 %    }
 %  }
 %
-%  if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'D' ) {
-%    my $svc_domain = qsearchs('svc_domain', {
-%      'svcnum' => $part_svc->part_svc_column('domsvc')->columnvalue,
-%    } );
-%    if ( $svc_domain ) {
-%      $svc_domain{$svc_domain->svcnum} = $svc_domain;
-%    } else {
-%      warn "unknown svc_domain.svcnum for part_svc_column domsvc: ".
-%           $part_svc->part_svc_column('domsvc')->columnvalue;
-%    }
-%  }
-%
-%  if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'S' ) {
-%    foreach my $domain
-%              (split(',',$part_svc->part_svc_column('domsvc')->columnvalue)) {
-%      my $svc_domain =
-%        qsearchs('svc_domain', { 'svcnum' => $domain } );
-%     $svc_domain{$svc_domain->svcnum} = $svc_domain if $svc_domain;
-%    }
-%  }elsif ($cust_pkg && !$conf->exists('svc_acct-alldomains') ) {
-%    my @cust_svc =
-%      map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) }
-%          qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum } );
-%    foreach my $cust_svc ( @cust_svc ) {
-%      my $svc_domain =
-%        qsearchs('svc_domain', { 'svcnum' => $cust_svc->svcnum } );
-%     $svc_domain{$svc_domain->svcnum} = $svc_domain if $svc_domain;
-%    }
-%  } else {
-%    %svc_domain = map { $_->svcnum => $_ } qsearch('svc_domain', {} );
-%  }
-%
+%  %svc_domain = (%svc_domain,
+%                 domain_select_hash FS::svc_acct('svcpart' => $svcpart,
+%                                                 'pkgnum'  => $pkgnum,
+%                                                )
+%                );
 %
 
 
@@ -247,21 +108,41 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
     <TD>
       <SELECT NAME="domsvc" SIZE=1>
 % foreach my $svcnum (
-%             sort { $svc_domain{$a}->domain cmp $svc_domain{$b}->domain }
+%             sort { $svc_domain{$a} cmp $svc_domain{$b} }
 %                  keys %svc_domain
 %           ) {
 %             my $svc_domain = $svc_domain{$svcnum};
 %        
 
 
-             <OPTION VALUE="<% $svc_domain->svcnum %>" <% $svc_domain->svcnum == $domsvc ? ' SELECTED' : '' %>><% $svc_domain->domain %>
+             <OPTION VALUE="<% $svcnum %>" <% $svcnum == $domsvc ? ' SELECTED' : '' %>><% $svc_domain{$svcnum} %>
 % } 
 
       </SELECT>
     </TD>
   </TR>
 % } 
-%
+
+
+% if ( $communigate ) {
+
+    <TR>
+      <TD ALIGN="right">Aliases</TD>
+      <TD><INPUT TYPE="text" NAME="cgp_aliases" VALUE="<% $svc_acct->cgp_aliases %>"></TD>
+    </TR>
+
+% } else {
+    <INPUT TYPE="hidden" NAME="cgp_aliases" VALUE="<% $svc_acct->cgp_aliases %>">
+% }
+
+
+<% include('/elements/tr-select-svc_pbx.html',
+             'curr_value' => $svc_acct->pbxsvc,
+             'part_svc'   => $part_svc,
+             'cust_pkg'   => $cust_pkg,
+          )
+%>
+
 %#pop
 %my $popnum = $svc_acct->popnum || 0;
 %if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) {
@@ -320,16 +201,28 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
 
 
   <TR>
-    <TD ALIGN="right">GECOS</TD>
+    <TD ALIGN="right">Real Name</TD>
     <TD>
       <INPUT TYPE="text" NAME="finger" VALUE="<% $svc_acct->finger %>">
     </TD>
   </TR>
 % } 
-
+%
+%#dir
+%if ( $part_svc->part_svc_column('dir')->columnflag eq 'F'
+%     || !$curuser->access_right('Edit home dir')
+%   ) { 
 
 
 <INPUT TYPE="hidden" NAME="dir" VALUE="<% $svc_acct->dir %>">
+% } else {
+
+
+  <TR>
+    <TD ALIGN="right">Home directory</TD>
+    <TD><INPUT TYPE="text" NAME="dir" VALUE="<% $svc_acct->dir %>"></TD>
+  </TR>
+% } 
 %
 %#shell
 %my $shell = $svc_acct->shell;
@@ -361,31 +254,289 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
     </TD>
   </TR>
 % } 
-% if ( $part_svc->part_svc_column('quota')->columnflag eq 'F' ) { 
 
 
+% if ( $communigate
+%      && $part_svc->part_svc_column('cgp_type')->columnflag ne 'F' )
+% {
+
+% # settings
+
+  <TR>
+    <TD ALIGN="right">Mailbox type</TD>
+    <TD>
+      <SELECT NAME="cgp_type">
+%       foreach my $option (qw( MultiMailbox TextMailbox MailDirMailbox
+%                               AGrade BGrade CGrade                    )) {
+          <OPTION VALUE="<% $option %>"
+                  <% $option eq $svc_acct->cgp_type() ? 'SELECTED' : '' %>
+          ><% $option %>
+%       }
+      </SELECT>
+    </TD>
+  </TR>
+
+% } else {
+    <INPUT TYPE="hidden" NAME="cgp_type" VALUE="<% $svc_acct->cgp_type() %>">
+% }
+
+
+% #false laziness w/svc_domain
+% if ( $communigate
+%      && $part_svc->part_svc_column('cgp_accessmodes')->columnflag ne 'F' )
+% {
+
+  <TR>
+    <TD ALIGN="right">Enabled services</TD>
+    <TD>
+      <% include( '/elements/communigate_pro-accessmodes.html',
+                    'curr_value' => $svc_acct->cgp_accessmodes,
+                )
+      %>
+    </TD>
+  </TR>
+
+% } else {
+    <INPUT TYPE="hidden" NAME="cgp_accessmodes" VALUE="<% $svc_acct->cgp_accessmodes() |h %>">
+% }
+
+
+% if ( $part_svc->part_svc_column('quota')->columnflag eq 'F' ) { 
   <INPUT TYPE="hidden" NAME="quota" VALUE="<% $svc_acct->quota %>">
-% } else { 
+% } else {
+%   my $quota_label = $communigate ? 'Mail storage limit' : 'Quota';
+    <TR>
+      <TD ALIGN="right"><% $quota_label %></TD>
+      <TD><INPUT TYPE="text" NAME="quota" VALUE="<% $svc_acct->quota %>"></TD>
+    </TR>
+% }
 
+% tie my %cgp_label, 'Tie::IxHash',
+%   'file_quota'   => 'File storage limit',
+%   'file_maxnum'  => 'Number of files limit',
+%   'file_maxsize' => 'File size limit',
+% ;
+%
+% foreach my $key (keys %cgp_label) {
+%
+%   if ( !$communigate || $part_svc->part_svc_column($key)->columnflag eq 'F' ){
+      <INPUT TYPE="hidden" NAME="<%$key%>" VALUE="<% $svc_acct->$key() |h %>">
+%   } else {
+
+      <TR>
+        <TD ALIGN="right"><% $cgp_label{$key} %></TD>
+        <TD><INPUT TYPE="text" NAME="<% $key %>" VALUE="<% $svc_acct->$key() |h %>"></TD>
+      </TR>
+
+%   }
+% }
 
+% if ( $communigate ) {
+
+  <% include('/elements/tr-checkbox.html',
+               'label'      => 'Password recovery',
+               'field'      => 'password_recover',
+               'curr_value' => $svc_acct->password_recover,
+               'value'      => 'Y',
+            )
+  %>
+
+  <% include('/elements/tr-select.html',
+               'label'      => 'Allowed mail rules',
+               'field'      => 'cgp_rulesallowed',
+               'options'    => [ '', 'No', 'Filter Only', 'All But Exec', 'Any' ],
+               'labels'     => {
+                                 '' => 'default (No)', #No always the default?
+                               },
+               'curr_value' => $svc_acct->cgp_rulesallowed,
+            )
+  %>
+
+  <% include('/elements/tr-checkbox.html',
+               'label'      => 'RPOP modifications',
+               'field'      => 'cgp_rpopallowed',
+               'curr_value' => $svc_acct->cgp_rpopallowed,
+               'value'      => 'Y',
+            )
+  %>
+
+  <% include('/elements/tr-checkbox.html',
+               'label'      => 'Accepts mail to "all"',
+               'field'      => 'cgp_mailtoall',
+               'curr_value' => $svc_acct->cgp_mailtoall,
+               'value'      => 'Y',
+            )
+  %>
+
+  <% include('/elements/tr-checkbox.html',
+               'label'      => 'Add trailer to sent mail',
+               'field'      => 'cgp_addmailtrailer',
+               'curr_value' => $svc_acct->cgp_addmailtrailer,
+               'value'      => 'Y',
+            )
+  %>
+
+%  #preferences
+
+%# false laziness w/svc_domain acct_def
   <TR>
-    <TD ALIGN="right">Quota:</TD>
-    <TD><INPUT TYPE="text" NAME="quota" VALUE="<% $svc_acct->quota %>"></TD>
+    <TD ALIGN="right">Message delete method</TD>
+    <TD>
+      <SELECT NAME="cgp_deletemode">
+%       for ( 'Move To Trash', 'Immediately', 'Mark' ) {
+          <OPTION VALUE="<% $_ %>"
+                  <% $_ eq $svc_acct->cgp_deletemode ? 'SELECTED' : '' %>
+          ><% $_ %>
+%       }
+      </SELECT>
+    </TD>
   </TR>
-% } 
-% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { 
 
+  <TR>
+    <TD ALIGN="right">On logout remove trash</TD>
+    <TD><INPUT TYPE="text" NAME="cgp_emptytrash" VALUE="<% $svc_acct->cgp_emptytrash %>"></TD>
+  </TR>
 
-  <INPUT TYPE="hidden" NAME="slipip" VALUE="<% $svc_acct->slipip %>">
-% } else { 
+  <% include('/elements/tr-select.html',
+               'label'      => 'Language',
+               'field'      => 'cgp_language',
+               'options'    => [ '', qw( English Arabic Chinese Dutch French German Hebrew Italian Japanese Portuguese Russian Slovak Spanish Thai ) ],
+               'labels'     => {
+                                 '' => 'default (English)',
+                               },
+               'curr_value' => $svc_acct->cgp_language,
+            )
+  %>
+
+  <% include('/elements/tr-select.html',
+               'label'      => 'Time zone',
+               'field'      => 'cgp_timezone',
+               'options'    => [
+                                 'HostOS',
+                                 '(+0100) Algeria/Congo',
+                                 '(+0200) Egypt/South Africa',
+                                 '(+0300) Saudi Arabia',
+                                 '(+0400) Oman',
+                                 '(+0500) Pakistan',
+                                 '(+0600) Bangladesh',
+                                 '(+0700) Thailand/Vietnam',
+                                 '(+0800) China/Malaysia',
+                                 '(+0900) Japan/Korea',
+                                 '(+1000) Queensland',
+                                 '(+1100) Micronesia',
+                                 '(+1200) Fiji',
+                                 '(+1300) Tonga/Kiribati',
+                                 '(+1400) Christmas Islands',
+                                 '(-0100) Azores/Cape Verde',
+                                 '(-0200) Fernando de Noronha',
+                                 '(-0300) Argentina/Uruguay',
+                                 '(-0400) Venezuela/Guyana',
+                                 '(-0500) Haiti/Peru',
+                                 '(-0600) Central America',
+                                 '(-0700) Arisona',
+                                 '(-0800) Adamstown',
+                                 '(-0900) Marquesas Islands',
+                                 '(-1000) Hawaii/Tahiti',
+                                 '(-1100) Samoa',
+                                 'Asia/Afghanistan',
+                                 'Asia/India',
+                                 'Asia/Iran',
+                                 'Asia/Iraq',
+                                 'Asia/Israel',
+                                 'Asia/Jordan',
+                                 'Asia/Lebanon',
+                                 'Asia/Syria',
+                                 'Australia/Adelaide',
+                                 'Australia/East',
+                                 'Australia/NorthernTerritory',
+                                 'Europe/Central',
+                                 'Europe/Eastern',
+                                 'Europe/Moscow',
+                                 'Europe/Western',
+                                 'GMT (+0000)',
+                                 'Newfoundland',
+                                 'NewZealand/Auckland',
+                                 'NorthAmerica/Alaska',
+                                 'NorthAmerica/Atlantic',
+                                 'NorthAmerica/Central',
+                                 'NorthAmerica/Eastern',
+                                 'NorthAmerica/Mountain',
+                                 'NorthAmerica/Pacific',
+                                 'Russia/Ekaterinburg',
+                                 'Russia/Irkutsk',
+                                 'Russia/Kamchatka',
+                                 'Russia/Krasnoyarsk',
+                                 'Russia/Magadan',
+                                 'Russia/Novosibirsk',
+                                 'Russia/Vladivostok',
+                                 'Russia/Yakutsk',
+                                 'SouthAmerica/Brasil',
+                                 'SouthAmerica/Chile',
+                                 'SouthAmerica/Paraguay',
+                               ],
+               'labels'     => {
+                                 '' => 'default (HostOS)',
+                               },
+               'curr_value' => $svc_acct->cgp_timezone,
+            )
+  %>
+
+  <% include('/elements/tr-select.html',
+               'label'      => 'Layout',
+               'field'      => 'cgp_skinname',
+               'options'    => [ '', '***', 'GoldFleece', 'Skin2' ],
+               'labels'     => {
+                                 '' => 'default (***)',
+                               },
+               'curr_value' => $svc_acct->cgp_skinname,
+            )
+  %>
+
+  <% include('/elements/tr-select.html',
+               'label'      => 'Pronto style',
+               'field'      => 'cgp_prontoskinname',
+               'options'    => [ '', 'Pronto', 'Pronto-darkflame', 'Pronto-steel', 'Pronto-twilight', ],
+
+               'curr_value' => $svc_acct->cgp_prontoskinname,
+            )
+  %>
+
+  <% include('/elements/tr-select.html',
+               'label'      => 'Send read receipts',
+               'field'      => 'cgp_sendmdnmode',
+               'options'    => [ '', 'Never', 'Manually', 'Automatically' ],
+               'labels'     => {
+                                 '' => 'default (Automatically)',
+                               },
+               'curr_value' => $svc_acct->cgp_language,
+            )
+  %>
+
+%#XXX vacation message, redirect all mail, mail rules
+
+% } else {
+
+%   for (qw( password_recover cgp_rulesallowed cgp_rpopallowed cgp_mailtoall
+%            cgp_addmailtrailer
+%            cgp_deletemode cgp_emptytrash cgp_language cgp_timezone
+%            cgp_skinname cgp_sendmdnmode
+%          ) ) {
+
+      <INPUT TYPE="hidden" NAME="<% $_ %>" VALUE="<% $svc_acct->$_() %>">
+%   }
+
+% }
 
 
+% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { 
+  <INPUT TYPE="hidden" NAME="slipip" VALUE="<% $svc_acct->slipip %>">
+% } else { 
   <TR>
     <TD ALIGN="right">IP</TD>
     <TD><INPUT TYPE="text" NAME="slipip" VALUE="<% $svc_acct->slipip %>"></TD>
   </TR>
 % } 
-%
+
 % my %label = ( seconds => 'Time',
 %               upbytes => 'Upload bytes',
 %               downbytes => 'Download bytes',
@@ -457,4 +608,147 @@ Service # <% $svcnum ? "<B>$svcnum</B>" : " (NEW)" %><BR>
 
 <INPUT TYPE="submit" VALUE="Submit">
 
-</FORM></BODY></HTML>
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+my $conf = new FS::Conf;
+my @shells = $conf->config('shells');
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct, @groups);
+if ( $cgi->param('error') ) {
+
+  $svc_acct = new FS::svc_acct ( {
+    map { $_, scalar($cgi->param($_)) } fields('svc_acct')
+  } );
+  $svcnum = $svc_acct->svcnum;
+  $pkgnum = $cgi->param('pkgnum');
+  $svcpart = $cgi->param('svcpart');
+  $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+  die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
+  @groups = $cgi->param('radius_usergroup');
+
+} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding
+
+  $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum';
+  $pkgnum = $1;
+  $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart';
+  $svcpart = $1;
+
+  $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart});
+  die "No part_svc entry!" unless $part_svc;
+
+  $svc_acct = new FS::svc_acct({svcpart => $svcpart}); 
+
+  $svcnum='';
+
+  $svc_acct->password_recover('Y'); #default. hmm.
+
+} else { #editing
+
+  my($query) = $cgi->keywords;
+  $query =~ /^(\d+)$/ or die "unparsable svcnum";
+  $svcnum=$1;
+  $svc_acct=qsearchs('svc_acct',{'svcnum'=>$svcnum})
+    or die "Unknown (svc_acct) svcnum!";
+
+  my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum})
+    or die "Unknown (cust_svc) svcnum!";
+
+  $pkgnum=$cust_svc->pkgnum;
+  $svcpart=$cust_svc->svcpart;
+
+  $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
+  die "No part_svc entry for svcpart $svcpart!" unless $part_svc;
+
+  @groups = $svc_acct->radius_groups;
+
+}
+
+my $communigate = scalar($part_svc->part_export('communigate_pro'));
+                # || scalar($part_svc->part_export('communigate_pro_singledomain'));
+
+my( $cust_pkg, $cust_main ) = ( '', '' );
+if ( $pkgnum ) {
+  $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } );
+  $cust_main = $cust_pkg->cust_main;
+}
+
+unless ( $svcnum || $cgi->param('error') ) { #adding
+
+  #set gecos
+  if ($cust_main) {
+    unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) {
+      $svc_acct->setfield('finger',
+        $cust_main->getfield('first') . " " . $cust_main->getfield('last')
+      );
+    }
+  }
+
+  $svc_acct->set_default_and_fixed( {
+    #false laziness w/svc-acct::_fieldhandlers
+    'usergroup' => sub { 
+                         my( $self, $groups ) = @_;
+                         if ( ref($groups) eq 'ARRAY' ) {
+                           @groups = @$groups;
+                           $groups;
+                         } elsif ( length($groups) ) {
+                           @groups = split(/\s*,\s*/, $groups);
+                           [ @groups ];
+                         } else {
+                           @groups = ();
+                           [];
+                         }
+                       }
+  } );
+
+}
+
+#fixed radius groups always override & display
+if ( $part_svc->part_svc_column('usergroup')->columnflag eq 'F' ) {
+  @groups = split(',', $part_svc->part_svc_column('usergroup')->columnvalue);
+}
+
+my $action = $svcnum ? 'Edit' : 'Add';
+
+my $svc = $part_svc->getfield('svc');
+
+my $otaker = getotaker;
+
+my $username = $svc_acct->username;
+
+my $password = '';
+if ( $cgi->param('error') ) {
+  $password = $cgi->param('clear_password');
+} elsif ( $svcnum ) {
+  my $password_encryption = $svc_acct->_password_encryption;
+  if ( $password = $svc_acct->get_cleartext_password ) {
+    $password = '*HIDDEN*' unless $conf->exists('showpasswords');
+  } elsif( $svc_acct->_password and $password_encryption ne 'plain' ) {
+    $password = "(".uc($password_encryption)." encrypted)";
+  }
+}
+
+my $ulen = 
+  $conf->exists('usernamemax')
+  ? $conf->config('usernamemax')
+  : dbdef->table('svc_acct')->column('username')->length;
+my $ulen2 = $ulen+2;
+
+my $pmax = max($conf->config('passwordmax') || 13);
+my $pmax2 = $pmax+2;
+
+my $p1 = popurl(1);
+
+sub max {
+  (sort(@_))[-1]
+}
+
+</%init>