communigate pro provisioning, RT#7083
authorivan <ivan>
Wed, 17 Feb 2010 08:32:53 +0000 (08:32 +0000)
committerivan <ivan>
Wed, 17 Feb 2010 08:32:53 +0000 (08:32 +0000)
FS/FS/Conf.pm
FS/FS/Schema.pm
FS/FS/cust_svc.pm
FS/FS/part_export.pm
FS/FS/part_export/communigate_pro.pm
FS/FS/svc_Common.pm
FS/FS/svc_domain.pm
httemplate/edit/process/svc_domain.cgi
httemplate/edit/svc_domain.cgi
httemplate/view/svc_domain.cgi

index 0bb59dc..f4f70f5 100644 (file)
@@ -3539,6 +3539,13 @@ worry that config_items is freeside-specific and icky.
     'type'        => 'checkbox',
   },
 
     'type'        => 'checkbox',
   },
 
+  {
+    'key'         => 'svc_domain-edit_domain',
+    'section'     => '',
+    'description' => 'Enable domain renaming',
+    'type'        => 'checkbox',
+  },
+
   { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
   { key => "apachemachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
   { key => "apachemachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
   { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
   { key => "apachemachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
   { key => "apachemachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
index fdb4a94..6a25fab 100644 (file)
@@ -1673,9 +1673,10 @@ sub tables_hashref {
        'parent_svcnum',    'int', 'NULL',       '', '', '',
        'registrarnum',     'int', 'NULL',       '', '', '',
        'registrarkey', 'varchar', 'NULL',      512, '', '',
        'parent_svcnum',    'int', 'NULL',       '', '', '',
        'registrarnum',     'int', 'NULL',       '', '', '',
        'registrarkey', 'varchar', 'NULL',      512, '', '',
-       'setup_date',  @date_type, '', '',
+       'setup_date',      @date_type, '', '',
        'renewal_interval', 'int', 'NULL',       '', '', '',
        'expiration_date', @date_type, '', '',
        'renewal_interval', 'int', 'NULL',       '', '', '',
        'expiration_date', @date_type, '', '',
+        'max_accounts',     'int', 'NULL',       '', '', '',
       ],
       'primary_key' => 'svcnum',
       'unique' => [ ],
       ],
       'primary_key' => 'svcnum',
       'unique' => [ ],
index 3c28204..3ce1314 100644 (file)
@@ -251,6 +251,18 @@ sub replace {
     }
   }
 
     }
   }
 
+#  #trigger a re-export on pkgnum changes?
+#  # (of prepaid packages), for Expiration RADIUS attribute
+#  if ( $new->pkgnum != $old->pkgnum && $new->cust_pkg->part_pkg->is_prepaid ) {
+#    my $svc_x = $new->svc_x;
+#    local($FS::Record::nowarn_identical) = 1;
+#    my $error = $svc_x->export('replace');
+#    if ( $error ) {
+#      $dbh->rollback if $oldAutoCommit;
+#      return $error if $error;
+#    }
+#  }
+
   #my $error = $new->SUPER::replace($old, @_);
   my $error = $new->SUPER::replace($old);
   if ( $error ) {
   #my $error = $new->SUPER::replace($old, @_);
   my $error = $new->SUPER::replace($old);
   if ( $error ) {
@@ -411,7 +423,7 @@ sub _svc_label {
 
 =item export_links
 
 
 =item export_links
 
-Returns a list of html elements associated with this services exports.
+Returns a listref of html elements associated with this service's exports.
 
 =cut
 
 
 =cut
 
@@ -423,6 +435,21 @@ sub export_links {
   $svc_x->export_links;
 }
 
   $svc_x->export_links;
 }
 
+=item export_getsettings
+
+Returns two hashrefs of settings associated with this service's exports.
+
+=cut
+
+sub export_getsettings {
+  my $self = shift;
+  my $svc_x = $self->svc_x
+    or return "can't find ". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
+
+  $svc_x->export_getsettings;
+}
+
+
 =item svc_x
 
 Returns the FS::svc_XXX object for this service (i.e. an FS::svc_acct object or
 =item svc_x
 
 Returns the FS::svc_XXX object for this service (i.e. an FS::svc_acct object or
index d533db8..588606d 100644 (file)
@@ -376,6 +376,15 @@ Adds a list of web elements to ARRAYREF specific to this export and SVC_OBJECT.
 The elements are displayed in the UI to lead the the operator to external
 configuration, monitoring, and similar tools.
 
 The elements are displayed in the UI to lead the the operator to external
 configuration, monitoring, and similar tools.
 
+=item export_getsettings SVC_OBJECT SETTINGS_HASHREF DEFAUTS_HASHREF
+
+Adds a hashref of settings to SETTINGSREF specific to this export and
+SVC_OBJECT.  The elements can be displayed in the UI on the service view.
+
+DEFAULTSREF is a hashref with the same keys where true values indicate the
+setting is a default (and thus can be displayed in the UI with less emphasis,
+or hidden by default).
+
 =cut
 
 =back
 =cut
 
 =back
index ecb3780..c4201c0 100644 (file)
@@ -1,35 +1,43 @@
 package FS::part_export::communigate_pro;
 
 package FS::part_export::communigate_pro;
 
-use vars qw(@ISA %info %options);
+use strict;
+use vars qw(@ISA %info %options $DEBUG);
+use Data::Dumper;
 use Tie::IxHash;
 use FS::part_export;
 use FS::queue;
 
 @ISA = qw(FS::part_export);
 
 use Tie::IxHash;
 use FS::part_export;
 use FS::queue;
 
 @ISA = qw(FS::part_export);
 
+$DEBUG = 1;
+
 tie %options, 'Tie::IxHash',
 tie %options, 'Tie::IxHash',
-  'port'     => { label=>'Port number', default=>'106', },
-  'login'    => { label=>'The administrator account name.  The name can contain a domain part.', },
-  'password' => { label=>'The administrator account password.', },
-  'accountType' => { label=>'Type for newly-created accounts',
-                     type=>'select',
-                     options=>[qw( MultiMailbox TextMailbox MailDirMailbox )],
-                     default=>'MultiMailbox',
-                   },
-  'externalFlag' => { label=> 'Create accounts with an external (visible for legacy mailers) INBOX.',
-                      type=>'checkbox',
-                    },
-  'AccessModes' => { label=>'Access modes',
-                     default=>'Mail POP IMAP PWD WebMail WebSite',
-                   },
+  'port'          => { label   =>'Port number', default=>'106', },
+  'login'         => { label   =>'The administrator account name.  The name can contain a domain part.', },
+  'password'      => { label   =>'The administrator account password.', },
+  'accountType'   => { label   => 'Type for newly-created accounts',
+                       type    => 'select',
+                       options => [qw(MultiMailbox TextMailbox MailDirMailbox)],
+                       default => 'MultiMailbox',
+                     },
+  'externalFlag'  => { label   => 'Create accounts with an external (visible for legacy mailers) INBOX.',
+                       type    => 'checkbox',
+                     },
+  'AccessModes'   => { label   => 'Access modes',
+                       default => 'Mail POP IMAP PWD WebMail WebSite',
+                     },
+  'create_domain' => { label   => 'Domain creation API call',
+                       type    => 'select',
+                       options => [qw( CreateDomain CreateSharedDomain )],
+                     }
 ;
 
 %info = (
 ;
 
 %info = (
-  'svc'     => 'svc_acct',
-  'desc'    => 'Real-time export to a CommuniGate Pro mail server',
+  'svc'     => [qw( svc_acct svc_domain )],
+  'desc'    => 'Real-time export of accounts and domains to a CommuniGate Pro mail server',
   'options' => \%options,
   'notes'   => <<'END'
   'options' => \%options,
   'notes'   => <<'END'
-Real time export to a
+Real time export of accounts and domains to a
 <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a>
 mail server.  The
 <a href="http://www.stalker.com/CGPerl/">CommuniGate Pro Perl Interface</a>
 <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a>
 mail server.  The
 <a href="http://www.stalker.com/CGPerl/">CommuniGate Pro Perl Interface</a>
@@ -45,77 +53,199 @@ sub export_username {
 }
 
 sub _export_insert {
 }
 
 sub _export_insert {
-  my( $self, $svc_acct ) = (shift, shift);
-  my @options = ( $svc_acct->svcnum, 'CreateAccount',
-    'accountName'    => $self->export_username($svc_acct),
-    'accountType'    => $self->option('accountType'),
-    'AccessModes'    => $self->option('AccessModes'),
-    'RealName'       => $svc_acct->finger,
-    'Password'       => $svc_acct->_password,
-  );
-  push @options, 'MaxAccountSize' => $svc_acct->quota if $svc_acct->quota;
-  push @options, 'externalFlag'   => $self->option('externalFlag')
-    if $self->option('externalFlag');
+  my( $self, $svc_x ) = (shift, shift);
+
+  my @options;
+
+  if ( $svc_x->isa('FS::svc_acct') ) {
+
+    @options = ( $svc_x->svcnum, 'CreateAccount',
+      'accountName'    => $self->export_username($svc_x),
+      'accountType'    => $self->option('accountType'),
+      'AccessModes'    => $self->option('AccessModes'),
+      'RealName'       => $svc_x->finger,
+      'Password'       => $svc_x->_password,
+    );
+    push @options, 'MaxAccountSize' => $svc_x->quota if $svc_x->quota;
+    push @options, 'externalFlag'   => $self->option('externalFlag')
+      if $self->option('externalFlag');
+
+  } elsif ( $svc_x->isa('FS::svc_domain') ) {
+
+    my $create = $self->option('create_domain') || 'CreateDomain';
+
+    @options = ( $svc_x->svcnum, $create, $svc_x->domain,
+      #other domain creation options?
+    );
+    push @options, 'AccountsLimit' => $svc_x->max_accounts
+      if $svc_x->max_accounts;
+
+  } else {
+    die "guru meditation #14: $svc_x is not FS::svc_acct, or FS::svc_domain";
+  }
 
   $self->communigate_pro_queue( @options );
 }
 
 sub _export_replace {
   my( $self, $new, $old ) = (shift, shift, shift);
 
   $self->communigate_pro_queue( @options );
 }
 
 sub _export_replace {
   my( $self, $new, $old ) = (shift, shift, shift);
-  return "can't (yet) change username with CommuniGate Pro"
-    if $old->username ne $new->username;
-  return "can't (yet) change domain with CommuniGate Pro"
-    if $self->export_username($old) ne $self->export_username($new);
-  return "can't (yet) change GECOS with CommuniGate Pro"
-    if $old->finger ne $new->finger;
-  return "can't (yet) change quota with CommuniGate Pro"
-    if $old->quota ne $new->quota;
-  return '' unless $old->username ne $new->username
-                || $old->_password ne $new->_password
-                || $old->finger ne $new->finger
-                || $old->quota ne $new->quota;
-
-  return '' if '*SUSPENDED* '. $old->_password eq $new->_password;
-
-  #my $err_or_queue = $self->communigate_pro_queue( $new->svcnum,'RenameAccount',
-  #  $old->email, $new->email );
-  #return $err_or_queue unless ref($err_or_queue);
-  #my $jobnum = $err_or_queue->jobnum;
-
-  $self->communigate_pro_queue( $new->svcnum, 'SetAccountPassword',
-                                $self->export_username($new), $new->_password        )
-    if $new->_password ne $old->_password;
+
+  if ( $new->isa('FS::svc_acct') ) {
+
+    #XXX they probably need the ability to change some of these
+    return "can't (yet) change username with CommuniGate Pro"
+      if $old->username ne $new->username;
+    return "can't (yet) change domain with CommuniGate Pro"
+      if $self->export_username($old) ne $self->export_username($new);
+    return "can't (yet) change GECOS with CommuniGate Pro"
+      if $old->finger ne $new->finger;
+    return "can't (yet) change quota with CommuniGate Pro"
+      if $old->quota ne $new->quota;
+    return '' unless $old->username ne $new->username
+                  || $old->_password ne $new->_password
+                  || $old->finger ne $new->finger
+                  || $old->quota ne $new->quota;
+
+    return '' if '*SUSPENDED* '. $old->_password eq $new->_password;
+
+    #my $err_or_queue = $self->communigate_pro_queue( $new->svcnum,'RenameAccount',
+    #  $old->email, $new->email );
+    #return $err_or_queue unless ref($err_or_queue);
+    #my $jobnum = $err_or_queue->jobnum;
+
+    $self->communigate_pro_queue( $new->svcnum, 'SetAccountPassword',
+                                  $self->export_username($new), $new->_password        )
+      if $new->_password ne $old->_password;
+
+  }  elsif ( $new->isa('FS::svc_domain') ) {
+
+    if ( $old->domain ne $new->domain ) {
+      $self->communigate_pro_queue( $new->svcnum, 'RenameDomain',
+        $old->domain, $new->domain,
+      );
+    }
+
+    if ( $old->max_accounts ne $new->max_accounts ) {
+      $self->communigate_pro_queue( $new->svcnum, 'UpdateDomainSettings',
+        $new->domain, 'AccountsLimit' => ($new->max_accounts || 'default'),
+      );
+    }
+
+    #other kinds of changes?
+
+  } else {
+    die "guru meditation #15: $new is not FS::svc_acct, or FS::svc_domain";
+  }
 
 }
 
 sub _export_delete {
 
 }
 
 sub _export_delete {
-  my( $self, $svc_acct ) = (shift, shift);
-  $self->communigate_pro_queue( $svc_acct->svcnum, 'DeleteAccount',
-    $self->export_username($svc_acct),
-  );
+  my( $self, $svc_x ) = (shift, shift);
+
+  if ( $svc_x->isa('FS::svc_acct') ) {
+
+    $self->communigate_pro_queue( $svc_x->svcnum, 'DeleteAccount',
+      $self->export_username($svc_x),
+    );
+
+  } elsif ( $svc_x->isa('FS::svc_domain') ) {
+
+    $self->communigate_pro_queue( $svc_x->svcnum, 'DeleteDomain',
+      $svc_x->domain,
+      #XXX turn on force option for domain deletion?
+    );
+
+  } else {
+    die "guru meditation #16: $svc_x is not FS::svc_acct, or FS::svc_domain";
+  }
+
 }
 
 sub _export_suspend {
 }
 
 sub _export_suspend {
-  my( $self, $svc_acct ) = (shift, shift);
-  $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings',
-    'accountName' => $self->export_username($svc_acct),
-    'AccessModes' => 'Mail',
-  );
+  my( $self, $svc_x ) = (shift, shift);
+
+  if ( $svc_x->isa('FS::svc_acct') ) {
+
+     $self->communigate_pro_queue( $svc_x->svcnum, 'UpdateAccountSettings',
+      'accountName' => $self->export_username($svc_x),
+      'AccessModes' => 'Mail',
+    );
+
+  } elsif ( $svc_x->isa('FS::svc_domain') ) {
+
+    #XXX domain operations
+  } else {
+    die "guru meditation #17: $svc_x is not FS::svc_acct, or FS::svc_domain";
+  }
+
 }
 
 sub _export_unsuspend {
 }
 
 sub _export_unsuspend {
-  my( $self, $svc_acct ) = (shift, shift);
-  $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings',
-    'accountName' => $self->export_username($svc_acct),
-    'AccessModes' => $self->option('AccessModes'),
-  );
+  my( $self, $svc_x ) = (shift, shift);
+
+  if ( $svc_x->isa('FS::svc_acct') ) {
+
+    $self->communigate_pro_queue( $svc_x->svcnum, 'UpdateAccountSettings',
+      'accountName' => $self->export_username($svc_x),
+      'AccessModes' => $self->option('AccessModes'),
+    );
+  } elsif ( $svc_x->isa('FS::svc_domain') ) {
+
+    #XXX domain operations
+  } else {
+    die "guru meditation #18: $svc_x is not FS::svc_acct, or FS::svc_domain";
+  }
+
+}
+
+sub export_getsettings {
+  my($self, $svc_x, $settingsref, $defaultref ) = @_;
+
+  my $settings = eval { $self->communigate_pro_runcommand(
+    'GetDomainSettings',
+    $svc_x->domain
+  ) };
+  return $@ if $@;
+
+  my $effective_settings = eval { $self->communigate_pro_runcommand(
+    'GetDomainEffectiveSettings',
+    $svc_x->domain
+  ) };
+  return $@ if $@;
+
+  my %defaults = map { $_ => 1 }
+                   grep !exists(${$settings}{$_}), keys %$effective_settings;
+
+  foreach my $key ( grep ref($effective_settings->{$_}),
+                    keys %$effective_settings )
+  {
+    my $value = $effective_settings->{$key};
+    if ( ref($value) eq 'ARRAY' ) {
+      $effective_settings->{$key} = join(', ', @$value);
+    } else {
+      #XXX
+      warn "serializing ". ref($value). " for table display not yet handled";
+    }
+  }
+
+  %{$settingsref} = %$effective_settings;
+  %{$defaultref} = %defaults;
+
+  '';
 }
 
 sub communigate_pro_queue {
   my( $self, $svcnum, $method ) = (shift, shift, shift);
 }
 
 sub communigate_pro_queue {
   my( $self, $svcnum, $method ) = (shift, shift, shift);
-  my @kludge_methods = qw(CreateAccount UpdateAccountSettings);
-  my $sub = 'communigate_pro_command';
-  $sub = $method if grep { $method eq $_ } @kludge_methods;
+  my %kludge_methods = (
+    'CreateAccount'         => 'CreateAccount',
+    'UpdateAccountSettings' => 'UpdateAccountSettings',
+    'CreateDomain'          => 'cp_Scalar_Hash',
+    'CreateSharedDomain'    => 'cp_Scalar_Hash',
+    'UpdateDomainSettings'  => 'UpdateDomainSettings',
+  );
+  my $sub = exists($kludge_methods{$method})
+              ? $kludge_methods{$method}
+              : 'communigate_pro_command';
   my $queue = new FS::queue {
     'svcnum' => $svcnum,
     'job'    => "FS::part_export::communigate_pro::$sub",
   my $queue = new FS::queue {
     'svcnum' => $svcnum,
     'job'    => "FS::part_export::communigate_pro::$sub",
@@ -131,6 +261,41 @@ sub communigate_pro_queue {
 
 }
 
 
 }
 
+sub communigate_pro_runcommand {
+  my( $self, $method ) = (shift, shift);
+
+  communigate_pro_command(
+    $self->machine,
+    $self->option('port'),
+    $self->option('login'),
+    $self->option('password'),
+    $method,
+    @_,
+  );
+
+}
+
+#XXX one sub per arg prototype is lame.  more magic?  i suppose queue needs
+# to store data strctures properly instead of just an arg list.  right.
+
+sub cp_Scalar_Hash {
+  my( $machine, $port, $login, $password, $method, $scalar, %hash ) = @_;
+  my @args = ( $scalar, \%hash );
+  communigate_pro_command( $machine, $port, $login, $password, $method, @args );
+}
+
+#sub cp_Hash {
+#  my( $machine, $port, $login, $password, $method, %hash ) = @_;
+#  my @args = ( \%hash );
+#  communigate_pro_command( $machine, $port, $login, $password, $method, @args );
+#}
+
+sub UpdateDomainSettings {
+  my( $machine, $port, $login, $password, $method, $domain, %settings ) = @_;
+  my @args = ( 'domain' => $domain, 'settings' => \%settings );
+  communigate_pro_command( $machine, $port, $login, $password, $method, @args );
+}
+
 sub CreateAccount {
   my( $machine, $port, $login, $password, $method, %args ) = @_;
   my $accountName  = delete $args{'accountName'};
 sub CreateAccount {
   my( $machine, $port, $login, $password, $method, %args ) = @_;
   my $accountName  = delete $args{'accountName'};
@@ -152,7 +317,7 @@ sub UpdateAccountSettings {
   my( $machine, $port, $login, $password, $method, %args ) = @_;
   my $accountName  = delete $args{'accountName'};
   $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ];
   my( $machine, $port, $login, $password, $method, %args ) = @_;
   my $accountName  = delete $args{'accountName'};
   $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ];
-  @args = ( $accountName, \%args );
+  my @args = ( $accountName, \%args );
   communigate_pro_command( $machine, $port, $login, $password, $method, @args );
 }
 
   communigate_pro_command( $machine, $port, $login, $password, $method, @args );
 }
 
@@ -168,10 +333,15 @@ sub communigate_pro_command { #subroutine, not method
     'password' => $password,
   } ) or die "Can't login to CGPro: $CGP::ERR_STRING\n";
 
     'password' => $password,
   } ) or die "Can't login to CGPro: $CGP::ERR_STRING\n";
 
-  $cli->$method(@args) or die "CGPro error: ". $cli->getErrMessage;
+  #warn "$method ". Dumper(@args) if $DEBUG;
+
+  my $return = $cli->$method(@args)
+    or die "Communigate Pro error: ". $cli->getErrMessage;
 
   $cli->Logout; # or die "Can't logout of CGPro: $CGP::ERR_STRING\n";
 
 
   $cli->Logout; # or die "Can't logout of CGPro: $CGP::ERR_STRING\n";
 
+  $return;
+
 }
 
 1;
 }
 
 1;
index 368e936..ee270ca 100644 (file)
@@ -854,6 +854,25 @@ sub export_links {
   $return;
 }
 
   $return;
 }
 
+=item export_getsettings
+
+Runs export_getsettings callbacks and returns the two hashrefs.
+
+=cut
+
+sub export_getsettings {
+  my $self = shift;
+  my %settings = ();
+  my %defaults = ();
+  my $error = $self->export('getsettings', \%settings, \%defaults);
+  if ( $error ) {
+    #XXX bubble this up better
+    warn "error running export_getsetings: $error";
+    return ( {}, {} );
+  }
+  ( \%settings, \%defaults );
+}
+
 =item export HOOK [ EXPORT_ARGS ]
 
 Runs the provided export hook (i.e. "suspend", "unsuspend") for this service.
 =item export HOOK [ EXPORT_ARGS ]
 
 Runs the provided export hook (i.e. "suspend", "unsuspend") for this service.
index 8ca30c2..89ee26a 100644 (file)
@@ -89,6 +89,8 @@ FS::svc_Common.  The following fields are currently supported:
 
 =item expiration_date - UNIX timestamp
 
 
 =item expiration_date - UNIX timestamp
 
+=item max_accounts
+
 =back
 
 =head1 METHODS
 =back
 
 =head1 METHODS
@@ -109,6 +111,9 @@ sub table_info {
     'cancel_weight'  => 60,
     'fields' => {
       'domain' => 'Domain',
     'cancel_weight'  => 60,
     'fields' => {
       'domain' => 'Domain',
+      'max_accounts' => { label => 'Maximum number of accounts',
+                          'disable_inventory' => 1,
+                        },
     },
   };
 }
     },
   };
 }
