[freeside-commits] branch master updated. c422010521a7c09673a8d4d0068d3fd482dd2dbc

Jonathan Prykop jonathan at 420.am
Tue May 5 13:50:06 PDT 2015


The branch, master has been updated
       via  c422010521a7c09673a8d4d0068d3fd482dd2dbc (commit)
      from  c684757e24c7c64b73a6d636b2d25997b3511053 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c422010521a7c09673a8d4d0068d3fd482dd2dbc
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Tue May 5 15:49:51 2015 -0500

    RT#34289: Flag service fields as mandatory

diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 1da30cb..ca26074 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -142,56 +142,53 @@ sub insert {
   # add part_svc_column records
 
   my $svcdb = $self->svcdb;
-#  my @rows = map { /^${svcdb}__(.*)$/; $1 }
-#    grep ! /_flag$/,
-#      grep /^${svcdb}__/,
-#        fields('part_svc');
-  foreach my $field (
-    grep { $_ ne 'svcnum'
-           && ( defined( $self->getfield($svcdb.'__'.$_.'_flag') )
-                || defined($self->getfield($svcdb.'__'.$_.'_required'))
-                || $self->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
-         } (fields($svcdb), @fields)
-  ) {
-    my $part_svc_column = $self->part_svc_column($field);
-    my $previous = qsearchs('part_svc_column', {
-      'svcpart'    => $self->svcpart,
-      'columnname' => $field,
-    } );
+  foreach my $field (fields($svcdb), @fields) {
+    next if $field eq 'svcnum';
+    my $prefix = $svcdb.'__';
+    if ( defined( $self->getfield($prefix.$_.'_flag'))
+      or defined($self->getfield($prefix.$_.'_required'))
+      or length($self->getfield($prefix.$_.'_label'))
+    ) {
+      my $part_svc_column = $self->part_svc_column($field);
+      my $previous = qsearchs('part_svc_column', {
+        'svcpart'    => $self->svcpart,
+        'columnname' => $field,
+      } );
 
-    my $flag  = $self->getfield($svcdb.'__'.$field.'_flag');
-    my $label = $self->getfield($svcdb.'__'.$field.'_label');
-    my $required = $self->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
-    if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
-
-      if ( uc($flag) =~ /^([A-Z])$/ ) {
-        my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
-                     || sub { shift };
-        $part_svc_column->setfield('columnflag', $1);
-        $part_svc_column->setfield('columnvalue',
-          &$parser($self->getfield($svcdb.'__'.$field))
-        );
-      }
+      my $flag  = $self->getfield($prefix.$field.'_flag');
+      my $label = $self->getfield($prefix.$field.'_label');
+      my $required = $self->getfield($prefix.$field.'_required') ? 'Y' : '';
+      if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
 
-      $part_svc_column->setfield('columnlabel', $label)
-        if $label !~ /^\s*$/;
+        if ( uc($flag) =~ /^([A-Z])$/ ) {
+          my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+                       || sub { shift };
+          $part_svc_column->setfield('columnflag', $1);
+          $part_svc_column->setfield('columnvalue',
+            &$parser($self->getfield($prefix.$field))
+          );
+        }
+
+        $part_svc_column->setfield('columnlabel', $label)
+          if $label !~ /^\s*$/;
 
-      $part_svc_column->setfield('required', $required);
+        $part_svc_column->setfield('required', $required);
+
+        if ( $previous ) {
+          $error = $part_svc_column->replace($previous);
+        } else {
+          $error = $part_svc_column->insert;
+        }
 
-      if ( $previous ) {
-        $error = $part_svc_column->replace($previous);
       } else {
-        $error = $part_svc_column->insert;
+        $error = $previous ? $previous->delete : '';
+      }
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
       }
 
-    } else {
-      $error = $previous ? $previous->delete : '';
-    }
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return $error;
     }
-
   }
 
   # add export_svc records
@@ -284,54 +281,54 @@ sub replace {
    # maintain part_svc_column records
 
     my $svcdb = $new->svcdb;
-    foreach my $field (
-      grep { $_ ne 'svcnum'
-             && ( defined( $new->getfield($svcdb.'__'.$_.'_flag') )
-                  || defined($new->getfield($svcdb.'__'.$_.'_required'))
-                  || $new->getfield($svcdb.'__'.$_.'_label') !~ /^\s*$/ )
-           } (fields($svcdb), at fields)
-    ) {
-
-      my $part_svc_column = $new->part_svc_column($field);
-      my $previous = qsearchs('part_svc_column', {
-        'svcpart'    => $new->svcpart,
-        'columnname' => $field,
-      } );
-
-      my $flag  = $new->getfield($svcdb.'__'.$field.'_flag');
-      my $label = $new->getfield($svcdb.'__'.$field.'_label');
-      my $required = $new->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
+    foreach my $field (fields($svcdb), at fields) {
+      next if $field eq 'svcnum';
+      my $prefix = $svcdb.'__';
+      if ( defined( $new->getfield($prefix.$_.'_flag'))
+        or defined($new->getfield($prefix.$_.'_required'))
+        or length($new->getfield($prefix.$_.'_label'))
+      ) {
+        my $part_svc_column = $new->part_svc_column($field);
+        my $previous = qsearchs('part_svc_column', {
+          'svcpart'    => $new->svcpart,
+          'columnname' => $field,
+        } );
+
+        my $flag  = $new->getfield($svcdb.'__'.$field.'_flag');
+        my $label = $new->getfield($svcdb.'__'.$field.'_label');
+        my $required = $new->getfield($svcdb.'__'.$field.'_required') ? 'Y' : '';
  
-      if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
-
-        if ( uc($flag) =~ /^([A-Z])$/ ) {
-          $part_svc_column->setfield('columnflag', $1);
-          my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
-                     || sub { shift };
-          $part_svc_column->setfield('columnvalue',
-            &$parser($new->getfield($svcdb.'__'.$field))
-          );
-        } else {
-          $part_svc_column->setfield('columnflag',  '');
-          $part_svc_column->setfield('columnvalue', '');
-        }
+        if ( uc($flag) =~ /^([A-Z])$/ || $label !~ /^\s*$/ ) {
+
+          if ( uc($flag) =~ /^([A-Z])$/ ) {
+            $part_svc_column->setfield('columnflag', $1);
+            my $parser = FS::part_svc->svc_table_fields($svcdb)->{$field}->{parse}
+                       || sub { shift };
+            $part_svc_column->setfield('columnvalue',
+              &$parser($new->getfield($svcdb.'__'.$field))
+            );
+          } else {
+            $part_svc_column->setfield('columnflag',  '');
+            $part_svc_column->setfield('columnvalue', '');
+          }
 
-        $part_svc_column->setfield('columnlabel', $label)
-          if $label !~ /^\s*$/;
+          $part_svc_column->setfield('columnlabel', $label)
+            if $label !~ /^\s*$/;
 
-        $part_svc_column->setfield('required', $required);
+          $part_svc_column->setfield('required', $required);
 
-        if ( $previous ) {
-          $error = $part_svc_column->replace($previous);
+          if ( $previous ) {
+            $error = $part_svc_column->replace($previous);
+          } else {
+            $error = $part_svc_column->insert;
+          }
         } else {
-          $error = $part_svc_column->insert;
+          $error = $previous ? $previous->delete : '';
+        }
+        if ( $error ) {
+          $dbh->rollback if $oldAutoCommit;
+          return $error;
         }
-      } else {
-        $error = $previous ? $previous->delete : '';
-      }
-      if ( $error ) {
-        $dbh->rollback if $oldAutoCommit;
-        return $error;
       }
     }
 
@@ -605,6 +602,7 @@ sub svc_x {
 =cut
 
 my $svc_defs;
+my $svc_info;
 sub _svc_defs {
 
   return $svc_defs if $svc_defs; #cache
@@ -659,7 +657,14 @@ sub _svc_defs {
     sort { $info{$a}->{'display_weight'} <=> $info{$b}->{'display_weight'} }
     keys %info,
   ;
-  
+
+  tie my %svc_info, 'Tie::IxHash',
+    map  { $_ => $info{$_} }
+    sort { $info{$a}->{'display_weight'} <=> $info{$b}->{'display_weight'} }
+    keys %info,
+  ;
+    
+  $svc_info = \%svc_info; #access via svc_table_info  
   $svc_defs = \%svc_defs; #cache
   
 }
@@ -735,6 +740,27 @@ sub svc_table_fields {
   $def;
 }
 
+=item svc_table_info TABLE
+
+Returns table_info for TABLE from cache, or empty
+hashref if none is found.
+
+Caution:  caches table_info for ALL services when run;
+access a service's table_info directly unless you know
+you're loading them all.
+
+Caution:  does not standardize fields into hashrefs;
+use L</svc_table_fields> to access fields.
+
+=cut
+
+sub svc_table_info {
+  my $class = shift;
+  my $table = shift;
+  $class->_svc_defs; #creates cache if needed
+  return $svc_info->{$table} || {};
+}
+
 =back
 
 =head1 SUBROUTINES
diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm
index 8d3b535..9d9e50f 100644
--- a/FS/FS/svc_Common.pm
+++ b/FS/FS/svc_Common.pm
@@ -167,28 +167,30 @@ sub check {
   my $required = {};
   my $labels = {};
   my $tinfo = $self->can('table_info') ? $self->table_info : {};
-  my $fields = $tinfo->{'fields'} || {};
-  foreach my $field (keys %$fields) {
-    if (ref($fields->{$field}) && $fields->{$field}->{'required'}) {
-      $required->{$field} = 1;
-      $labels->{$field} = $fields->{$field}->{'label'};
+  if ($tinfo->{'manual_require'}) {
+    my $fields = $tinfo->{'fields'} || {};
+    foreach my $field (keys %$fields) {
+      if (ref($fields->{$field}) && $fields->{$field}->{'required'}) {
+        $required->{$field} = 1;
+        $labels->{$field} = $fields->{$field}->{'label'};
+      }
     }
-  }
-  # add fields marked as required in database
-  foreach my $column (
-    qsearch('part_svc_column',{
-      'svcpart' => $self->svcpart,
-      'required' => 'Y'
-    })
-  ) {
-    $required->{$column->columnname} = 1;
-    $labels->{$column->columnname} = $column->columnlabel;
-  }
-  # do the actual checking
-  foreach my $field (keys %$required) {
-    unless ($self->$field) {
-      my $name = $labels->{$field} || $field;
-      return "Field $name is required\n"
+    # add fields marked as required in database
+    foreach my $column (
+      qsearch('part_svc_column',{
+        'svcpart' => $self->svcpart,
+        'required' => 'Y'
+      })
+    ) {
+      $required->{$column->columnname} = 1;
+      $labels->{$column->columnname} = $column->columnlabel;
+    }
+    # do the actual checking
+    foreach my $field (keys %$required) {
+      unless (length($self->get($field)) > 0) {
+        my $name = $labels->{$field} || $field;
+        return "Field $name is required\n"
+      }
     }
   }
 
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 790ac34..0181b1e 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -260,6 +260,7 @@ sub table_info {
     'display_weight' => 10,
     'cancel_weight'  => 50, 
     'ip_field' => 'slipip',
+    'manual_require' => 1,
     'fields' => {
         'dir'       => 'Home directory',
         'uid'       => {
diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm
index e295f73..38594f0 100755
--- a/FS/FS/svc_broadband.pm
+++ b/FS/FS/svc_broadband.pm
@@ -103,6 +103,7 @@ sub table_info {
     'display_weight' => 50,
     'cancel_weight'  => 70,
     'ip_field' => 'ip_addr',
+    'manual_require' => 1,
     'fields' => {
       'svcnum'      => 'Service',
       'description' => 'Descriptive label',
diff --git a/FS/FS/svc_dish.pm b/FS/FS/svc_dish.pm
index 5c9e217..2d249d1 100644
--- a/FS/FS/svc_dish.pm
+++ b/FS/FS/svc_dish.pm
@@ -63,9 +63,10 @@ sub table_info {
     'name'           => 'Dish service',
     'display_weight' => 58,
     'cancel_weight'  => 85,
+    'manual_require' => 1,
     'fields' => {
       'svcnum'    =>  { label => 'Service' },
-      'acctnum'   =>  { label => 'DISH account#', %opts },
+      'acctnum'   =>  { label => 'DISH account#', required => 1, %opts },
       'installdate' => { label => 'Install date', %opts },
       'note'      => { label => 'Installation notes', %opts },
     }
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index 78556cf..b01d673 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -134,10 +134,7 @@ sub table_info {
     'display_weight' => 20,
     'cancel_weight'  => 60,
     'fields' => {
-      'domain' => {
-                  label => 'Domain',
-                  required => 1,
-                },
+      'domain' => 'Domain',
       'parent_svcnum' => { 
                          label => 'Parent domain / Communigate administrator domain',
                          type  => 'select',
diff --git a/FS/FS/svc_hardware.pm b/FS/FS/svc_hardware.pm
index 16a5ea9..dbb8b68 100644
--- a/FS/FS/svc_hardware.pm
+++ b/FS/FS/svc_hardware.pm
@@ -75,6 +75,7 @@ sub table_info {
     'name_plural'    => 'Hardware',
     'display_weight' => 59,
     'cancel_weight'  => 86,
+    'manual_require' => 1,
     'fields' => {
       'svcnum'    => { label => 'Service' },
       'typenum'   => { label => 'Device type',
@@ -83,6 +84,7 @@ sub table_info {
                        disable_fixed     => 1,
                        disable_default   => 1,
                        disable_inventory => 1,
+                       required => 1,
                      },
       'serial'    => { label => 'Serial number', %opts },
       'hw_addr'   => { label => 'Hardware address', %opts },
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index 76df820..7b02994 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -418,6 +418,7 @@ Example:
 %			'value' => $opt{curr_value},
 %			'label' => $label,
 %			'noinit' => $f->{noinit},
+%           'required' => $f->{'required'},
 %		}
 %	);
 %     }
diff --git a/httemplate/edit/elements/part_svc_column.html b/httemplate/edit/elements/part_svc_column.html
index 23a6deb..bc679e5 100644
--- a/httemplate/edit/elements/part_svc_column.html
+++ b/httemplate/edit/elements/part_svc_column.html
@@ -76,7 +76,7 @@ my %communigate_fields = (
     <TH BGCOLOR="#cccccc">Field</TH>
     <TH BGCOLOR="#cccccc">Label</TH>
     <TH BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>
-    <TH BGCOLOR="#cccccc">Required?</TH>
+    <TH BGCOLOR="#cccccc"><% $manual_require ? 'Required?' : '' %></TH>
   </TR>
 % $part_svc->set('svcpart' => $opt{'clone'}) if $opt{'clone'}; # for now
 % my $i = 0;
@@ -211,7 +211,9 @@ my %communigate_fields = (
 %   }
     </TD>
     <TD>
-%   if (!$def->{'type'} || !(grep {$_ eq $def->{'type'}} ('checkbox','disabled'))) {
+%   if ($manual_require && 
+%       (!$def->{'type'} || !(grep {$_ eq $def->{'type'}} ('checkbox','disabled')))
+%   ) {
       <INPUT ID="<% $name.'_required' %>" TYPE="checkbox" NAME="<% $svcdb %>__<% $field %>_required" VALUE="Y" 
         <% ($part_svc_column->required || $def->{'required'}) ? 'CHECKED' : '' %> 
         <% $def->{'required'} ? 'DISABLED' : '' %>
@@ -309,4 +311,5 @@ if ( $svcdb eq 'svc_acct'
 }
 
 my @defs = map { FS::part_svc->svc_table_fields($svcdb)->{$_} } @fields;
+my $manual_require = FS::part_svc->svc_table_info($svcdb)->{'manual_require'};
 </%init>
diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html
index 97b630f..a4e345e 100644
--- a/httemplate/edit/elements/svc_Common.html
+++ b/httemplate/edit/elements/svc_Common.html
@@ -102,6 +102,9 @@
                    my $columndef = $part_svc->part_svc_column($f->{'field'});
                    my $flag = $columndef->columnflag;
 
+                   $f->{'required'} = 1
+                     if $columndef->required;
+
                    if ( $flag eq 'F' ) { #fixed
                      $f->{'value'} = $columndef->columnvalue;
                      if (length($columndef->columnvalue)) {
diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi
index 2c694a8..31678a9 100755
--- a/httemplate/edit/svc_acct.cgi
+++ b/httemplate/edit/svc_acct.cgi
@@ -30,8 +30,9 @@
   <TD BGCOLOR="#eeeeee"><% $part_svc->svc %></TD>
 </TR>
 
-<TR>
-  <TD ALIGN="right"><% mt('Username') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Username'),
+     'required' => $part_svc->part_svc_column('username')->required ) %>
 % if ( $svcnum && $conf->exists('svc_acct-no_edit_username') ) {
     <TD BGCOLOR="#eeeeee"><% $svc_acct->username() %></TD>
     <INPUT TYPE="hidden" NAME="username" VALUE="<% $username %>">
@@ -43,9 +44,10 @@
 </TR>
 
 %if ( $part_svc->part_svc_column('_password')->columnflag ne 'F' ) {
-<TR>
 % #XXX eventually should require "Edit Password" ACL
-  <TD ALIGN="right"><% mt('Password') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Password'),
+     'required' => $part_svc->part_svc_column('_password')->required ) %>
   <TD>
     <INPUT TYPE="text" ID="clear_password" NAME="clear_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $pmax %>>
     <& /elements/random_pass.html, 'clear_password' &>
@@ -60,8 +62,9 @@
 %if ( $conf->exists('security_phrase') 
 %  && $part_svc->part_svc_column('sec_phrase')->columnflag ne 'F' ) {
 
-  <TR>
-    <TD ALIGN="right"><% mt('Security phrase') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Security phrase'),
+     'required' => $part_svc->part_svc_column('sec_phrase')->required ) %>
     <TD>
       <INPUT TYPE="text" NAME="sec_phrase" VALUE="<% $sec_phrase %>" SIZE=32>
       (<% mt('for forgotten passwords') |h %>)
@@ -97,8 +100,9 @@
 %                                                )
 %                );
 
-  <TR>
-    <TD ALIGN="right"><% mt('Domain') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Domain'),
+     'required' => $part_svc->part_svc_column('domsvc')->required ) %>
     <TD>
       <SELECT NAME="domsvc" SIZE=1>
 % foreach my $svcnum (
@@ -143,8 +147,9 @@
   <INPUT TYPE="hidden" NAME="popnum" VALUE="<% $popnum %>">
 % } else { 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Access number') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Access number'),
+     'required' => $part_svc->part_svc_column('popnum')->required ) %>
     <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
   </TR>
 % } 
@@ -156,6 +161,7 @@
          'curr_value' => $svc_acct->sectornum,
          #'part_svc'   => $part_svc,
          #'cust_pkg'   => $cust_pkg,
+         'required'   => $part_svc->part_svc_column('sectornum')->required,
     &>
 %} else {
     <INPUT TYPE="hidden" NAME="sectornum" VALUE="<% $svc_acct->sectornum %>">
@@ -176,6 +182,9 @@
 %  
 % if ( length($svc_acct->$xid()) ) { 
 
+<% include('/elements/tr-td-label.html',
+     'label'    => uc($xid),
+     'required' => $part_svc->part_svc_column($xid)->required ) %>
       <TR>
         <TD ALIGN="right"><% uc($xid) %></TD>
           <TD BGCOLOR="#eeeeee"><% $svc_acct->$xid() %></TD>
@@ -187,8 +196,9 @@
     <INPUT TYPE="hidden" NAME="<% $xid %>" VALUE="<% $svc_acct->$xid() %>">
 % } else { 
   
-    <TR>
-      <TD ALIGN="right"><% uc($xid) %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => uc($xid),
+     'required' => $part_svc->part_svc_column($xid)->required ) %>
       <TD>
         <INPUT TYPE="text" NAME="<% $xid %>" SIZE=8 MAXLENGTH=6 VALUE="<% $svc_acct->$xid() %>">
       </TD>
@@ -205,8 +215,9 @@
 % } else { 
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Real Name') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Real Name'),
+     'required' => $part_svc->part_svc_column('finger')->required ) %>
     <TD>
       <INPUT TYPE="text" NAME="finger" VALUE="<% $svc_acct->finger %>">
     </TD>
@@ -223,8 +234,9 @@
 % } else {
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Home directory') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Home directory'),
+     'required' => $part_svc->part_svc_column('dir')->required ) %>
     <TD><INPUT TYPE="text" NAME="dir" VALUE="<% $svc_acct->dir %>"></TD>
   </TR>
 % } 
@@ -240,8 +252,9 @@
 % } else { 
 
 
-  <TR>
-    <TD ALIGN="right"><% mt('Shell') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('Shell'),
+     'required' => $part_svc->part_svc_column('shell')->required ) %>
     <TD>
       <SELECT NAME="shell" SIZE=1>
 %
@@ -269,7 +282,9 @@
 %   # (should we show this if slipip is fixed?)
 <& /elements/tr-select-router_block_ip.html, 
   'object' => $svc_acct,
-  'ip_field' => 'slipip'
+  'ip_field' => 'slipip',
+  'required' => $part_svc->part_svc_column('routernum')->required,
+  'ip_addr_required' => $part_svc->part_svc_column('slipip')->required,
 &>
 % } else {
 %   # don't expose these to the user--they're only useful in the other case
@@ -278,8 +293,9 @@
 %   if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { 
     <INPUT TYPE="hidden" NAME="slipip" VALUE="<% $svc_acct->slipip %>">
 %   } else { 
-    <TR>
-      <TD ALIGN="right"><% mt('IP') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('IP'),
+     'required' => $part_svc->part_svc_column('slipip')->required ) %>
       <TD><INPUT TYPE="text" NAME="slipip" VALUE="<% $svc_acct->slipip %>"></TD>
     </TR>
 %   }
@@ -324,8 +340,9 @@
 % } 
 
 
-<TR>
-  <TD ALIGN="right"><% mt('RADIUS groups') |h %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => mt('RADIUS groups'),
+     'required' => $part_svc->part_svc_column('usergroup')->required ) %>
 % if ( $part_svc_usergroup->columnflag eq 'F' ) { 
     <TD BGCOLOR="#eeeeee"><% join('<BR>', @groupnames) %></TD>
 % } else { 
diff --git a/httemplate/edit/svc_acct/communigate.html b/httemplate/edit/svc_acct/communigate.html
index 6370a54..370bfb0 100644
--- a/httemplate/edit/svc_acct/communigate.html
+++ b/httemplate/edit/svc_acct/communigate.html
@@ -47,8 +47,9 @@
   <INPUT TYPE="hidden" NAME="quota" VALUE="<% $svc_acct->quota %>">
 % } else {
 %   my $quota_label = $communigate ? 'Mail storage limit' : 'Quota';
-    <TR>
-      <TD ALIGN="right"><% $quota_label %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $quota_label,
+     'required' => $part_svc->part_svc_column('quota')->required ) %>
       <TD><INPUT TYPE="text" NAME="quota" VALUE="<% $svc_acct->quota %>"></TD>
     </TR>
 % }
diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi
index 1b85460..81c694a 100644
--- a/httemplate/edit/svc_broadband.cgi
+++ b/httemplate/edit/svc_broadband.cgi
@@ -102,7 +102,16 @@ END
 my @fields = (
   qw( description speed_down speed_up ),
   { field=>'sectornum', type=>'select-tower_sector', },
-  { field=>'routernum', type=>'select-router_block_ip' },
+  { field=>'routernum', type=>'select-router_block_ip', 
+    include_opt_callback => sub { 
+      my $svc_broadband = shift;
+      my $part_svc = $svc_broadband->part_svc;
+      return () unless $part_svc; #sanity check
+      my $col = $part_svc->part_svc_column('ip_addr');
+      return () unless $col; #sanity check
+      return ('ip_addr_required' => $col->required);
+    },
+  },
   { field=>'mac_addr' , type=>'input-mac_addr' },
   qw(
       latitude longitude altitude
diff --git a/httemplate/elements/tr-input-date-field.html b/httemplate/elements/tr-input-date-field.html
index ff98551..f2a570b 100644
--- a/httemplate/elements/tr-input-date-field.html
+++ b/httemplate/elements/tr-input-date-field.html
@@ -13,6 +13,7 @@ Example:
           'usedatetime' => 1, #use DateTime->strftime to format the date
                               # instead of Date::Format->time2str
           'noinit'      => 1,          #first one on the page is enough
+          'required'    => 1,
        },
   &>
 
@@ -24,8 +25,9 @@ Example:
 <SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/calendar-setup.js"></SCRIPT>
 % }
 
-<TR>
-  <TD ALIGN="right"><% $label %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $label,
+     'required' => $required ) %>
   <TD COLSPAN=<% $colspan %>>
     <INPUT TYPE="text" NAME="<% $name %>" ID="<% $name %>_text" VALUE="<% $value %>">
     <IMG SRC="<%$fsurl%>images/calendar.png" ID="<% $name  %>_button" STYLE="cursor: pointer" TITLE="<% mt('Select date') |h %>">
@@ -48,7 +50,7 @@ Example:
 
 <%init>
 
-my($name, $value, $label, $format, $usedatetime, $noinit, $colspan);
+my($name, $value, $label, $format, $usedatetime, $noinit, $colspan, $required);
 if ( ref($_[0]) ) {
   my $opt = shift;
   $name        = $opt->{'name'};
@@ -58,6 +60,7 @@ if ( ref($_[0]) ) {
   $usedatetime = $opt->{'usedatetime'};
   $noinit      = $opt->{'noinit'};
   $colspan     = $opt->{'colspan'} || 1;
+  $required    = $opt->{'required'};
 } else {
   ($name, $value, $label, $format, $usedatetime) = @_;
   $colspan = 1;
diff --git a/httemplate/elements/tr-select-hardware_type.html b/httemplate/elements/tr-select-hardware_type.html
index c306641..b51afc0 100644
--- a/httemplate/elements/tr-select-hardware_type.html
+++ b/httemplate/elements/tr-select-hardware_type.html
@@ -1,5 +1,6 @@
-<TR>
-  <TD ALIGN="right"><% $opt{'label'} || 'Device type: ' %></TD>
+<% include('/elements/tr-td-label.html',
+     'label'    => $opt{'label'} || 'Device type: ',
+     'required' => $opt{'required'} ) %>
   <TD><% include('select-hardware_type.html', %opt) %></TD>
 </TR>
 
diff --git a/httemplate/elements/tr-select-router_block_ip.html b/httemplate/elements/tr-select-router_block_ip.html
index 11f7c48..ee13568 100644
--- a/httemplate/elements/tr-select-router_block_ip.html
+++ b/httemplate/elements/tr-select-router_block_ip.html
@@ -30,7 +30,7 @@ function clearhint_ip_addr (what) {
     what.value = '';
 }
 </script>
-<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router') &>
+<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router'), required => $opt{'required'} &>
 <td>
   <& /elements/select-tiered.html, prefix => 'router_', tiers => [
   {
@@ -56,9 +56,9 @@ function clearhint_ip_addr (what) {
 ]
 &>
 </td></tr>
-<& /elements/tr-td-label.html, label => 'IP address' &>
+<& /elements/tr-td-label.html, label => 'IP address', required => $opt{'ip_addr_required'} &>
 <td>
-% warn Dumper \%fixed;
+% #warn Dumper \%fixed;
 % if ( exists $fixed{$ip_field} ) {
   <input type="hidden" id="input_ip_addr" name="<% $ip_field %>" 
     value="<% $opt{'ip_addr'} |h%>"><% $opt{'ip_addr'} || '' %>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/part_svc.pm                                  |  196 +++++++++++---------
 FS/FS/svc_Common.pm                                |   44 ++---
 FS/FS/svc_acct.pm                                  |    1 +
 FS/FS/svc_broadband.pm                             |    1 +
 FS/FS/svc_dish.pm                                  |    3 +-
 FS/FS/svc_domain.pm                                |    5 +-
 FS/FS/svc_hardware.pm                              |    2 +
 httemplate/edit/elements/edit.html                 |    1 +
 httemplate/edit/elements/part_svc_column.html      |    7 +-
 httemplate/edit/elements/svc_Common.html           |    3 +
 httemplate/edit/svc_acct.cgi                       |   63 ++++---
 httemplate/edit/svc_acct/communigate.html          |    5 +-
 httemplate/edit/svc_broadband.cgi                  |   11 +-
 httemplate/elements/tr-input-date-field.html       |    9 +-
 httemplate/elements/tr-select-hardware_type.html   |    5 +-
 httemplate/elements/tr-select-router_block_ip.html |    6 +-
 16 files changed, 215 insertions(+), 147 deletions(-)




More information about the freeside-commits mailing list