[freeside-commits] branch master updated. 83f70978574fef3401020cb11cf651d12c139b3b

Ivan ivan at 420.am
Sat Mar 24 18:47:12 PDT 2012


The branch, master has been updated
       via  83f70978574fef3401020cb11cf651d12c139b3b (commit)
      from  798cf217a0d14520c5648560ef8a3095ffcfad27 (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 83f70978574fef3401020cb11cf651d12c139b3b
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Sat Mar 24 18:47:07 2012 -0700

    better display/edit of contacts on customer view, RT#16819

diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 069d5b6..7d1a156 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -8,6 +8,7 @@ use base qw( FS::cust_main::Packages FS::cust_main::Status
              FS::cust_main::Billing_Discount
              FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
              FS::geocode_Mixin
+             FS::o2m_Common
              FS::Record
            );
 use vars qw( $DEBUG $me $conf
diff --git a/httemplate/edit/cust_main-contacts.html b/httemplate/edit/cust_main-contacts.html
new file mode 100644
index 0000000..bae58bd
--- /dev/null
+++ b/httemplate/edit/cust_main-contacts.html
@@ -0,0 +1,100 @@
+<% include('elements/edit.html',
+     'name_singular'   => 'customer contacts', #yes, we're editing all of them
+     'table'           => 'cust_main',
+     'post_url'       => popurl(1). 'process/cust_main-contacts.html',
+     'labels'          => { 'custnum'     => ' ', #XXX supress this line entirely, its being redundant
+                            'contactnum'  => 'Contact',
+                            #'locationnum' => ' ',
+                          },
+     'fields'          => [
+       { 'field'             => 'contactnum',
+         'type'              => 'contact',
+         'colspan'           => 6,
+         'm2m_method'        => 'cust_contact',
+         'm2m_dstcol'        => 'contactnum',   
+         'm2_label'          => 'Contact',
+         'm2_error_callback' => $m2_error_callback,
+       },
+     ],
+     #'new_callback'    => $new_callback,
+     #'edit_callback'   => $edit_callback,
+     #'error_callback'  => $error_callback,
+     'agent_virt'      => 1,
+     'menubar'          => [], #remove "view all" link
+
+     #XXX it would be nice if this could instead be after the error but before
+     # the table
+     'html_init'        => include('/elements/small_custview.html',
+                                     $custnum,
+                                     $conf->config('countrydefault') || 'US',
+                                     1, #no balance
+                                  ),
+   )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = new FS::Conf;
+
+my $custnum;
+if ( $cgi->param('error') ) {
+  $custnum = scalar($cgi->param('custnum'));
+
+  die "access denied"
+    unless $curuser->access_right(($custnum ? 'Edit' : 'New'). ' customer'); #contacts?
+
+} elsif ( $cgi->keywords ) { #editing
+  $custnum = ($cgi->keywords)[0];
+
+  die "access denied"
+    unless $curuser->access_right('Edit customer');
+
+} else { #new customer
+
+  #this doesn't really work here, we're an edit only
+  die "guru meditation #32";
+
+  die "access denied"
+    unless $curuser->access_right('New customer');
+
+}
+
+#my $new_callback = sub {
+#  my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $edit_callback = sub {
+# my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $error_callback = sub {
+#  my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+my $m2_error_callback = sub {
+  my($cgi, $object) = @_;
+
+  #process_o2m fields in process/cust_main-contacts.html
+  my @fields = qw( first last title comment );
+  my @gfields = ( '', map "_$_", @fields );
+
+  map {
+        if ( /^contactnum(\d+)$/ ) {
+          my $num = $1;
+          if ( grep $cgi->param("contactnum$num$_"), @gfields ) {
+            my $x = new FS::contact {
+              'contactnum' => scalar($cgi->param("contactnum$num")),
+              map { $_ => scalar($cgi->param("contactnum${num}_$_")) } @fields,
+            };
+            $x;
+          } else {
+            ();
+          }
+        } else {
+          ();
+        }
+      }
+      $cgi->param;
+};
+
+</%init>
diff --git a/httemplate/edit/process/cust_main-contacts.html b/httemplate/edit/process/cust_main-contacts.html
new file mode 100644
index 0000000..ed874a5
--- /dev/null
+++ b/httemplate/edit/process/cust_main-contacts.html
@@ -0,0 +1,20 @@
+<% include('elements/process.html',
+     'table'          => 'cust_main',
+     'error_redirect' => popurl(3). 'edit/cust_main-contacts.html?',
+     'agent_virt'     => 1,
+     'skip_process'   => 1, #we don't want to make any changes to cust_main
+     'process_o2m' => {
+       'table'  => 'contact',
+       'fields' => \@contact_fields,
+     },
+     'redirect' => popurl(3). 'view/cust_main.cgi?',
+   )
+%>
+<%init>
+
+my @contact_fields = qw( classnum first last title comment emailaddress );
+foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
+  push @contact_fields, 'phonetypenum'.$phone_type->phonetypenum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 636bae0..12b3bd9 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -62,6 +62,10 @@ Example:
                       'fields' => [qw( fieldname fieldname2 )],
                     },
 