@@ -290,7 +295,8 @@ sub replace {
               : $new->replace_old;
 
   return "Can't change domain - reorder."
               : $new->replace_old;
 
   return "Can't change domain - reorder."
-    if $old->getfield('domain') ne $new->getfield('domain'); 
+    if $old->getfield('domain') ne $new->getfield('domain')
+    && ! $conf->exists('svc_domain-edit_domain'); 
 
   # Better to do it here than to force the caller to remember that svc_domain is weird.
   $new->setfield(action => 'I');
 
   # Better to do it here than to force the caller to remember that svc_domain is weird.
   $new->setfield(action => 'I');
@@ -335,6 +341,7 @@ sub check {
 
   my $error = $self->ut_numbern('svcnum')
               || $self->ut_numbern('catchall')
 
   my $error = $self->ut_numbern('svcnum')
               || $self->ut_numbern('catchall')
+              || $self->ut_numbern('max_accounts')
   ;
   return $error if $error;
 
   ;
   return $error if $error;
 
@@ -429,6 +436,7 @@ sub domain_record {
     'PTR'   => sub { $_[0]->reczone <=> $_[1]->reczone },
   );
 
     'PTR'   => sub { $_[0]->reczone <=> $_[1]->reczone },
   );
 
+  map { $_ } #return $self->num_domain_record( PARAMS ) unless wantarray;
   sort {    $order{$a->rectype} <=> $order{$b->rectype}
          or &{ $sort{$a->rectype} || sub { 0; } }($a, $b)
        }
   sort {    $order{$a->rectype} <=> $order{$b->rectype}
          or &{ $sort{$a->rectype} || sub { 0; } }($a, $b)
        }
index 59b5180..d8c1a12 100755 (executable)
@@ -24,10 +24,10 @@ my $new = new FS::svc_domain ( {
 
 my $error = '';
 if ($cgi->param('svcnum')) {
 
 my $error = '';
 if ($cgi->param('svcnum')) {
-  $error="Can't modify a domain!";
+  $error  = $new->replace();
 } else {
 } else {
-  $error=$new->insert;
-  $svcnum=$new->svcnum;
+  $error  = $new->insert;
+  $svcnum = $new->svcnum;
 }
 
 </%init>
 }
 
 </%init>
index 10079ce..369d6a0 100755 (executable)
@@ -8,10 +8,18 @@
 <INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
 
 <% ntable("#cccccc",2) %>
 <INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $svcpart %>">
 
 <% ntable("#cccccc",2) %>
+
 <TR>
 <TR>
-<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="<% $domain %>" SIZE=28 MAXLENGTH=63>
-<BR>
+  <TD ALIGN="right">Domain</TD>
+  <TD>
+%   if ( !$svcnum || $conf->exists('svc_domain-edit_domain') ) {
+      <INPUT TYPE="text" NAME="domain" VALUE="<% $domain %>" SIZE=28 MAXLENGTH=63>
+%   } else {
+      <B><% $domain %></B>
+%   }
+
 % if ($export) {
 % if ($export) {
+<BR>
 Available top-level domains: <% $export->option('tlds') %>
 </TR>
 
 Available top-level domains: <% $export->option('tlds') %>
 </TR>
 
@@ -27,11 +35,25 @@ Available top-level domains: <% $export->option('tlds') %>
 </TR>
 
 % }
 </TR>
 
 % }
-
-<TR>
-<P><INPUT TYPE="submit" VALUE="Submit">
+  </TD>
 </TR>
 </TR>
+
+% if ( $part_svc->part_svc_column('max_accounts')->columnflag =~ /^[FA]$/ ) {
+    <INPUT TYPE="hidden" NAME="max_accounts" VALUE="<% $svc_domain->max_accounts %>">
+% } else {
+    <TR>
+      <TD ALIGN="right">Maximum number of accounts</TD>
+      <TD>
+        <INPUT TYPE="text" NAME="max_accounts" SIZE=5 MAXLENGTH=6 VALUE="<% $svc_domain->max_accounts %>">
+      </TD>
+    </TR>
+% }
+
 </TABLE>
 </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Submit">
+
 </FORM>
 
 <% include('/elements/footer.html') %>
 </FORM>
 
 <% include('/elements/footer.html') %>
@@ -41,6 +63,8 @@ Available top-level domains: <% $export->option('tlds') %>
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
 
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
 
+my $conf = new FS::Conf;
+
 my($svcnum, $pkgnum, $svcpart, $kludge_action, $part_svc,
    $svc_domain);
 if ( $cgi->param('error') ) {
 my($svcnum, $pkgnum, $svcpart, $kludge_action, $part_svc,
    $svc_domain);
 if ( $cgi->param('error') ) {
index a9fc775..3f2d473 100755 (executable)
@@ -1,19 +1,48 @@
-<% include("/elements/header.html",'Domain View', menubar(
-  ( ( $pkgnum || $custnum )
-    ? ( "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum",
-      )
-    : ( "Delete this (unaudited) domain" =>
-          "javascript:areyousure('${p}misc/cancel-unaudited.cgi?$svcnum', 'Delete $domain and all records?' )" )
-  )
-)) %>
+% if ( $custnum ) {
+
+%#  <% include("/elements/header.html","View $svcdomain") %>
+  <% include("/elements/header.html","View domain") %>
+  <% include( '/elements/small_custview.html', $custnum, '', 1,
+     "${p}view/cust_main.cgi") %>
+  <BR>
+
+% } else {
+
+  <% include("/elements/header.html",'View domain', menubar(
+       "Cancel this (unaudited) domain" =>
+         "javascript:areyousure('${p}misc/cancel-unaudited.cgi?$svcnum', 'Delete $domain and all records?')",
+     ))
+  %>
+
+% }
 
 <% include('/elements/error.html') %>
 
 
 <% include('/elements/error.html') %>
 
-Service #<% $svcnum %>
-<BR>Service: <B><% $part_svc->svc %></B>
-<BR>Domain name: <B><% $domain %></B>
+Service #<B><% $svcnum %></B>
+% #if ( $conf->exists('svc_domain-edit_domain') ) {
+  | <A HREF="<%$p%>edit/svc_domain.cgi?<%$svcnum%>">Edit this domain</A>
+% #}
+
+<% &ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+
+<TR>
+  <TD ALIGN="right">Service</TD>
+  <TD BGCOLOR="#ffffff"><% $part_svc->svc %></TD>
+</TR>
+
+<TR>
+  <TD ALIGN="right">Domain</TD>
+  <TD BGCOLOR="#ffffff">
+    <B><% $domain %></B>
+    <A HREF="<% ${p} %>misc/whois.cgi?custnum=<%$custnum%>;svcnum=<%$svcnum%>;domain=<%$domain%>">(view whois information)</A>
+  </TD>
+</TR>
+
 % if ($export) {
 % if ($export) {
-<BR>Status: <B><% $status %></B>
+  <TR>
+    <TD ALIGN="right">Registration status</TD>
+    <TD BGCOLOR="#ffffff"><B><% $status %></B>
+
 %   if ( $FS::CurrentUser::CurrentUser->access_right('Manage domain registration') ) {
 %     if ( defined($ops{'register'}) ) {
     <A HREF="<% ${p} %>edit/process/domreg.cgi?op=register&svcnum=<% $svcnum %>">Register at <% $registrar->{'name'} %></A>&nbsp;
 %   if ( $FS::CurrentUser::CurrentUser->access_right('Manage domain registration') ) {
 %     if ( defined($ops{'register'}) ) {
     <A HREF="<% ${p} %>edit/process/domreg.cgi?op=register&svcnum=<% $svcnum %>">Register at <% $registrar->{'name'} %></A>&nbsp;
@@ -28,17 +57,30 @@ Service #<% $svcnum %>
     <A HREF="<% ${p} %>edit/process/domreg.cgi?op=revoke&svcnum=<% $svcnum %>">Revoke</A>
 %     }
 %   }
     <A HREF="<% ${p} %>edit/process/domreg.cgi?op=revoke&svcnum=<% $svcnum %>">Revoke</A>
 %     }
 %   }
+
+    </TD>
+  </TR>
+% }
+
+% if ( $svc_domain->max_accounts ) {
+  <TR>
+    <TD ALIGN="right">Maximum number of Accounts</TD>
+    <TD BGCOLOR="#ffffff"><% $svc_domain->max_accounts %></TD>
+  </TR>
 % }
 
 % }
 
+<TR>
+  <TD ALIGN="right">Catch all email</TD>
+  <TD BGCOLOR="#ffffff"><% $email ? "<B>$email</B>" : '<I>(none)</I>' %>
 % if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall') ) {
 % if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain catchall') ) {
-    <BR>Catch all email <A HREF="<% ${p} %>misc/catchall.cgi?<% $svcnum %>">(change)</A>:
-% } else {
-    <BR>Catch all email:
+     <A HREF="<% ${p} %>misc/catchall.cgi?<% $svcnum %>">(change)</A>
 % }
 % }
+  </TD>
+</TR>
+
+</TABLE></TD></TR></TABLE>
+<BR>
 
 
-<% $email ? "<B>$email</B>" : "<I>(none)<I>" %>
-<BR><BR><A HREF="<% ${p} %>misc/whois.cgi?custnum=<%$custnum%>;svcnum=<%$svcnum%>;domain=<%$domain%>">View whois information.</A>
-<BR><BR>
 <SCRIPT>
   function areyousure(href, message) {
     if ( confirm(message) == true )
 <SCRIPT>
   function areyousure(href, message) {
     if ( confirm(message) == true )
@@ -49,6 +91,7 @@ Service #<% $svcnum %>
   }
 </SCRIPT>
 
   }
 </SCRIPT>
 
+DNS records
 % my @records; if ( @records = $svc_domain->domain_record ) { 
 
   <% include('/elements/table-grid.html') %>
 % my @records; if ( @records = $svc_domain->domain_record ) { 
 
   <% include('/elements/table-grid.html') %>
@@ -96,7 +139,6 @@ Service #<% $svcnum %>
 % } 
 
 % if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice') ) {
 % } 
 
 % if ( $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice') ) {
-    <BR>
     <FORM METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
       <INPUT TYPE="text" NAME="reczone"> 
     <FORM METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
       <INPUT TYPE="text" NAME="reczone"> 
@@ -110,16 +152,12 @@ Service #<% $svcnum %>
       <INPUT TYPE="submit" VALUE="Add record">
     </FORM>
 
       <INPUT TYPE="submit" VALUE="Add record">
     </FORM>
 
-    <BR><BR>
-    or
-    <BR><BR>
-
     <FORM NAME="SlaveForm" METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
 %     if ( @records ) { 
          Delete all records and 
 %     } 
     <FORM NAME="SlaveForm" METHOD="POST" ACTION="<%$p%>edit/process/domain_record.cgi">
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
 %     if ( @records ) { 
          Delete all records and 
 %     } 
-      Slave from nameserver IP 
+      Or slave from nameserver IP 
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
       <INPUT TYPE="hidden" NAME="reczone" VALUE="@"> 
       <INPUT TYPE="hidden" NAME="recaf" VALUE="IN">
       <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%$svcnum%>">
       <INPUT TYPE="hidden" NAME="reczone" VALUE="@"> 
       <INPUT TYPE="hidden" NAME="recaf" VALUE="IN">
@@ -129,8 +167,30 @@ Service #<% $svcnum %>
     </FORM>
 
 % }
     </FORM>
 
 % }
+<BR>
+
+% my ( $settings, $defaults ) = $svc_domain->export_getsettings;
+% if ( keys %$settings ) {
+
+%# XXX a way to label this "Communigate pro settings".. just a config maybe
+  External settings
+  <% ntable('#cccccc',2) %>
+
+%   foreach my $key ( keys %$settings ) {
+      <TR>
+        <TD ALIGN="right"><% $key |h %></TD>
+        <TD BGCOLOR="<% $defaults->{$key} ? '#eeeeee' : '#ffffff' %>">
+          <% $defaults->{$key} ? '<I>' : '<B>' %>
+          <% $settings->{$key} |h %>
+          <% $defaults->{$key} ? '</I>' : '</B>' %>
+        </TD>
+      </TR>
+%   }
 
 
-<BR><BR>
+  </TABLE>
+  <BR>
+
+% }
 
 <% joblisting({'svcnum'=>$svcnum}, 1) %>
 
 
 <% joblisting({'svcnum'=>$svcnum}, 1) %>
 
@@ -140,6 +200,8 @@ Service #<% $svcnum %>
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
 
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('View customer services');
 
+my $conf = new FS::Conf;
+
 my($query) = $cgi->keywords;
 $query =~ /^(\d+)$/;
 my $svcnum = $1;
 my($query) = $cgi->keywords;
 $query =~ /^(\d+)$/;
 my $svcnum = $1;