add svc_phone on new customer first package, RT#4315
authorivan <ivan>
Sun, 12 Apr 2009 06:14:00 +0000 (06:14 +0000)
committerivan <ivan>
Sun, 12 Apr 2009 06:14:00 +0000 (06:14 +0000)
18 files changed:
FS/FS/part_pkg.pm
httemplate/edit/cust_main.cgi
httemplate/edit/cust_main/billing.html
httemplate/edit/cust_main/birthdate.html [new file with mode: 0644]
httemplate/edit/cust_main/bottomfixup.html [new file with mode: 0644]
httemplate/edit/cust_main/bottomfixup.js [new file with mode: 0644]
httemplate/edit/cust_main/choose_tax_location.html
httemplate/edit/cust_main/first_pkg.html [new file with mode: 0644]
httemplate/edit/cust_main/first_pkg/select-part_pkg.html [new file with mode: 0644]
httemplate/edit/cust_main/first_pkg/svc_acct.html [new file with mode: 0644]
httemplate/edit/cust_main/first_pkg/svc_phone.html [new file with mode: 0644]
httemplate/edit/cust_main/select-domain.html [deleted file]
httemplate/edit/cust_main/top_misc.html [new file with mode: 0644]
httemplate/edit/process/cust_main.cgi
httemplate/elements/select-domain.html
httemplate/elements/select-svc_acct-domain.html [new file with mode: 0644]
httemplate/elements/selectlayers.html
httemplate/misc/part_svc-columns.cgi [new file with mode: 0644]

index 8cf7d0c..8cfd614 100644 (file)
@@ -613,25 +613,49 @@ Returns the svcpart of the primary service definition (see L<FS::part_svc>)
 associated with this package definition (see L<FS::pkg_svc>).  Returns
 false if there not a primary service definition or exactly one service
 definition with quantity 1, or if SVCDB is specified and does not match the
-svcdb of the service definition, 
+svcdb of the service definition.  SVCDB can be specified as a scalar table
+name, such as 'svc_acct', or as an arrayref of possible table names.
 
 =cut
 
 sub svcpart {
+  my $pkg_svc = shift->_primary_pkg_svc(@_);
+  $pkg_svc ? $pkg_svc->svcpart : '';
+}
+
+=item part_svc [ SVCDB ]
+
+Like the B<svcpart> method, but returns the FS::part_svc object (see
+L<FS::part_svc>).
+
+=cut
+
+sub part_svc {
+  my $pkg_svc = shift->_primary_pkg_svc(@_);
+  $pkg_svc ? $pkg_svc->part_svc : '';
+}
+
+sub _primary_pkg_svc {
   my $self = shift;
-  my $svcdb = scalar(@_) ? shift : '';
+
+  my $svcdb = scalar(@_) ? shift : [];
+  $svcdb = ref($svcdb) ? $svcdb : [ $svcdb ];
+  my %svcdb = map { $_=>1 } @$svcdb;
+
   my @svcdb_pkg_svc =
-    grep { ( $svcdb eq $_->part_svc->svcdb || !$svcdb ) } $self->pkg_svc;
+    grep { !scalar(@$svcdb) || $svcdb{ $_->part_svc->svcdb } }
+         $self->pkg_svc;
+
   my @pkg_svc = grep { $_->primary_svc =~ /^Y/i } @svcdb_pkg_svc;
   @pkg_svc = grep {$_->quantity == 1 } @svcdb_pkg_svc
     unless @pkg_svc;
   return '' if scalar(@pkg_svc) != 1;
-  $pkg_svc[0]->svcpart;
+  $pkg_svc[0];
 }
 
 =item svcpart_unique_svcdb SVCDB
 
-Returns the svcpart of the a service definition (see L<FS::part_svc>) matching
+Returns the svcpart of a service definition (see L<FS::part_svc>) matching
 SVCDB associated with this package definition (see L<FS::pkg_svc>).  Returns
 false if there not a primary service definition for SVCDB or there are multiple
 service definitions for SVCDB.
index 098de84..7308c72 100755 (executable)
@@ -1,14 +1,18 @@
 <% include('/elements/header.html',
       "Customer $action",
       '',
-      ' onUnload="myclose()"'
+      ' onUnload="myclose()"' #hmm, in billing.html
 ) %>
 
-<% include('/elements/init_overlib.html') %>
-
 <% include('/elements/error.html') %>
 
-<FORM NAME="topform" STYLE="margin-bottom: 0">
+<FORM NAME   = "CustomerForm"
+      METHOD = "POST"
+      ACTION = "<% popurl(1) %>process/cust_main.cgi"
+%#      STYLE = "margin-bottom: 0"
+%#      STYLE="margin-top: 0; margin-bottom: 0">
+>
+
 <INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
 
 % if ( $custnum ) { 
   <BR><BR>
 % } 
 
-<% &ntable("#cccccc") %>
-
-%# agent
-<% include('/elements/tr-select-agent.html', 
-              'curr_value'    => $cust_main->agentnum,
-              'label'         => "<B>${r}Agent</B>",
-              'empty_label'   => 'Select agent',
-              'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
-           )
-%>
-
-%# agent_custid
-% if ( $conf->exists('cust_main-edit_agent_custid') ) {
-
-    <TR>
-      <TD ALIGN="right">Customer identifier</TD>
-      <TD><INPUT TYPE="text" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>"></TD>
-    </TR>
-
-% } else {
-
-    <INPUT TYPE="hidden" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>">
-
-% }
-
-%# referral (advertising source)
-%my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
-%if ( $custnum && ! $conf->exists('editreferrals') ) {
-
-  <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
-
-% } else { 
-
-   <% include('/elements/tr-select-part_referral.html',
-                'curr_value' => $refnum
-             )
-   %>
-% } 
-
-
-%# referring customer
-%my $referring_cust_main = '';
-%if ( $cust_main->referral_custnum
-%     and $referring_cust_main =
-%           qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
-%) {
-
-  <TR>
-    <TD ALIGN="right">Referring customer</TD>
-    <TD>
-      <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
-    </TD>
-  </TR>
-  <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
-% } elsif ( ! $conf->exists('disable_customer_referrals') ) { 
-
-
-  <TR>
-    <TD ALIGN="right">Referring customer</TD>
-    <TD>
-      <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
-      <% include('/elements/search-cust_main.html',
-                    'field_name' => 'referral_custnum',
-                 )
-      %>
-    </TD>
-  </TR>
-% } else { 
-
-
-  <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
-% } 
-
-
-</TABLE>
-
-<!-- birthdate -->
+%# agent, agent_custid, refnum (advertising source), referral_custnum
+<% include('cust_main/top_misc.html', $cust_main, 'custnum' => $custnum ) %>
 
+%# birthdate
 % if ( $conf->exists('cust_main-enable_birthdate') ) {
-
   <BR>
-  <% ntable("#cccccc", 2) %>
-  <% include ('/elements/tr-input-date-field.html',
-              'birthdate',
-              $cust_main->birthdate,
-              'Date of Birth',
-              $conf->config('date_format') || "%m/%d/%Y",
-              1)
-  %>
-
-  </TABLE>
-
+  <% include('cust_main/birthdate.html', $cust_main) %>
 % }
 
-<!-- contact info -->
+%# contact info
 
 %  my $same_checked = '';
 %  my $ship_disabled = '';
 %  }
 
 <BR><BR>