+   'skip_process' => 0, #boolean, if set true, will skip the main table
+                        #add/edit processing and only run any linked table
+                        #process_ items
+
    #checks CGI params and whatever else before much else runs
    #return an error string or empty for no error
    'precheck_callback' => sub { my( $cgi ) = @_; },
@@ -204,62 +208,71 @@ my $new;
 my $new_pkey = '';
 foreach my $value ( @values ) {
 
-  $new = $class->new( \%hash );
+  if ($opt{'skip_process'}) {
+
+    $new = $old;
+    $new_pkey = $old_pkey;
+
+  } else {
+
+    $new = $class->new( \%hash );
 
-  $new->$bfield($value) if $bfield;
+    $new->$bfield($value) if $bfield;
 
-  if ($old && exists($opt{'copy_on_empty'})) {
-    foreach my $field (@{$opt{'copy_on_empty'}}) {
-      $new->set($field, $old->get($field))
-        unless scalar($cgi->param($field));
+    if ($old && exists($opt{'copy_on_empty'})) {
+      foreach my $field (@{$opt{'copy_on_empty'}}) {
+        $new->set($field, $old->get($field))
+          unless scalar($cgi->param($field));
+      }
     }
-  }
 
-  if ( $opt{'agent_virt'} ) {
+    if ( $opt{'agent_virt'} ) {
 
-    if ( ! $new->agentnum
-         && (    ! $opt{'agent_null_right'}
-              || ! $curuser->access_right($opt{'agent_null_right'})
-            )
-       )
-    {
+      if ( ! $new->agentnum
+           && (    ! $opt{'agent_null_right'}
+                || ! $curuser->access_right($opt{'agent_null_right'})
+              )
+         )
+      {
 
-      $error ||= 'Select an agent';
+        $error ||= 'Select an agent';
 
-    } else {
+      } else {
 
-      die "illegal agentnum"
-        unless $curuser->agentnums_href->{$new->agentnum}
-            or $curuser->access_right('View customers of all agents')
-            or $opt{'agent_null_right'}
-               && ! $new->agentnum
-               && $curuser->access_right($opt{'agent_null_right'});
+        die "illegal agentnum"
+          unless $curuser->agentnums_href->{$new->agentnum}
+              or $curuser->access_right('View customers of all agents')
+              or $opt{'agent_null_right'}
+                 && ! $new->agentnum
+                 && $curuser->access_right($opt{'agent_null_right'});
 
-    }
+      }
 
-  }
+    }
 
-  $error ||= $new->check;
+    $error ||= $new->check;
 
-  my @args = ();
-  if ( !$error && $opt{'args_callback'} ) {
-    @args = &{ $opt{'args_callback'} }( $cgi, $new );
-  }
+    my @args = ();
+    if ( !$error && $opt{'args_callback'} ) {
+      @args = &{ $opt{'args_callback'} }( $cgi, $new );
+    }
 
-  if ( !$error && $opt{'debug'} ) {
-    warn "$me updating record in $table table using $class class\n";
-    warn Dumper(\%hash);
-    warn "with args: \n". Dumper(\@args) if @args;
-  }
+    if ( !$error && $opt{'debug'} ) {
+      warn "$me updating record in $table table using $class class\n";
+      warn Dumper(\%hash);
+      warn "with args: \n". Dumper(\@args) if @args;
+    }
 
-  if ( !$error ) {
-    if ( $old_pkey ) {
-      $error = $new->replace($old, @args);
-    } else {
-      $error = $new->insert(@args);
+    if ( !$error ) {
+      if ( $old_pkey ) {
+        $error = $new->replace($old, @args);
+      } else {
+        $error = $new->insert(@args);
+      }
+      $new_pkey = $new->getfield($pkey);
     }
-    $new_pkey = $new->getfield($pkey);
-  }
+
+  } #unless $opt{'skip_process'}
 
   if ( !$error && $opt{'process_m2m'} ) {
 
@@ -344,5 +357,4 @@ foreach my $value ( @values ) {
   last if $error;
 
 }
-
 </%init>
diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css
index 79c98cd..44a4a3c 100644
--- a/httemplate/elements/freeside.css
+++ b/httemplate/elements/freeside.css
@@ -115,7 +115,7 @@ a.fstab {
          padding-right:12px;*/
          padding-left:4px;
          padding-right:4px;
-         font-size:16px;
+         font-size:18px;
          font-weight:bold;
          text-decoration:none;
          overflow:visible;
@@ -148,7 +148,7 @@ a.fstabselected {
          padding-right:12px;*/
          padding-left:4px;
          padding-right:4px;
-         font-size:16px;
+         font-size:18px;
          font-weight:bold;
          text-decoration:none;
          overflow:visible;
@@ -220,6 +220,32 @@ div.fstabcontainer {
   font-weight:bold;
 }
 
+.fsinnerbox {
+  background-color:#cccccc;
+  padding:2px;
+  -moz-box-shadow:  1px 1px 2px #666666;
+  -webkit-box-shadow:  1px 1px 2px #666666;
+  box-shadow: 1px 1px 2px #666666;
+  filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2);
+}
+
+.fsinnerbox-title {
+  font-size:110%;
+  font-weight:bold;
+  background-color:#cccccc;
+  padding:2px;
+         -moz-border-radius-topleft:8px;
+         -moz-border-radius-topright:8px;
+         -webkit-border-radius-topleft:8px;
+         -webkit-border-radius-topright:8px;
+         border-radius-topleft:8px;
+         border-radius-topright:8px;
+  -moz-box-shadow:  1px 0px 1px #999999;
+  -webkit-box-shadow:  1px 0px 1px #999999;
+  box-shadow: 1px 0px 1px #999999;
+  filter: progid:DXImageTransform.Microsoft.Shadow(color='#999999', Direction=90, Strength=1);
+}
+
 .background {
   background-color:#f8f8f8;
 }
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index dcadf99..fda4db0 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -150,6 +150,11 @@ function areyousure(href, message) {
 
   </TD>
 </TR>
+<TR>
+  <TD COLSPAN = 2>
+    <& cust_main/contacts_new.html, $cust_main &>
+  </TD>
+</TR>
 </TABLE>
 
 % }
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index f1add6f..522c6db 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -1,4 +1,4 @@
-<% mt('Billing information') |h %> 
+<FONT CLASS="fsinnerbox-title"><% mt('Billing information') |h %></FONT>
 %# If we can't see the unencrypted card, then bill now is an exercise in
 %# frustration (without some sort of job queue magic to send it to a secure
 %# machine, anyway)
@@ -6,14 +6,14 @@
 %      && ! $cust_main->is_encrypted($cust_main->payinfo)
 %   ) { 
 %#  (<A HREF="<% $p %>misc/bill.cgi?<% $cust_main->custnum %>"><% mt('Bill now') |h %></A>)
-  (<& /elements/bill.html,
-                custnum   => $cust_main->custnum,
-                label     => emt('Bill now'),
-                url       => $p.'view/cust_main.cgi?'.$cust_main->custnum,
-   &>)
+  <& /elements/bill.html,
+       custnum   => $cust_main->custnum,
+       label     => emt('Bill now'),
+       url       => $p.'view/cust_main.cgi?'.$cust_main->custnum,
+  &>
 % } 
 
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TABLE CLASS="fsinnerbox">
 
 %( my $balance = $cust_main->balance )
 %  =~ s/^(\-?)(.*)$/<FONT SIZE=+1>$1<\/FONT>$money_char$2/;
@@ -285,7 +285,7 @@
 % }
 
 
-</TABLE></TD></TR></TABLE>
+</TABLE>
 <%once>
 
 my $paystate_label = FS::Msgcat::_gettext('paystate');
diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html
index 68e3b17..b3e52b5 100644
--- a/httemplate/view/cust_main/contacts.html
+++ b/httemplate/view/cust_main/contacts.html
@@ -5,8 +5,8 @@
 % foreach my $which ( '', 'ship_' ) {
 %   my $pre = $cust_main->get("${which}last") ? $which : '';
 
-<% $which{$which} %> <% mt('address') |h %>
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<FONT CLASS="fsinnerbox-title"><% $which{$which} %> <% mt('address') |h %></FONT>
+<TABLE CLASS="fsinnerbox">
 <TR>
   <TD ALIGN="right"><% mt('Contact name') |h %></TD>
   <TD COLSPAN=5 BGCOLOR="#ffffff">
@@ -17,18 +17,23 @@
     <TD BGCOLOR="#ffffff"><% $cust_main->masked('ss') || '&nbsp' %></TD>
 % } 
 </TR>
+
 % if ( $conf->exists('cust-email-high-visibility') && $which eq '') {
-<TR>
-  <TD ALIGN="right"><% mt('Email invoices') |h %></TD>
-  <TD BGCOLOR="#ffff00">
-    <% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
-  </TD>
-</TR>
+  <TR>
+    <TD ALIGN="right"><% mt('Email invoices') |h %></TD>
+    <TD BGCOLOR="#ffff00">
+      <% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
+    </TD>
+  </TR>
 % }
-<TR>
-  <TD ALIGN="right"><% mt('Company') |h %></TD>
-  <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") |h %></TD>
-</TR>
+
+% if ( $cust_main->get("${pre}company") ) {
+  <TR>
+    <TD ALIGN="right"><% mt('Company') |h %></TD>
+    <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") |h %></TD>
+  </TR>
+% }
+
 <TR>
   <TD ALIGN="right"><% mt('Address') |h %></TD>
   <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") |h %></TD>
@@ -74,42 +79,30 @@
   &>
 % }
 
-<TR>
-  <TD ALIGN="right"><% $daytime_label %></TD>
-  <TD COLSPAN=3 BGCOLOR="#ffffff">
-    <& /elements/phonenumber.html,
-                  $cust_main->get("${pre}daytime"),
-                  'callable'=>1,
-                  'calling_list_exempt'=>$cust_main->calling_list_exempt,
-    &>
-  </TD>
-</TR>
-<TR>
-  <TD ALIGN="right"><% $night_label %></TD>
-  <TD COLSPAN=3 BGCOLOR="#ffffff">
-    <& /elements/phonenumber.html,
-                  $cust_main->get("${pre}night"),
-                  'callable'=>1,
-                  'calling_list_exempt'=>$cust_main->calling_list_exempt,
-    &>
-  </TD>
-</TR>
-<TR>
-  <TD ALIGN="right"><% $mobile_label %></TD>
-  <TD COLSPAN=3 BGCOLOR="#ffffff">
-    <& /elements/phonenumber.html,
-                  $cust_main->get("${pre}mobile"),
-                  'callable'=>1,
-                  'calling_list_exempt'=>$cust_main->calling_list_exempt,
-    &>
-  </TD>
-</TR>
-<TR>
-  <TD ALIGN="right"><% mt('Fax') |h %></TD>
-  <TD COLSPAN=3 BGCOLOR="#ffffff">
-    <% $cust_main->get("${pre}fax") || '&nbsp' %>
-  </TD>
-</TR>
+% foreach my $phone (grep $cust_main->get($pre.$_), qw( daytime night mobile )){
+
+  <TR>
+    <TD ALIGN="right"><% $phone_label{$phone} %></TD>
+    <TD COLSPAN=3 BGCOLOR="#ffffff">
+      <& /elements/phonenumber.html,
+                    $cust_main->get($pre.$phone),
+                    'callable'=>1,
+                    'calling_list_exempt'=>$cust_main->calling_list_exempt,
+      &>
+    </TD>
+  </TR>
+
+% }
+
+% if ( $cust_main->get("${pre}fax") ) {
+  <TR>
+    <TD ALIGN="right"><% mt('Fax') |h %></TD>
+    <TD COLSPAN=3 BGCOLOR="#ffffff">
+      <% $cust_main->get("${pre}fax") || '&nbsp' %>
+    </TD>
+  </TR>
+% }
+
 % if ( $which eq '' && $conf->exists('show_stateid') ) { 
   <TR>
     <TD ALIGN="right"><% $stateid_label %></TD>
@@ -118,23 +111,31 @@
     <TD BGCOLOR="#ffffff"><% $cust_main->stateid_state || '&nbsp' %></TD>
   </TR>
 % } 
-</TABLE></TD></TR></TABLE>
+
+</TABLE>
 % if ( $which ne 'ship_' ) {
 <BR>
 % }
 % } 
-<& contacts_new.html, $cust_main &>
 <%once>
 
-my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
-                      ? 'Day Phone'
-                      : FS::Msgcat::_gettext('daytime');
-my $night_label   = FS::Msgcat::_gettext('night') =~ /^(night)?$/
-                      ? 'Night Phone'
-                      : FS::Msgcat::_gettext('night');
-my $mobile_label = FS::Msgcat::_gettext('mobile') =~ /^(mobile)?$/
-                      ? 'Mobile Phone'
-                      : FS::Msgcat::_gettext('Mobile');
+my %phone_label = (
+
+  'daytime' => ( FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
+                   ? 'Day Phone'
+                   : FS::Msgcat::_gettext('daytime')
+               ),
+
+  'night'   => ( FS::Msgcat::_gettext('night') =~ /^(night)?$/
+                   ? 'Night Phone'
+                   : FS::Msgcat::_gettext('night')
+               ),
+
+  'mobile'  => ( FS::Msgcat::_gettext('mobile') =~ /^(mobile)?$/
+                   ? 'Mobile Phone'
+                   : FS::Msgcat::_gettext('Mobile')
+               ),
+);
 
 my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
                       ? 'Driver’s License'
diff --git a/httemplate/view/cust_main/contacts_new.html b/httemplate/view/cust_main/contacts_new.html
index bd812c7..155490f 100644
--- a/httemplate/view/cust_main/contacts_new.html
+++ b/httemplate/view/cust_main/contacts_new.html
@@ -1,17 +1,44 @@
-% if ( @contacts ) {
 <BR>
-Contacts
-<% ntable("#cccccc",2) %>
+<FONT CLASS="fsinnerbox-title">Contacts</FONT>
+<A HREF="<%$p%>/edit/cust_main-contacts.html?<% $cust_main->custnum %>">Edit contacts</A>
+<TABLE CLASS="fsinnerbox">
 %   foreach my $contact ( @contacts ) {
+%     #XXX maybe this should be a table with alternating colors instead
       <TR>
-        <TD ALIGN="right">Contact</TD>
+        <TD ALIGN="right"><% $contact->contact_classname %> Contact</TD>
         <TD BGCOLOR="#FFFFFF"><% $contact->line %></TD>
+
+%       my @contact_email = $contact->contact_email;
+%       if (@contact_email) {
+          <TD ALIGN="right">   Email</TD>
+          <TD BGCOLOR="#FFFFFF"><% join(', ', map $_->emailaddress, @contact_email) %></TD>
+%       }
+
+%       foreach my $phone_type (@phone_type) {
+%         my $contact_phone =
+%           qsearchs('contact_phone', {
+%                      'contactnum'   => $contact->contactnum,
+%                      'phonetypenum' => $phone_type->phonetypenum,
+%                   })
+%           or next;
+          <TD ALIGN="right">   <% $phone_type->typename %> phone</TD>
+          <TD BGCOLOR="#FFFFFF"><% $contact_phone->phonenum |h %></TD>
+%       }
+
+%       if ( $contact->comment ) {
+          <TD ALIGN="right">   Comment</TD>
+          <TD BGCOLOR="#FFFFFF"><% $contact->comment |h %></TD>
+
+%       }
+
       </TR>
 %   }
 </TABLE>
+<%once>
 
-% }
+my @phone_type = qsearch({table=>'phone_type', order_by=>'weight'});
 
+</%once>
 <%init>
 
 my( $cust_main ) = @_;
diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html
index 28414ef..2953287 100644
--- a/httemplate/view/cust_main/misc.html
+++ b/httemplate/view/cust_main/misc.html
@@ -1,4 +1,4 @@
-<% ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+<TABLE CLASS="fsinnerbox">
 
 <TR>
   <TD ALIGN="right"><% mt('Customer number') |h %></TD>
@@ -150,7 +150,7 @@
     <% $cust_main->pvf($_)->widget('HTML', 'view', $cust_main->getfield($_)) %>
 % }
 
-</TABLE></TD></TR></TABLE>
+</TABLE>
 <%init>
 
 my( $cust_main ) = @_;

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

Summary of changes:
 FS/FS/cust_main.pm                              |    1 +
 httemplate/edit/cust_main-contacts.html         |  100 +++++++++++++++++++
 httemplate/edit/process/cust_main-contacts.html |   20 ++++
 httemplate/edit/process/elements/process.html   |   96 ++++++++++--------
 httemplate/elements/freeside.css                |   30 ++++++-
 httemplate/view/cust_main.cgi                   |    5 +
 httemplate/view/cust_main/billing.html          |   16 ++--
 httemplate/view/cust_main/contacts.html         |  119 ++++++++++++-----------
 httemplate/view/cust_main/contacts_new.html     |   37 ++++++-
 httemplate/view/cust_main/misc.html             |    4 +-
 10 files changed, 310 insertions(+), 118 deletions(-)
 create mode 100644 httemplate/edit/cust_main-contacts.html
 create mode 100644 httemplate/edit/process/cust_main-contacts.html




More information about the freeside-commits mailing list