-Billing address
+<FONT SIZE="+1"><B>Billing address</B></FONT>
+
 <% include('cust_main/contact.html',
              'cust_main'    => $cust_main,
              'pre'          => '',
@@ -199,7 +119,8 @@ function samechanged(what) {
 </SCRIPT>
 
 <BR>
-Service address 
+<FONT SIZE="+1"><B>Service address</B></FONT>
+
 (<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$same_checked%>>same as billing address)
 <% include('cust_main/contact.html',
              'cust_main' => $cust_main,
@@ -209,473 +130,69 @@ Service address
           )
 %>
 
-
-<!-- billing info -->
-
+%# billing info
 <% include( 'cust_main/billing.html', $cust_main,
                'payinfo'        => $payinfo,
                'invoicing_list' => \@invoicing_list,
            )
 %>
 
-<% include( '/elements/xmlhttp.html',
-              'url'  => $p.'misc/xmlhttp-cust_main-address_standardize.html',
-              'subs' => [ 'address_standardize' ],
-              #'method' => 'POST', #could get too long?
-          )
-%>
-
-<SCRIPT>
-function bottomfixup(what) {
-
-  //i don't think we need to copy things between two forms anymore, modern
-  //browsers are fine with DIVs inside FORMs
-
-  var topvars = new Array(
-    'birthdate',
-
-    'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
-
-    'last', 'first', 'ss', 'company',
-    'address1', 'address2', 'city',
-    'county', 'state', 'zip', 'country',
-    'daytime', 'night', 'fax',
-    'stateid', 'stateid_state',
-
-    'same',
-
-    'ship_last', 'ship_first', 'ship_company',
-    'ship_address1', 'ship_address2', 'ship_city',
-    'ship_county', 'ship_state', 'ship_zip', 'ship_country',
-    'ship_daytime','ship_night', 'ship_fax',
-
-    'geocode',
-
-    'select' // XXX key
-  );
-
-  var layervars = new Array(
-    'payauto',
-    'payinfo', 'payinfo1', 'payinfo2', 'paytype',
-    'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
-    'paystart_month', 'paystart_year', 'payissue',
-    'payip',
-    'paid'
-  );
-
-  var billing_bottomvars = new Array(
-    'tax',
-    'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
-    'invoice_terms',
-    'spool_cdr',
-    'squelch_cdr'
-  );
-
-  for ( f=0; f < topvars.length; f++ ) {
-    var field = topvars[f];
-    copyelement( document.topform.elements[field],
-                 document.bottomform.elements[field]
-               );
-  }
-
-  var layerform = document.topform.select.options[document.topform.select.selectedIndex].value;
-  for ( f=0; f < layervars.length; f++ ) {
-    var field = layervars[f];
-    copyelement( document.forms[layerform].elements[field],
-                 document.bottomform.elements[field]
-               );
-  }
-
-  for ( f=0; f < billing_bottomvars.length; f++ ) {
-    var field = billing_bottomvars[f];
-    copyelement( document.billing_bottomform.elements[field],
-                 document.bottomform.elements[field]
-               );
-  }
-
-  //this part does USPS address correction
-
-  // XXX should this be first and should we update the form fields that are
-  // displayed???
-
-  //var state_el = document.bottomform.elements['state'];
-
-  //address_standardize(
-  var cust_main = new Array(
-    'company',  document.bottomform.elements['company'].value,
-    'address1', document.bottomform.elements['address1'].value,
-    'address2', document.bottomform.elements['address2'].value,
-    'city',     document.bottomform.elements['city'].value,
-    'state',    document.bottomform.elements['state'].value,
-    //'state',    state_el.options[ state_el.selectedIndex ].value,
-    'zip',      document.bottomform.elements['zip'].value,
-
-    'ship_company',  document.bottomform.elements['ship_company'].value,
-    'ship_address1', document.bottomform.elements['ship_address1'].value,
-    'ship_address2', document.bottomform.elements['ship_address2'].value,
-    'ship_city',     document.bottomform.elements['ship_city'].value,
-    'ship_state',    document.bottomform.elements['ship_state'].value,
-    //'ship_state',    state_el.options[ state_el.selectedIndex ].value,
-    'ship_zip',      document.bottomform.elements['ship_zip'].value
-  );
-
-  address_standardize( cust_main, update_address );
-
-}
-
-var standardize_address;
-
-function update_address(arg) {
-
-  var argsHash = eval('(' + arg + ')');
-
-  var changed  = argsHash['address_standardized'];
-  var ship_changed = argsHash['ship_address_standardized'];
-  var error = argsHash['error'];
-  var ship_error = argsHash['ship_error'];
-
-  //yay closures
-  standardize_address = function () {
-
-    if ( changed ) {
-      document.bottomform.elements['company'].value = argsHash['new_company'];
-      document.bottomform.elements['address1'].value = argsHash['new_address1'];
-      document.bottomform.elements['address2'].value = argsHash['new_address2'];
-      document.bottomform.elements['city'].value = argsHash['new_city'];
-      document.bottomform.elements['state'].value = argsHash['new_state'];
-  //'state',    state_el.options[ state_el.selectedIndex ].value,
-      document.bottomform.elements['zip'].value = argsHash['new_zip'];
-    }
-
-    if ( ship_changed ) {
-      document.bottomform.elements['ship_company'].value = argsHash['new_ship_company'];
-      document.bottomform.elements['ship_address1'].value = argsHash['new_ship_address1'];
-      document.bottomform.elements['ship_address2'].value = argsHash['new_ship_address2'];
-      document.bottomform.elements['ship_city'].value = argsHash['new_ship_city'];
-      document.bottomform.elements['ship_state'].value = argsHash['new_ship_state'];
-  //'state',    state_el.options[ state_el.selectedIndex ].value,
-      document.bottomform.elements['ship_zip'].value = argsHash['new_ship_zip'];
-    }
-
-  }
-
-% if ( $conf->exists('enable_taxproducts') ) {
-
-  if ( <% $taxpre %>error ) {
-
-    if ( document.bottomform.elements['<% $taxpre %>country'].value == 'CA' ||
-         document.bottomform.elements['<% $taxpre %>country'].value == 'US'
-       )
-    {
-
-      var url = "cust_main/choose_tax_location.html?data_vendor=cch-zip;city="+document.bottomform.elements['<% $taxpre %>city'].value+";state="+document.bottomform.elements['<% $taxpre %>state'].value+";zip="+document.bottomform.elements['<% $taxpre %>zip'].value+";country="+document.bottomform.elements['<% $taxpre %>country'].value+";";
-      // popup a chooser
-      OLgetAJAX( url, update_geocode, 300 );
-
-    } else {
-
-      document.bottomform.elements['geocode'].value = 'DEFAULT';
-      document.bottomform.submit();
-
-    }
+% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
+% if (!$ro_comments || $cust_main->comments) {
 
-  } else
+    <BR>Comments
+    <% &ntable("#cccccc") %>
+      <TR>
+        <TD>
+          <TEXTAREA NAME = "comments"
+                    COLS = 80
+                    ROWS = 5
+                    WRAP = "HARD"
+                    <% $ro_comments %>
+          ><% $cust_main->comments %></TEXTAREA>
+        </TD>
+      </TR>
+    </TABLE>
 
 % }
 
-  if ( changed || ship_changed ) {
-
-%   if ( $conf->exists('cust_main-auto_standardize_address') ) {
-
-    standardize_address();
-    document.bottomform.submit();
-
-%   } else {
-
-    // popup a confirmation popup
-
-    var confirm_change =
-      '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
-      '<TABLE>';
-    
-    if ( changed ) {
-
-      confirm_change = confirm_change + 
-        '<TR><TH>Entered billing address</TH>' +
-          '<TH>Standardized billing address</TH></TR>';
-        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-      
-      if ( argsHash['company'] || argsHash['new_company'] ) {
-        confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['company'] +
-          '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
-      }
-      
-      confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['address1'] +
-          '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['address2'] +
-          '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + '  ' + argsHash['zip'] +
-          '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + '  ' + argsHash['new_zip'] + '</TD></TR>' +
-          '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
-    }
-
-    if ( ship_changed ) {
-
-      confirm_change = confirm_change + 
-        '<TR><TH>Entered service address</TH>' +
-          '<TH>Standardized service address</TH></TR>';
-        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-      
-      if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
-        confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['ship_company'] +
-          '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
-      }
-      
-      confirm_change = confirm_change +
-        '<TR><TD>' + argsHash['ship_address1'] +
-          '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['ship_address2'] +
-          '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
-        '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + '  ' + argsHash['ship_zip'] +
-          '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + '  ' + argsHash['new_ship_zip'] + '</TD></TR>' +
-        '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
-
-    }
-
-    var addresses = 'address';
-    var height = 268;
-    if ( changed && ship_changed ) {
-      addresses = 'addresses';
-      height = 396; // #what
-    }
-
-    confirm_change = confirm_change +
-      '<TR><TD>' +
-        '<BUTTON TYPE="button" onClick="document.bottomform.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' + 
-      '</TD><TD>' +
-        '<BUTTON TYPE="button" onClick="standardize_address(); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' + 
-      '</TD></TR>' +
-      '<TR><TD COLSPAN=2 ALIGN="center">' +
-        '<BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
-        
-      '</TABLE></CENTER>';
-
-    overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-%   }
-
-  } else {
-
-    document.bottomform.submit();
-
-  }
-
-}
-
-function update_geocode() {
-
-  //yay closures
-  set_geocode = function (what) {
-
-    //alert(what.options[what.selectedIndex].value);
-    var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
-    document.bottomform.elements['<% $taxpre %>city'].value = argsHash['city'];
-    document.bottomform.elements['<% $taxpre %>state'].value = argsHash['state'];
-    document.bottomform.elements['<% $taxpre %>zip'].value = argsHash['zip'];
-    document.bottomform.elements['geocode'].value = argsHash['geocode'];
-
-  }
+% unless ( $custnum ) {
 
-  // popup a chooser
+    <% include('cust_main/first_pkg.html', $cust_main,
+                 'pkgpart_svcpart' => $pkgpart_svcpart,
+                 #svc_acct
+                 'username'        => $username,
+                 'password'        => $password,
+                 'popnum'          => $popnum,
+                 'saved_domsvc'    => $saved_domsvc,
+                 %svc_phone,
+              )
+    %>
 
-  overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
-
-}
-
-function copyelement(from, to) {
-  if ( from == undefined ) {
-    to.value = '';
-  } else if ( from.type == 'select-one' ) {
-    to.value = from.options[from.selectedIndex].value;
-    //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
-  } else if ( from.type == 'checkbox' ) {
-    if ( from.checked ) {
-      to.value = from.value;
-    } else {
-      to.value = '';
-    }
-  } else {
-    if ( from.value == undefined ) {
-      to.value = '';
-    } else {
-      to.value = from.value;
-    }
-  }
-  //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
-}
+% }
 
-</SCRIPT>
+<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
 
-<FORM ACTION="<% popurl(1) %>process/cust_main.cgi" METHOD=POST NAME="bottomform" STYLE="margin-top: 0; margin-bottom: 0">
 % foreach my $hidden (
-%     'birthdate',
-%
-%     'custnum', 'agentnum', 'agent_custid', 'refnum', 'referral_custnum',
-%     'last', 'first', 'ss', 'company',
-%     'address1', 'address2', 'city',
-%     'county', 'state', 'zip', 'country',
-%     'daytime', 'night', 'fax',
-%     'stateid', 'stateid_state',
-%     
-%     'same',
-%     
-%     'ship_last', 'ship_first', 'ship_company',
-%     'ship_address1', 'ship_address2', 'ship_city',
-%     'ship_county', 'ship_state', 'ship_zip', 'ship_country',
-%     'ship_daytime','ship_night', 'ship_fax',
-%     
-%     'geocode',
-%     
-%     'select', #XXX key
-%
-%     'payauto',
-%     'payinfo', 'payinfo1', 'payinfo2', 'paytype',
-%     'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
-%     'paystart_month', 'paystart_year', 'payissue',
-%     'payip',
-%     'paid',
-%     
-%     'tax',
-%     'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
-%     'invoice_terms',
-%     'spool_cdr',
-%     'squelch_cdr'
-%   ) {
-%
-
-  <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
-% } 
-%
-% my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
-% if (!$ro_comments || $cust_main->comments) {
-
-<BR>Comments
-<% &ntable("#cccccc") %>
-  <TR>
-    <TD>
-      <TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments" <%$ro_comments%>><% $cust_main->comments %></TEXTAREA>
-    </TD>
-  </TR>
-</TABLE>
-%
-% }
-%
-%unless ( $custnum ) {
-%  # pry the wrong place for this logic.  also pretty expensive
-%  #use FS::part_pkg;
-%
-%  #false laziness, copied from FS::cust_pkg::order
-%  my $pkgpart;
-%  my $agentnum = '';
-%  my @agents = $FS::CurrentUser::CurrentUser->agents;
-%  if ( scalar(@agents) == 1 ) {
-%    # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
-%    $pkgpart = $agents[0]->pkgpart_hashref;
-%    $agentnum = $agents[0]->agentnum;
-%  } else {
-%    #can't know (agent not chosen), so, allow all
-%    $agentnum = 'all';
-%    my %typenum;
-%    foreach my $agent ( @agents ) {
-%      next if $typenum{$agent->typenum}++;
-%      $pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
-%    }
-%  }
-%  #eslaf
-%
-%  my @part_pkg = grep { $_->svcpart('svc_acct')
-%                        && ( $pkgpart->{ $_->pkgpart } 
-%                             || $agentnum eq 'all'
-%                             || ( $agentnum ne 'all'
-%                                  && $agentnum
-%                                  && $_->agentnum
-%                                  && $_->agentnum == $agentnum
-%                                )
-%                           )
-%                      }
-%    qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
-%
-%  if ( @part_pkg ) {
-%
-%    #    print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"),
-%    #apiabuse & undesirable wrapping
-%
-%    
-
-    <BR>First package
-    <% ntable("#cccccc") %>
-    
-      <TR>
-        <TD COLSPAN=2>
-          <% include('cust_main/select-domain.html',
-                       'pkgparts'      => \@part_pkg,
-                       'saved_pkgpart' => $saved_pkgpart,
-                       'saved_domsvc' => $saved_domsvc,
-                    )
-          %>
-        </TD>
-      </TR>
-% 
-%        #false laziness: (mostly) copied from edit/svc_acct.cgi
-%        #$ulen = $svc_acct->dbdef_table->column('username')->length;
-%        my $ulen = dbdef->table('svc_acct')->column('username')->length;
-%        my $ulen2 = $ulen+2;
-%        my $passwordmax = $conf->config('passwordmax') || 8;
-%        my $pmax2 = $passwordmax + 2;
-%      
-
-    
-      <TR>
-        <TD ALIGN="right">Username</TD>
-        <TD>
-          <INPUT TYPE="text" NAME="username" VALUE="<% $username %>" SIZE=<% $ulen2 %> MAXLENGTH=<% $ulen %>>
-        </TD>
-      </TR>
-    
-      <TR>
-        <TD ALIGN="right">Domain</TD>
-        <TD>
-          <SELECT NAME="domsvc">
-            <OPTION>(none)</OPTION>
-          </SELECT>
-        </TD>
-      </TR>
-    
-      <TR>
-        <TD ALIGN="right">Password</TD>
-        <TD>
-          <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $passwordmax %>>
-          (blank to generate)
-        </TD>
-      </TR>
-    
-      <TR>
-        <TD ALIGN="right">Access number</TD>
-        <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
-      </TR>
-    </TABLE>
-% } 
+%    'payauto',
+%    'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+%    'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+%    'paystart_month', 'paystart_year', 'payissue',
+%    'payip',
+%    'paid',
+% ) {
+    <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
 % } 
 
+<% include('cust_main/bottomfixup.html') %>
 
-<INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
-<BR>
-<INPUT TYPE="button" NAME="submitButton" ID="submitButton" VALUE="<% $custnum ?  "Apply Changes" : "Add Customer" %>" onClick="document.bottomform.submitButton.disabled=true; bottomfixup(this.form);">
 <BR>
+<INPUT TYPE    = "button"
+       NAME    = "submitButton"
+       ID      = "submitButton"
+       VALUE   = "<% $custnum ?  "Apply Changes" : "Add Customer" %>"
+       onClick = "this.disabled=true; bottomfixup(this.form);"
+>
 </FORM>
 
 <% include('/elements/footer.html') %>
@@ -685,52 +202,49 @@ function copyelement(from, to) {
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
 
-#for misplaced logic below
-#use FS::part_pkg;
-
-#for false laziness below (now more properly lazy)
-#use FS::svc_acct_pop;
-
-#for (other) false laziness below
-#use FS::agent;
-#use FS::type_pkgs;
-
 my $conf = new FS::Conf;
 
-my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
 #get record
 
-my($custnum, $username, $password, $popnum, $cust_main, $saved_pkgpart, $saved_domsvc);
-my(@invoicing_list);
-my ($ss,$stateid,$payinfo);
+my($custnum, $cust_main, $ss, $stateid, $payinfo, @invoicing_list);
 my $same = '';
+my $pkgpart_svcpart = ''; #first_pkg
+my($username, $password, $popnum, $saved_domsvc) = ( '', '', 0, 0 ); #svc_acct
+my %svc_phone = ();
+
 if ( $cgi->param('error') ) {
+
   $cust_main = new FS::cust_main ( {
     map { $_, scalar($cgi->param($_)) } fields('cust_main')
   } );
+
   $custnum = $cust_main->custnum;
-  $saved_domsvc = $cgi->param('domsvc') || '';
-  if ( $saved_domsvc =~ /^(\d+)$/ ) {
-    $saved_domsvc = $1;
-  } else {
-    $saved_domsvc = '';
-  }
-  $saved_pkgpart = $cgi->param('pkgpart_svcpart') || '';
-  if ( $saved_pkgpart =~ /^(\d+)_/ ) {
-    $saved_pkgpart = $1;
-  } else {
-    $saved_pkgpart = '';
-  }
-  $username = $cgi->param('username');
-  $password = $cgi->param('_password');
-  $popnum = $cgi->param('popnum');
   @invoicing_list = split( /\s*,\s*/, $cgi->param('invoicing_list') );
   $same = $cgi->param('same');
   $cust_main->setfield('paid' => $cgi->param('paid')) if $cgi->param('paid');
   $ss = $cust_main->ss;           # don't mask an entered value on errors
   $stateid = $cust_main->stateid; # don't mask an entered value on errors
   $payinfo = $cust_main->payinfo; # don't mask an entered value on errors
+
+  $pkgpart_svcpart = $cgi->param('pkgpart_svcpart') || '';
+
+  #svc_acct
+  $username = $cgi->param('username');
+  $password = $cgi->param('_password');
+  $popnum = $cgi->param('popnum');
+  $saved_domsvc = $cgi->param('domsvc') || '';
+  if ( $saved_domsvc =~ /^(\d+)$/ ) {
+    $saved_domsvc = $1;
+  } else {
+    $saved_domsvc = '';
+  }
+
+  #svc_phone
+  $svc_phone{$_} = $cgi->param($_)
+    foreach qw( countrycode phonenum sip_password pin phone_name );
+
 } elsif ( $cgi->keywords ) { #editing
+
   my( $query ) = $cgi->keywords;
   $query =~ /^(\d+)$/;
   $custnum=$1;
@@ -741,31 +255,24 @@ if ( $cgi->param('error') ) {
     $paycvv =~ s/./*/g;
     $cust_main->paycvv($paycvv);
   }
-  $saved_pkgpart = 0;
-  $saved_domsvc = 0;
-  $username = '';
-  $password = '';
-  $popnum = 0;
   @invoicing_list = $cust_main->invoicing_list;
   $ss = $cust_main->masked('ss');
   $stateid = $cust_main->masked('stateid');
   $payinfo = $cust_main->paymask;
-} else {
+
+} else { #new customer
+
   $custnum='';
   $cust_main = new FS::cust_main ( {} );
   $cust_main->otaker( &getotaker );
   $cust_main->referral_custnum( $cgi->param('referral_custnum') );
-  $saved_pkgpart = 0;
-  $saved_domsvc = 0;
-  $username = '';
-  $password = '';
-  $popnum = 0;
   @invoicing_list = ();
   push @invoicing_list, 'POST'
     unless $conf->exists('disablepostalinvoicedefault');
   $ss = '';
   $stateid = '';
   $payinfo = '';
+
 }
 
 my $error = $cgi->param('error');
index e175e21..353f2b9 100644 (file)
@@ -1,18 +1,15 @@
 %if ( $payby_default eq 'HIDE' ) {
 %
 %  $cust_main->payby('BILL') unless $cust_main->payby;
+%  my $payby = $cust_main->payby;
 
-  <INPUT TYPE="hidden" NAME="select" VALUE="<% $cust_main->payby %>">
-
-  </FORM>
-
-  <FORM NAME="<% $cust_main->payby %>" STYLE="margin-top: 0; margin-bottom: 0"> 
+  <INPUT TYPE="hidden" NAME="payby" VALUE="<% $payby %>">
 
-    <INPUT TYPE="hidden" NAME="payinfo" VALUE="<% $cust_main->paymask %>">
+  <INPUT TYPE="hidden" NAME="<%$payby%>_payinfo" VALUE="<% $cust_main->paymask %>">
 
 % foreach my $field (qw( payname paycvv paystart_month paystart_year payissue payip paytype paystate )) { 
 
-    <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $cust_main->getfield($field) %>">
+    <INPUT TYPE="hidden" NAME="<% $payby.'_'.$field %>" VALUE="<% $cust_main->get($field) %>">
 
 % } 
 
 %    die "unrecognized expiration date format: $date";
 %  }
 
-  <INPUT TYPE="hidden" NAME="exp_month" VALUE="<% $mon %>">
-  <INPUT TYPE="hidden" NAME="exp_year"  VALUE="<% $year %>">
-
-  </FORM>
-
-  <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+  <INPUT TYPE="hidden" NAME="<%$payby%>_exp_month" VALUE="<% $mon %>">
+  <INPUT TYPE="hidden" NAME="<%$payby%>_exp_year"  VALUE="<% $year %>">
 
   <INPUT TYPE="hidden" NAME="tax" VALUE="<% $cust_main->tax %>">
 
   <INPUT TYPE="hidden" NAME="invoicing_list" VALUE="<% join(', ', @invoicing_list) %>">
 
-  </FORM>
-
 % } else {
 %
 %  my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
 
-  <BR>Billing information
+  <BR><FONT SIZE="+1"><B>Billing information</B></FONT>
   <% &ntable("#cccccc") %>
 
     <TR>
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Card number </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payinfo" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $payinfo : '' ). qq!" MAXLENGTH=19 onChange="card_changed(this)" onKeyUp="card_changed(this)"></TD></TR>!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
 %          '<TD WIDTH="408">'.
 %
 %          include('/elements/select-month_year.html',
-%                    'prefix' => 'exp',
+%                    'prefix' => 'CARD_exp',
 %                    'selected_date' =>
 %                      ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->paydate : '' ),
 %                 ).
 %
 %          qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
 %          qq!</TD>!.
-%          '<TD WIDTH="408"><INPUT TYPE="text" NAME="paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
+%          '<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_paycvv" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ && !$cust_main->is_encrypted($cust_main->paycvv) ? $cust_main->paycvv : '' ). '" SIZE=4 MAXLENGTH=4>'.
 %
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200"><SPAN ID="paystart_label" $text_disabled>Start date </SPAN></TD>!.
 %          '<TD WIDTH="408">'.
 %
 %          include('/elements/select-month_year.html',
-%                    'prefix' => 'paystart',
+%                    'prefix' => 'CARD_paystart',
 %                    'disabled' => $disabled,
 %                    'empty_option' => 1,
 %                    'start_year' => 2000,
 %                 ).
 %
 %        qq!<SPAN ID="payissue_label" $text_disabled> or Issue number </SPAN>!.
-%          '<INPUT TYPE="text" NAME="payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
+%          '<INPUT TYPE="text" NAME="CARD_payissue" VALUE="'. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payissue : '' ). qq!" SIZE=3 MAXLENGTH=2 $disabled></TD></TR>!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Exact name on card </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CARD_payname" VALUE="!. ( $payby =~ /^(CARD|DCRD)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
 %
-%        qq!<TR><TD COLSPAN=2 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCRD' ? '' : 'CHECKED' ). '> Charge future payments to this card automatically</TD></TR>'.
+%        qq!<TR><TD COLSPAN=2 WIDTH="608"><INPUT TYPE="checkbox" NAME="CARD_payauto" !. ( $payby eq 'DCRD' ? '' : 'CHECKED' ). '> Charge future payments to this card automatically</TD></TR>'.
 %
 %      '</TABLE>',
 %
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Account number </TD>!.
-%          qq!<TD><INPUT TYPE="text" SIZE=12 NAME="payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
-%          qq!<TD ALIGN="right">Type</TD><TD><SELECT NAME="paytype">!.
+%          qq!<TD><INPUT TYPE="text" SIZE=12 NAME="CHEK_payinfo1" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $account : '' ). '"></TD>'.
+%          qq!<TD ALIGN="right">Type</TD><TD><SELECT NAME="CHEK_paytype">!.
 %            join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes).
 %          qq!</SELECT></TD></TR>!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}ABA/Routing number </TD>!.
-%          qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!" SIZE=10 MAXLENGTH=9> !.
+%          qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" SIZE=10 MAXLENGTH=9 NAME="CHEK_payinfo2" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $aba : '' ). qq!" SIZE=10 MAXLENGTH=9> !.
 %          qq!(<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;">help</A>)!.
 %          qq!</TD></TR>!.
 %
-%        qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-%        qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+%        qq!<INPUT TYPE="hidden" NAME="CHEK_exp_month" VALUE="12">!.
+%        qq!<INPUT TYPE="hidden" NAME="CHEK_exp_year" VALUE="2037">!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Bank name </TD>!.
-%          qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%          qq!<TD COLSPAN="3" WIDTH="408"><INPUT TYPE="text" NAME="CHEK_payname" VALUE="!. ( $payby =~ /^(CHEK|DCHK)$/ ? $cust_main->payname : '' ). qq!"></TD></TR>!.
 %      ( $conf->exists('show_bankstate') ?
 %          qq!<TR><TD ALIGN="right" WIDTH="200">$paystate_label</TD>!.
 %          qq!<TD COLSPAN="3" WIDTH="408">!.
 %                    'empty'   => '(choose)',
 %                    'state'   => $cust_main->paystate,
 %                    'country' => $cust_main->country,
-%                    'prefix'  => 'pay',
+%                    'prefix'  => 'CHEK_pay',
 %                 ). "</TD></TR>"
-%         : '<INPUT TYPE="hidden" NAME="paystate" VALUE="'.
+%         : '<INPUT TYPE="hidden" NAME="CHEK_paystate" VALUE="'.
 %            $cust_main->paystate. '">'
 %       ).
 %
 %
-%        qq!<TR><TD COLSPAN=4 WIDTH="608"><INPUT TYPE="checkbox" NAME="payauto" !. ( $payby eq 'DCHK' ? '' : 'CHECKED' ). '> Charge future payments to this electronic check automatically</TD></TR>'.
+%        qq!<TR><TD COLSPAN=4 WIDTH="608"><INPUT TYPE="checkbox" NAME="CHEK_payauto" !. ( $payby eq 'DCHK' ? '' : 'CHECKED' ). '> Charge future payments to this electronic check automatically</TD></TR>'.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Phone number </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="LECB_payinfo" VALUE="!. ( $payby eq 'LECB' ? $cust_main->payinfo : '' ). qq!" MAXLENGTH=15 SIZE=16></TD></TR>!.
 %
-%        qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-%        qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
-%        qq!<INPUT TYPE="hidden" NAME="payname" VALUE="">!.
+%        qq!<INPUT TYPE="hidden" NAME="LECB_exp_month" VALUE="12">!.
+%        qq!<INPUT TYPE="hidden" NAME="LECB_exp_year" VALUE="2037">!.
+%        qq!<INPUT TYPE="hidden" NAME="LECB_payname" VALUE="">!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">P.O. </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payinfo" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payinfo : '' ). qq!"></TD></TR>!.
 %
-%        qq!<INPUT TYPE="hidden" NAME="exp_month" VALUE="12">!.
-%        qq!<INPUT TYPE="hidden" NAME="exp_year" VALUE="2037">!.
+%        qq!<INPUT TYPE="hidden" NAME="BILL_exp_month" VALUE="12">!.
+%        qq!<INPUT TYPE="hidden" NAME="BILL_exp_year" VALUE="2037">!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">Attention </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="BILL_payname" VALUE="!. ( $payby eq 'BILL' ? $cust_main->payname : '' ). qq!"></TD></TR>!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Approved by </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="payinfo" VALUE=""></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""></TD></TR>!.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Expiration </TD>!.
 %          '<TD WIDTH="408">'.
 %
 %          include('/elements/select-month_year.html',
-%                    'prefix' => 'exp',
+%                    'prefix' => 'COMP_exp',
 %                    'selected_date' =>
 %                      ( $payby eq 'COMP' ? $cust_main->paydate : '' ),
 %                 ).
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="CASH_paid" VALUE="!. ( $payby eq 'CASH' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="WEST_paid" VALUE="!. ( $payby eq 'WEST' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %      '<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 HEIGHT=192>'.
 %
 %        qq!<TR><TD ALIGN="right" WIDTH="200">${r}Amount </TD>!.
-%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
+%          qq!<TD WIDTH="408"><INPUT TYPE="text" NAME="MCRD_paid" VALUE="!. ( $payby eq 'MCRD' ? $cust_main->paid : '' ). qq!"></TD></TR>!.
 %
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %        '<TR><TD>&nbsp;</TD></TR>'.
 %  );
 %
 %  #this should use FS::payby
-%  my %allopt = (
-%    'CARD' => 'Credit card',
-%    'CHEK' => 'Electronic check',
-%    'LECB' => 'Phone bill billing',
-%    'BILL' => 'Billing',
-%    'CASH' => 'Cash', # initial payment, then billing',
-%    'WEST' => 'Western Union', # initial payment, then billing',
-%    'MCRD' => 'Manual credit card', # initial payment, then billing',
-%    'COMP' => 'Complimentary',
-%  );
-%  if ( $cust_main->custnum ) { #don't offer CASH/WEST/MCRD initial payment types
-%                               # when editing customer
+%  my @allopt = qw( CARD CHEK LECB BILL CASH WEST MCRD COMP );
+%
+%  my %allopt = map { $_ => FS::payby->shortname($_) } @allopt;
+%
+%  if ( $cust_main->custnum ) {
+%    #don't offer CASH/WEST/MCRD initial payment types when editing customer
 %    delete $allopt{$_} for qw(CASH WEST MCRD);
 %  }
 %  
-%  tie my %options, 'Tie::IxHash',
-%    map  { $_ => $allopt{$_} }
-%    grep { exists $allopt{$_} }
-%         @payby;
+%  my @options = grep exists( $allopt{$_} ), @payby;
 %
 %  my %payby2option = (
-%    ( map { $_ => $_ } keys %options ),
+%    ( map { $_ => $_ } @options ),
 %    'DCRD' => 'CARD',
 %    'DCHK' => 'CHEK',
 %  );
-%
-%  my $widget = new HTML::Widgets::SelectLayers(
-%    'options'        => \%options,
-%    #'form_name'      => 'dummy',
-%    #'form_action'    => 'nothingyet',
-%    #chops bottom of page in IE# 'under_position' => 'absolute',
-%    'html_between'   => '</TD></TR></TABLE>',
-%    'selected_layer' => $payby2option{$payby || $payby_default || $payby[0] },
-%    'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
-%  );
-%
-%  
-
 
-  <TD WIDTH="408"><% $widget->html %>
-
-  <FORM NAME="billing_bottomform" STYLE="margin-top: 0; margin-bottom: 0">
+  <TD WIDTH="408">
+    <% include( '/elements/selectlayers.html',
+                  'field'      => 'payby',
+                  'curr_value' => $payby2option{$payby || $payby_default || $payby[0] },
+                  'options'    => \@options,
+                  'labels'     => \%allopt,
+                  'html_between' => '</TD></TR></TABLE>',
+                  'layer_callback' => sub { my $layer = shift; $payby{$layer}; },
+              )
+    %>
 
   <% &ntable("#cccccc") %>
 
 
   </TABLE>
 
-  </FORM>
-
   <% $r %> required fields
 % } 
 
diff --git a/httemplate/edit/cust_main/birthdate.html b/httemplate/edit/cust_main/birthdate.html
new file mode 100644 (file)
index 0000000..415aba3
--- /dev/null
@@ -0,0 +1,15 @@
+<% ntable("#cccccc", 2) %>
+  <% include ('/elements/tr-input-date-field.html',
+              'birthdate',
+              $cust_main->birthdate,
+              'Date of Birth',
+              $conf->config('date_format') || "%m/%d/%Y",
+              1)
+  %>
+</TABLE>
+<%init>
+
+my( $cust_main, %opt ) = @_;
+my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/cust_main/bottomfixup.html b/httemplate/edit/cust_main/bottomfixup.html
new file mode 100644 (file)
index 0000000..3eb43e0
--- /dev/null
@@ -0,0 +1,12 @@
+<% include('/elements/init_overlib.html') %>
+
+<% include( '/elements/xmlhttp.html',
+              'url'  => $p.'misc/xmlhttp-cust_main-address_standardize.html',
+              'subs' => [ 'address_standardize' ],
+              #'method' => 'POST', #could get too long?
+          )
+%>
+
+<SCRIPT TYPE="text/javascript">
+  <% include('bottomfixup.js') %>
+</SCRIPT>
diff --git a/httemplate/edit/cust_main/bottomfixup.js b/httemplate/edit/cust_main/bottomfixup.js
new file mode 100644 (file)
index 0000000..efe2215
--- /dev/null
@@ -0,0 +1,278 @@
+function bottomfixup(what) {
+
+  var layervars = new Array(
+    'payauto',
+    'payinfo', 'payinfo1', 'payinfo2', 'paytype',
+    'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
+    'paystart_month', 'paystart_year', 'payissue',
+    'payip',
+    'paid'
+  );
+
+  var cf = document.CustomerForm;
+  var payby = cf.payby.options[cf.payby.selectedIndex].value;
+  for ( f=0; f < layervars.length; f++ ) {
+    var field = layervars[f];
+    copyelement( cf.elements[payby + '_' + field],
+                 cf.elements[field]
+               );
+  }
+
+  //this part does USPS address correction
+
+  // XXX should this be first and should we update the form fields that are
+  // displayed???
+
+  var cf = document.CustomerForm;
+
+  var state_el      = cf.elements['state'];
+  var ship_state_el = cf.elements['ship_state'];
+
+  //address_standardize(
+  var cust_main = new Array(
+    'company',  cf.elements['company'].value,
+    'address1', cf.elements['address1'].value,
+    'address2', cf.elements['address2'].value,
+    'city',     cf.elements['city'].value,
+    'state',    state_el.options[ state_el.selectedIndex ].value,
+    'zip',      cf.elements['zip'].value,
+
+    'ship_company',  cf.elements['ship_company'].value,
+    'ship_address1', cf.elements['ship_address1'].value,
+    'ship_address2', cf.elements['ship_address2'].value,
+    'ship_city',     cf.elements['ship_city'].value,
+    'ship_state',    ship_state_el.options[ ship_state_el.selectedIndex ].value,
+    'ship_zip',      cf.elements['ship_zip'].value
+  );
+
+  address_standardize( cust_main, update_address );
+
+}
+
+var standardize_address;
+
+function update_address(arg) {
+
+  var argsHash = eval('(' + arg + ')');
+
+  var changed  = argsHash['address_standardized'];
+  var ship_changed = argsHash['ship_address_standardized'];
+  var error = argsHash['error'];
+  var ship_error = argsHash['ship_error'];
+
+  //yay closures
+  standardize_address = function () {
+
+    var cf = document.CustomerForm;
+    var state_el      = cf.elements['state'];
+    var ship_state_el = cf.elements['ship_state'];
+
+    if ( changed ) {
+      cf.elements['company'].value  = argsHash['new_company'];
+      cf.elements['address1'].value = argsHash['new_address1'];
+      cf.elements['address2'].value = argsHash['new_address2'];
+      cf.elements['city'].value     = argsHash['new_city'];
+      setselect(cf.elements['state'], argsHash['new_state']);
+      cf.elements['zip'].value      = argsHash['new_zip'];
+    }
+
+    if ( ship_changed ) {
+      cf.elements['ship_company'].value  = argsHash['new_ship_company'];
+      cf.elements['ship_address1'].value = argsHash['new_ship_address1'];
+      cf.elements['ship_address2'].value = argsHash['new_ship_address2'];
+      cf.elements['ship_city'].value     = argsHash['new_ship_city'];
+      setselect(cf.elements['ship_state'], argsHash['new_ship_state']);
+      cf.elements['ship_zip'].value      = argsHash['new_ship_zip'];
+    }
+
+  }
+
+  var cf = document.CustomerForm;
+
+% if ( $conf->exists('enable_taxproducts') ) {
+
+  if ( <% $taxpre %>error ) {
+
+    var country_el = cf.elements['<% $taxpre %>country'];
+    var country = country_el.options[ country_el.selectedIndex ].value;
+
+    if ( country == 'CA' || country == 'US' ) {
+
+      var state_el = cf.elements['<% $taxpre %>state'];
+      var state = state_el.options[ state_el.selectedIndex ].value;
+
+      var url = "cust_main/choose_tax_location.html" +
+                  "?data_vendor=cch-zip" + 
+                  ";city="    + cf.elements['<% $taxpre %>city'].value +
+                  ";state="   + state + 
+                  ";zip="     + cf.elements['<% $taxpre %>zip'].value +
+                  ";country=" + country +
+                  ";";
+
+      // popup a chooser
+      OLgetAJAX( url, update_geocode, 300 );
+
+    } else {
+
+      cf.elements['geocode'].value = 'DEFAULT';
+      cf.submit();
+
+    }
+
+  } else
+
+% }
+
+  if ( changed || ship_changed ) {
+
+%   if ( $conf->exists('cust_main-auto_standardize_address') ) {
+
+    standardize_address();
+    cf.submit();
+
+%   } else {
+
+    // popup a confirmation popup
+
+    var confirm_change =
+      '<CENTER><BR><B>Confirm address standardization</B><BR><BR>' +
+      '<TABLE>';
+    
+    if ( changed ) {
+
+      confirm_change = confirm_change + 
+        '<TR><TH>Entered billing address</TH>' +
+          '<TH>Standardized billing address</TH></TR>';
+        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+      
+      if ( argsHash['company'] || argsHash['new_company'] ) {
+        confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['company'] +
+          '</TD><TD>' + argsHash['new_company'] + '</TD></TR>';
+      }
+      
+      confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['address1'] +
+          '</TD><TD>' + argsHash['new_address1'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['address2'] +
+          '</TD><TD>' + argsHash['new_address2'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['city'] + ', ' + argsHash['state'] + '  ' + argsHash['zip'] +
+          '</TD><TD>' + argsHash['new_city'] + ', ' + argsHash['new_state'] + '  ' + argsHash['new_zip'] + '</TD></TR>' +
+          '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+    }
+
+    if ( ship_changed ) {
+
+      confirm_change = confirm_change + 
+        '<TR><TH>Entered service address</TH>' +
+          '<TH>Standardized service address</TH></TR>';
+        // + '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+      
+      if ( argsHash['ship_company'] || argsHash['new_ship_company'] ) {
+        confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['ship_company'] +
+          '</TD><TD>' + argsHash['new_ship_company'] + '</TD></TR>';
+      }
+      
+      confirm_change = confirm_change +
+        '<TR><TD>' + argsHash['ship_address1'] +
+          '</TD><TD>' + argsHash['new_ship_address1'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['ship_address2'] +
+          '</TD><TD>' + argsHash['new_ship_address2'] + '</TD></TR>' +
+        '<TR><TD>' + argsHash['ship_city'] + ', ' + argsHash['ship_state'] + '  ' + argsHash['ship_zip'] +
+          '</TD><TD>' + argsHash['new_ship_city'] + ', ' + argsHash['new_ship_state'] + '  ' + argsHash['new_ship_zip'] + '</TD></TR>' +
+        '<TR><TD>&nbsp;</TD><TD>&nbsp;</TD></TR>';
+
+    }
+
+    var addresses = 'address';
+    var height = 268;
+    if ( changed && ship_changed ) {
+      addresses = 'addresses';
+      height = 396; // #what
+    }
+
+    confirm_change = confirm_change +
+      '<TR><TD>' +
+        '<BUTTON TYPE="button" onClick="document.CustomerForm.submit();"><IMG SRC="<%$p%>images/error.png" ALT=""> Use entered ' + addresses + '</BUTTON>' + 
+      '</TD><TD>' +
+        '<BUTTON TYPE="button" onClick="standardize_address(); document.CustomerForm.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Use standardized ' + addresses + '</BUTTON>' + 
+      '</TD></TR>' +
+      '<TR><TD COLSPAN=2 ALIGN="center">' +
+        '<BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission</BUTTON></TD></TR>' +
+        
+      '</TABLE></CENTER>';
+
+    overlib( confirm_change, CAPTION, 'Confirm address standardization', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, height, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+%   }
+
+  } else {
+
+    cf.submit();
+
+  }
+
+}
+
+function update_geocode() {
+
+  //yay closures
+  set_geocode = function (what) {
+
+    var cf = document.CustomerForm;
+
+    //alert(what.options[what.selectedIndex].value);
+    var argsHash = eval('(' + what.options[what.selectedIndex].value + ')');
+    cf.elements['<% $taxpre %>city'].value     = argsHash['city'];
+    setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
+    cf.elements['<% $taxpre %>zip'].value      = argsHash['zip'];
+    cf.elements['geocode'].value  = argsHash['geocode'];
+
+  }
+
+  // popup a chooser
+
+  overlib( OLresponseAJAX, CAPTION, 'Select tax location', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', TEXTSIZE, 3 );
+
+}
+
+function copyelement(from, to) {
+  if ( from == undefined ) {
+    to.value = '';
+  } else if ( from.type == 'select-one' ) {
+    to.value = from.options[from.selectedIndex].value;
+    //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
+  } else if ( from.type == 'checkbox' ) {
+    if ( from.checked ) {
+      to.value = from.value;
+    } else {
+      to.value = '';
+    }
+  } else {
+    if ( from.value == undefined ) {
+      to.value = '';
+    } else {
+      to.value = from.value;
+    }
+  }
+  //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
+}
+
+function setselect(el, value) {
+
+  for ( var s = 0; s < el.options.length; s++ ) {
+     if ( el.options[s].value == value ) {
+       el.selectedIndex = s;
+     }
+  }
+
+}
+<%init>
+
+my $conf = new FS::Conf;
+
+my $taxpre = $conf->exists('tax-ship_address') ? 'ship_' : '';
+
+</%init>
index bd8b95c..2a41926 100644 (file)
@@ -26,8 +26,8 @@
 </SELECT><BR><BR>
 
 <TABLE><TR>
-  <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes')); document.bottomform.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
-  <TD><BUTTON TYPE="button" onClick="document.bottomform.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
+  <TD> <BUTTON TYPE="button" onClick="set_geocode(document.getElementById('geocodes')); document.CustomerForm.submit();"><IMG SRC="<%$p%>images/tick.png" ALT=""> Set location </BUTTON></TD>
+  <TD><BUTTON TYPE="button" onClick="document.CustomerForm.submitButton.disabled=false; parent.cClick();"><IMG SRC="<%$p%>images/cross.png" ALT=""> Cancel submission </BUTTON></TD>
 </TR>
 </TABLE>
 
diff --git a/httemplate/edit/cust_main/first_pkg.html b/httemplate/edit/cust_main/first_pkg.html
new file mode 100644 (file)
index 0000000..0de33c0
--- /dev/null
@@ -0,0 +1,55 @@
+% if ( @part_pkg ) {
+
+    <BR><BR>
+    <FONT SIZE="+1"><B>First package</B></FONT>
+    <% ntable("#cccccc") %>
+
+      <TR>
+        <TD COLSPAN=2>
+          <% include('first_pkg/select-part_pkg.html',
+                       'part_pkg' => \@part_pkg,
+                       %opt,
+                       # map { $_ => $opt{$_} } qw( pkgpart_svcpart saved_domsvc )
+                    )
+          %>
+
+% } 
+<%init>
+
+my( $cust_main, %opt ) = @_;
+
+# pry the wrong place for this logic.  also pretty expensive
+
+#false laziness, copied from FS::cust_pkg::order
+my $pkgpart;
+my $agentnum = '';
+my @agents = $FS::CurrentUser::CurrentUser->agents;
+if ( scalar(@agents) == 1 ) {
+  # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
+  $pkgpart = $agents[0]->pkgpart_hashref;
+  $agentnum = $agents[0]->agentnum;
+} else {
+  #can't know (agent not chosen), so, allow all
+  $agentnum = 'all';
+  my %typenum;
+  foreach my $agent ( @agents ) {
+    next if $typenum{$agent->typenum}++;
+    $pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
+  }
+}
+#eslaf
+
+my @first_svc = ( 'svc_acct', 'svc_phone' );
+
+my @part_pkg =
+  grep { $_->svcpart(\@first_svc)
+         && ( $pkgpart->{ $_->pkgpart } 
+              || $agentnum eq 'all'
+              || ( $agentnum ne 'all' && $agentnum && $_->agentnum
+                   && $_->agentnum == $agentnum
+                 )
+            )
+       }
+  qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/select-part_pkg.html b/httemplate/edit/cust_main/first_pkg/select-part_pkg.html
new file mode 100644 (file)
index 0000000..1b62035
--- /dev/null
@@ -0,0 +1,164 @@
+<% include('/elements/xmlhttp.html',
+              'url'  => $p.'misc/svc_acct-domains.cgi',
+              'subs' => [ $opt{'prefix'}. 'get_domains' ],
+           )
+%>
+
+<% include('/elements/xmlhttp.html',
+              'url'  => $p.'misc/part_svc-columns.cgi',
+              'subs' => [ $opt{'prefix'}. 'get_part_svc' ],
+           )
+%>
+
+<SCRIPT TYPE="text/javascript">
+
+  function selopt(what,value,text,selected) {
+    var optionName = new Option(text, value, false, selected);
+    var length = what.length;
+    what.options[length] = optionName;
+  }
+
+  var pkgpart_svcpart2svcdb = {
+%   foreach my $pkgpart ( map $_->pkgpart, @part_pkg ) {
+      "<% $pkgpart_svcpart{$pkgpart} %>":"<% $svcdb{$pkgpart} %>",
+%   }
+    '':''
+  };
+
+  function <% $opt{'prefix'} %>pkgpart_svcpart_changed_too(what,selected) {
+
+    pkgpart_svcpart = what.options[what.selectedIndex].value;
+
+    var svcdb = pkgpart_svcpart2svcdb[pkgpart_svcpart];
+
+    if ( svcdb == 'svc_acct' ) {
+
+      // go get the new domains
+      function <% $opt{'prefix'} %>update_domains(domains) {
+
+        // blank the current domain list
+        for ( var i = what.form.<% $opt{'prefix'} %>domsvc.length; i >= 0; i-- )
+            what.form.<% $opt{'prefix'} %>domsvc.options[i] = null;
+
+        // add the new domains
+        var domainArray = eval('(' + domains + ')' );
+        for ( var s = 0; s < domainArray.length; s=s+2 ) {
+            var domainLabel = domainArray[s+1];
+            if ( domainLabel == "" )
+                domainLabel = '(n/a)';
+            selopt( what.form.<% $opt{'prefix'} %>domsvc,
+                    domainArray[s],
+                    domainLabel,
+                    (domainArray[s] == selected) ? true : false
+                  );
+        }
+
+      }
+
+      <% $opt{'prefix'} %>get_domains( pkgpart_svcpart,
+                                       <% $opt{'prefix'} %>update_domains
+                                     );
+
+    } else if ( svcdb == 'svc_phone' ) {
+
+      function <% $opt{'prefix'} %>update_svc_phone(part_svc_column) {
+        var colArray = eval('(' + part_svc_column + ')' );
+        for ( var s = 0; s < colArray.length; s=s+3 ) {
+          var name  = colArray[s];
+          var flag  = colArray[s+1];
+          var value = colArray[s+2];
+          var td_label = document.getElementById(name+'_label_td');
+          var td       = document.getElementById(name+'_td');
+          var input    = document.getElementById(name);
+          if ( flag == 'D' ) {
+            if ( ! input.value ) { input.value = value; }
+            td_label.style.display = ''
+            td.style.display = ''
+          } else if ( flag == 'F' ) {
+            input.value = value;
+            td_label.style.display = 'none'
+            td.style.display = 'none'
+          } else {
+            td_label.style.display = ''
+            td.style.display = ''
+          }
+        }
+      }
+
+      <% $opt{'prefix'} %>get_part_svc( pkgpart_svcpart,
+                                        <% $opt{'prefix'} %>update_svc_phone
+                                      );
+
+    }
+
+  }
+
+</SCRIPT>
+
+<% include( '/elements/selectlayers.html',
+              'field'        => $opt{'prefix'}. 'pkgpart_svcpart',
+              'curr_value'   => $opt{pkgpart_svcpart},
+              'options'      => \@options,
+              'labels'       => \%labels,
+              'html_between' => '</TD></TR></TABLE>',
+              #'onchange'     => $opt{'prefix'}. 'pkgpart_svcpart_changed(this,0);',
+              'onchange'     => $opt{'prefix'}. 'pkgpart_svcpart_changed_too(what,0)',
+
+              'layer_callback' => $layer_callback,
+              'layermap'       => \%layermap,
+          )
+%>
+
+<SCRIPT TYPE="text/javascript">
+  pkgpart_svcpart_changed_too( document.CustomerForm.pkgpart_svcpart,
+                               <% $opt{saved_domsvc} %>
+                             );
+</SCRIPT>
+
+<%init>
+
+my %opt = @_;
+
+foreach my $opt (qw( svc_part pkgparts saved_pkgpart saved_domsvc prefix)) {
+  $opt{$_} = '' unless exists($opt{$_}) && defined($opt{$_});
+}
+$opt{saved_domsvc} = 0 unless $opt{saved_domsvc};
+
+my @part_pkg = @{$opt{'part_pkg'}};
+
+my @first_svc = ( 'svc_acct', 'svc_phone' );
+
+my %pkgpart_svcpart = ();
+my %svcdb = ();
+my %layermap = ();
+foreach my $part_pkg ( @part_pkg ) {
+  my $pkgpart = $part_pkg->pkgpart;
+  my $pkgpart_svcpart         = $pkgpart. "_". $part_pkg->svcpart(\@first_svc);
+  $pkgpart_svcpart{$pkgpart}  = $pkgpart_svcpart;
+  $svcdb{$pkgpart}            = $part_pkg->part_svc(\@first_svc)->svcdb;
+  $layermap{$pkgpart_svcpart} = $svcdb{$pkgpart};
+}
+
+my @options = ( '', map $pkgpart_svcpart{ $_->pkgpart }, @part_pkg );
+my %labels = ( '' => '(none)',
+               map { $pkgpart_svcpart{ $_->pkgpart }
+                       => $_->pkg. " - ". $_->comment
+                   }
+                   @part_pkg
+             );
+
+my $layer_callback = sub {
+  my $layer = shift;
+  #$layer_fields, $layer_values, $layer_prefix
+
+#  my( $pkgpart, $svcpart ) = split('_', $layer);
+#  my $svcdb = $svcdb{$pkgpart};
+  my $svcdb = $layer;
+
+  return '' unless $svcdb; #'<BR><BR><BR><BR><BR>'
+
+  #full path cause we're being slung around as a coderef (mason closures?)
+  include("/edit/cust_main/first_pkg/$svcdb.html", %opt, );
+};
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/svc_acct.html b/httemplate/edit/cust_main/first_pkg/svc_acct.html
new file mode 100644 (file)
index 0000000..91ee7a5
--- /dev/null
@@ -0,0 +1,58 @@
+<% ntable("#cccccc") %>
+
+  <TR>
+    <TD ALIGN="right">Username</TD>
+    <TD>
+      <INPUT TYPE      = "text"
+             NAME      = "username"
+             VALUE     = "<% $opt{'username'} %>"
+             SIZE      = <% $ulen2 %>
+             MAXLENGTH = <% $ulen %>
+      >
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Domain</TD>
+    <TD>
+      <SELECT NAME="domsvc">
+        <OPTION>(none)</OPTION>
+      </SELECT>
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Password</TD>
+    <TD>
+      <INPUT TYPE      = "text"
+             NAME      = "_password"
+             VALUE     = "<% $opt{'password'} %>"
+             SIZE      = <% $pmax2 %>
+             MAXLENGTH = <% $passwordmax %>>
+      (blank to generate)
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right">Access number</TD>
+    <TD><% FS::svc_acct_pop::popselector($opt{'popnum'}) %></TD>
+  </TR>
+
+</TABLE>
+
+<%init>
+
+#use FS::svc_acct_pop;
+
+my( %opt ) = @_;
+
+my $conf = new FS::Conf;
+
+#false laziness: (mostly) copied from edit/svc_acct.cgi
+#$ulen = $svc_acct->dbdef_table->column('username')->length;
+my $ulen = dbdef->table('svc_acct')->column('username')->length;
+my $ulen2 = $ulen+2;
+my $passwordmax = $conf->config('passwordmax') || 8;
+my $pmax2 = $passwordmax + 2;
+
+</%init>
diff --git a/httemplate/edit/cust_main/first_pkg/svc_phone.html b/httemplate/edit/cust_main/first_pkg/svc_phone.html
new file mode 100644 (file)
index 0000000..70e013e
--- /dev/null
@@ -0,0 +1,82 @@
+<% ntable("#cccccc") %>
+
+%#XXX this should be hidden or something in most/all cases
+  <TR>
+    <TD ALIGN="right" ID="countrycode_label_td">Country code</TD>
+    <TD ID="countrycode_td">
+      <INPUT TYPE      = "text"
+             NAME      = "countrycode"
+             ID        = "countrycode"
+             VALUE     = "<% $opt{'countrycode'} %>"
+             SIZE      = 4
+             MAXLENGTH = 3
+      >
+    </TD>
+  </TR>
+
+%#we don't know the svcpart until the dropdown is changed :/
+%#<% include('/elements/tr-select-did.html',
+%#             'label'      => 'Phone number',
+%#             'curr_value' => $opt{'phonenum'},
+%#          )
+%#%>
+  <TR>
+    <TD ALIGN="right" ID="phonenum_label_td">Phone Number</TD>
+    <TD ID="phonenum_td">
+      <INPUT TYPE      = "text"
+             NAME      = "phonenum"
+             ID        = "phonenum"
+             VALUE     = "<% $opt{'phonenum'} %>"
+             SIZE      = 21
+             MAXLENGTH = 20
+      >
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right" ID="sip_password_label_td">SIP password</TD>
+    <TD ID="sip_password_td">
+      <INPUT TYPE      = "text"
+             NAME      = "sip_password"
+             ID        = "sip_password"
+             VALUE     = "<% $opt{'sip_password'} %>"
+             MAXLENGTH = 80
+      >
+    </TD>
+  </TR>
+
+  <TR>
+    <TD ALIGN="right" ID="pin_label_td">Voicemail PIN</TD>
+    <TD ID="pin_td">
+      <INPUT TYPE      = "text"
+             NAME      = "pin"
+             ID        = "pin"
+             VALUE     = "<% $opt{'pin'} %>"
+             SIZE      = 5
+             MAXLENGTH = 4
+      >
+    </TD>
+  </TR>
+
+%#XXX this should be hidden or something in most/all cases
+  <TR>
+    <TD ALIGN="right" ID="phone_name_label_td">Name</TD>
+    <TD ID="phone_name_td">
+      <INPUT TYPE      = "text"
+             NAME      = "phone_name"
+             ID        = "phone_name"
+             VALUE     = "<% $opt{'phone_name'} %>"
+             MAXLENGTH = 80
+      >
+    </TD>
+  </TR>
+
+</TABLE>
+
+<%init>
+
+my( %opt ) = @_;
+
+#my $conf = new FS::Conf;
+
+</%init>
diff --git a/httemplate/edit/cust_main/select-domain.html b/httemplate/edit/cust_main/select-domain.html
deleted file mode 100644 (file)
index bec1e83..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-
-<% include('/elements/xmlhttp.html',
-              'url'  => $p.'misc/svc_acct-domains.cgi',
-              'subs' => [ $opt{'prefix'}. 'get_domains' ],
-           )
-%>
-
-<SCRIPT TYPE="text/javascript">
-
-  function selopt(what,value,text,selected) {
-    var optionName = new Option(text, value, false, selected);
-    var length = what.length;
-    what.options[length] = optionName;
-  }
-
-  function <% $opt{'prefix'} %>pkgpart_svcpart_changed(what,selected) {
-
-    pkgpart_svcpart = what.options[what.selectedIndex].value;
-
-    function <% $opt{'prefix'} %>update_domains(domains) {
-
-      // blank the current domain list
-      for ( var i = what.form.<% $opt{'prefix'} %>domsvc.length; i >= 0; i-- )
-          what.form.<% $opt{'prefix'} %>domsvc.options[i] = null;
-
-      // add the new domains
-      var domainArray = eval('(' + domains + ')' );
-      for ( var s = 0; s < domainArray.length; s=s+2 ) {
-          var domainLabel = domainArray[s+1];
-          if ( domainLabel == "" )
-              domainLabel = '(n/a)';
-          selopt(what.form.<% $opt{'prefix'} %>domsvc, domainArray[s], domainLabel, (domainArray[s] == selected) ? true : false);
-      }
-
-    }
-
-    // go get the new domains
-    <% $opt{'prefix'} %>get_domains( pkgpart_svcpart, <% $opt{'prefix'} %>update_domains );
-
-  }
-
-</SCRIPT>
-
-<SELECT NAME="<% $opt{'prefix'} %>pkgpart_svcpart" onchange="<% $opt{'prefix'} %>pkgpart_svcpart_changed(this,0);" >
-  <OPTION VALUE="">(none)
-
-% foreach my $part_pkg ( @part_pkg ) {
-
-  <OPTION VALUE="<% $part_pkg->pkgpart. "_". $part_pkg->svcpart('svc_acct') %>"<% ( $opt{saved_pkgpart} && $part_pkg->pkgpart == $opt{saved_pkgpart} ) ? ' SELECTED' : '' %>><% $part_pkg->pkg. " - ". $part_pkg->comment %>
-
-% } 
-
-</SELECT>
-<SCRIPT>
-  pkgpart_svcpart_changed(document.bottomform.pkgpart_svcpart, <% $opt{saved_domsvc} %>);
-</SCRIPT>
-
-<%init>
-my %opt = @_;
-foreach my $opt (qw( svc_part pkgparts saved_pkgpart saved_domsvc prefix)) {
-  $opt{$_} = '' unless exists($opt{$_}) && defined($opt{$_});
-}
-$opt{saved_domsvc} = 0 unless $opt{saved_domsvc};
-my @part_pkg = @{$opt{'pkgparts'}};
-
-</%init>
-
diff --git a/httemplate/edit/cust_main/top_misc.html b/httemplate/edit/cust_main/top_misc.html
new file mode 100644 (file)
index 0000000..5aaa0b0
--- /dev/null
@@ -0,0 +1,87 @@
+<% &ntable("#cccccc") %>
+
+%# agent
+<% include('/elements/tr-select-agent.html', 
+              'curr_value'    => $cust_main->agentnum,
+              'label'         => "<B>${r}Agent</B>",
+              'empty_label'   => 'Select agent',
+              'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
+           )
+%>
+
+%# agent_custid
+% if ( $conf->exists('cust_main-edit_agent_custid') ) {
+
+    <TR>
+      <TD ALIGN="right">Customer identifier</TD>
+      <TD><INPUT TYPE="text" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>"></TD>
+    </TR>
+
+% } else {
+
+    <INPUT TYPE="hidden" NAME="agent_custid" VALUE="<% $cust_main->agent_custid %>">
+
+% }
+
+%# referral (advertising source)
+%my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
+%if ( $custnum && ! $conf->exists('editreferrals') ) {
+
+  <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
+
+% } else { 
+
+   <% include('/elements/tr-select-part_referral.html',
+                'curr_value' => $refnum
+             )
+   %>
+% } 
+
+
+%# referring customer
+%my $referring_cust_main = '';
+%if ( $cust_main->referral_custnum
+%     and $referring_cust_main =
+%           qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
+%) {
+
+  <TR>
+    <TD ALIGN="right">Referring customer</TD>
+    <TD>
+      <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
+    </TD>
+  </TR>
+  <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
+% } elsif ( ! $conf->exists('disable_customer_referrals') ) { 
+
+
+  <TR>
+    <TD ALIGN="right">Referring customer</TD>
+    <TD>
+      <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
+      <% include('/elements/search-cust_main.html',
+                    'field_name' => 'referral_custnum',
+                 )
+      %>
+    </TD>
+  </TR>
+% } else { 
+
+
+  <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
+% } 
+
+
+</TABLE>
+
+<%init>
+
+my( $cust_main, %opt ) = @_;
+
+my $custnum = $opt{'custnum'};
+
+my $conf = new FS::Conf;
+
+my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
+
+</%init>
index 097d382..2e58315 100755 (executable)
@@ -27,8 +27,7 @@ $cgi->param('tax','') unless defined $cgi->param('tax');
 
 $cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] );
 
-#my $payby = $cgi->param('payby');
-my $payby = $cgi->param('select'); # XXX key
+my $payby = $cgi->param('payby');
 
 my %noauto = (
   'CARD' => 'DCRD',
@@ -37,8 +36,6 @@ my %noauto = (
 $payby = $noauto{$payby}
   if ! $cgi->param('payauto') && exists $noauto{$payby};
 
-$cgi->param('payby', $payby);
-
 if ( $payby ) {
   if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
     $cgi->param('payinfo',
@@ -93,34 +90,39 @@ $new->setfield('paid', $cgi->param('paid') )
   if $cgi->param('paid');
 
 #perhaps this stuff should go to cust_main.pm
-my $cust_pkg = '';
-my $svc_acct = '';
 if ( $new->custnum eq '' ) {
 
+  my $cust_pkg = '';
+  my $svc;
+
   if ( $cgi->param('pkgpart_svcpart') ) {
+
     my $x = $cgi->param('pkgpart_svcpart');
     $x =~ /^(\d+)_(\d+)$/ or die "illegal pkgpart_svcpart $x\n";
     my($pkgpart, $svcpart) = ($1, $2);
+    my $part_pkg = qsearchs('part_pkg', { 'pkgpart' => $pkgpart } );
     #false laziness: copied from FS::cust_pkg::order (which should become a
     #FS::cust_main method)
     my(%part_pkg);
     # generate %part_pkg
     # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart
     my $agent = qsearchs('agent',{'agentnum'=> $new->agentnum });
-       #my($type_pkgs);
-       #foreach $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {
-       #  my($pkgpart)=$type_pkgs->pkgpart;
-       #  $part_pkg{$pkgpart}++;
-       #}
-    # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart
-    my $pkgpart_href = $agent->pkgpart_hashref;
-    #eslaf
-
-    # this should wind up in FS::cust_pkg!
-    $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum. ") can't ".
-               "purchase pkgpart ". $pkgpart
-      #unless $part_pkg{ $pkgpart };
-      unless $pkgpart_href->{ $pkgpart };
+
+    if ( $agent ) {
+      # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart
+      my $pkgpart_href = $agent->pkgpart_hashref
+        if $agent;
+      #eslaf
+
+      # this should wind up in FS::cust_pkg!
+      $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum.
+                 ") can't purchase pkgpart ". $pkgpart
+        #unless $part_pkg{ $pkgpart };
+        unless $pkgpart_href->{ $pkgpart }
+            || $agent->agentnum == $part_pkg->agentnum;
+    } else {
+      $error = 'Select agent';
+    }
 
     $cust_pkg = new FS::cust_pkg ( {
       #later         'custnum' => $custnum,
@@ -132,32 +134,49 @@ if ( $new->custnum eq '' ) {
 
     #$error ||= $cust_svc->check;
 
-    my %svc_acct = (
-                     'svcpart'   => $svcpart,
-                     'username'  => $cgi->param('username'),
-                     '_password' => $cgi->param('_password'),
-                     'popnum'    => $cgi->param('popnum'),
-                   );
-    $svc_acct{'domsvc'} = $cgi->param('domsvc')
-      if $cgi->param('domsvc');
+    my $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
+    my $svcdb = $part_svc->svcdb;
+
+    if ( $svcdb eq 'svc_acct' ) {
+
+      my %svc_acct = (
+                       'svcpart'   => $svcpart,
+                       'username'  => scalar($cgi->param('username')),
+                       '_password' => scalar($cgi->param('_password')),
+                       'popnum'    => scalar($cgi->param('popnum')),
+                     );
+      $svc_acct{'domsvc'} = $cgi->param('domsvc')
+        if $cgi->param('domsvc');
+
+      $svc = new FS::svc_acct \%svc_acct;
+
+      #and just in case you were silly
+      $svc->svcpart($svcpart);
+      $svc->username($cgi->param('username'));
+      $svc->_password($cgi->param('_password'));
+      $svc->popnum($cgi->param('popnum'));
+
+    } elsif ( $svcdb eq 'svc_phone' ) {
+
+      my %svc_phone = (
+                        'svcpart' => $svcpart,
+                        map { $_ => scalar($cgi->param($_)) }
+                          qw( countrycode phonenum sip_password pin phone_name )
+                      );
 
-    $svc_acct = new FS::svc_acct \%svc_acct;
+      $svc = new FS::svc_phone \%svc_phone;
 
-    #and just in case you were silly
-    $svc_acct->svcpart($svcpart);
-    $svc_acct->username($cgi->param('username'));
-    $svc_acct->_password($cgi->param('_password'));
-    $svc_acct->popnum($cgi->param('popnum'));
+    } else {
+      die "$svcdb not handled on new customer yet";
+    }
 
     #$error ||= $svc_acct->check;
 
-  } elsif ( $cgi->param('username') ) { #good thing to catch
-    $error = "Can't assign username without a package!";
   }
 
   use Tie::RefHash;
   tie my %hash, 'Tie::RefHash';
-  %hash = ( $cust_pkg => [ $svc_acct ] ) if $cust_pkg;
+  %hash = ( $cust_pkg => [ $svc ] ) if $cust_pkg;
   $error ||= $new->insert( \%hash, \@invoicing_list );
 
   my $conf = new FS::Conf;
index a9998da..3372e06 100644 (file)
@@ -7,7 +7,7 @@
                           ' LEFT JOIN cust_pkg  USING ( pkgnum  ) '.
                           ' LEFT JOIN cust_main USING ( custnum ) ',
     'agent_virt'       => 1,
-    'agent_null-right' => 'View/link unlinked services',
+    'agent_null_right' => 'View/link unlinked services',
     @_,
    )
 %>
diff --git a/httemplate/elements/select-svc_acct-domain.html b/httemplate/elements/select-svc_acct-domain.html
new file mode 100644 (file)
index 0000000..c9a9206
--- /dev/null
@@ -0,0 +1,46 @@
+<SELECT NAME="domsvc" SIZE=1>
+% foreach my $svcnum (
+%                      sort { $svc_domain{$a} cmp $svc_domain{$b} }
+%                      keys %svc_domain
+%                    ) {
+%   my $svc_domain = $svc_domain{$svcnum};
+%   my $selected = ($svcnum == $domsvc) ? ' SELECTED' : ''
+
+    <OPTION VALUE="<% $svcnum %>" <% $selected %>><% $svc_domain{$svcnum} %>
+
+% } 
+
+</SELECT>
+<%init>
+
+my %opt = @_;
+
+my $domsvc = $opt{'curr_value'};
+my $part_svc = $opt{'part_svc'}
+               || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} });
+
+#optional
+my $cust_pkg = $opt{'cust_pkg'};
+$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} })
+  if $opt{'pkgnum'};
+
+my $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : '';
+
+my %svc_domain = ();
+
+if ( $domsvc ) {
+  my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $domsvc } );
+  if ( $svc_domain ) {
+    $svc_domain{$svc_domain->svcnum} = $svc_domain;
+  } else {
+    warn "unknown svc_domain.svcnum for svc_acct.domsvc: $domsvc";
+  }
+}
+
+%svc_domain = (
+  %svc_domain,
+  FS::svc_acct->domain_select_hash( 'svcpart' => $part_svc->svcpart,
+                                    'pkgnum'  => $pkgnum,
+                                  )
+);
+</%init>
index 82f5dd1..a85cea1 100644 (file)
@@ -63,18 +63,29 @@ Example:
     <SCRIPT TYPE="text/javascript">
 % }
 % unless ( grep $opt{$_}, qw(html_only select_only layers_only) ) {
-      //alert('start function define');
+
+%     if ( $opt{layermap} ) {
+%       my %map = %{ $opt{layermap} };
+        var layermap = { "":"",
+                         <% join(',', map { qq("$_":"$map{$_}") } keys %map ) %>
+                       };
+%     }
+
       function <% $key %>changed(what) {
 
         <% $opt{'onchange'} %>
 
         var <% $key %>layer = what.options[what.selectedIndex].value;
 
-%       foreach my $layer ( keys %$options ) {
-
+%       foreach my $layer ( @layers ) {
+%
+%         if ( $opt{layermap} ) {
+          if ( layermap[ <% $key %>layer ] == "<% $layer %>" ) {
+%         } else {
           if (<% $key %>layer == "<% $layer %>" ) {
+%         }
 
-%           foreach my $not ( grep { $_ ne $layer } keys %$options ) {
+%           foreach my $not ( grep { $_ ne $layer } @layers ) {
 %             my $element = "document.getElementById('${key}d$not').style";
               <% $element %>.display = "none";
               <% $element %>.zIndex = 0;
@@ -90,7 +101,6 @@ Example:
         //<% $opt{'onchange'} %>
 
       }
-      //alert('end function define');
 % }
 % unless ( grep $opt{$_}, qw(html_only js_only select_only layers_only) ) {
     </SCRIPT>
@@ -124,10 +134,16 @@ Example:
 %
 % unless ( grep $opt{$_}, qw(js_only select_only) ) {
 
-%   foreach my $layer ( keys %$options ) {
+%   foreach my $layer ( @layers ) {
+%     my $selected_layer;
+%     if ( $opt{layermap} ) {
+%       $selected_layer = $opt{layermap}->{$selected};
+%     } else {
+%       $selected_layer = $selected;
+%     }
 
       <DIV ID="<% $key %>d<% $layer %>"
-           STYLE="<% $layer eq $selected
+           STYLE="<% $selected_layer eq $layer
                        ? 'display: ""  ; z-index: 1'
                        : 'display: none; z-index: 0'
                   %>"
@@ -162,6 +178,14 @@ tie my %options, 'Tie::IxHash',
 my $between = exists($opt{html_between}) ? $opt{html_between} : '';
 my $options = \%options;
 
+my @layers = ();
+if ( $opt{layermap} ) {
+  my %layers = map { $opt{layermap}->{$_} => 1 } keys %options;
+  @layers = keys %layers;
+} else {
+  @layers = keys %options;
+}
+
 my $selected = exists($opt{curr_value}) ? $opt{curr_value} : '';
 
 #XXX eek.  also eek $layer_fields in the layer_callback() call...
diff --git a/httemplate/misc/part_svc-columns.cgi b/httemplate/misc/part_svc-columns.cgi
new file mode 100644 (file)
index 0000000..0602561
--- /dev/null
@@ -0,0 +1,13 @@
+<% objToJson(\@output) %>
+<%init>
+
+my $conf = new FS::Conf;
+
+my $pkgpart_svcpart = $cgi->param('arg');
+$pkgpart_svcpart =~ /^\d+_(\d+)$/;
+my $part_svc = qsearchs('part_svc', { 'svcpart' => $1 }) if $1;
+
+my @output = map { ( $_->columnname, $_->columnflag, $_->columnvalue ) }
+                 $part_svc->all_part_svc_column;
+
+</%init>