diff options
| -rw-r--r-- | FS/FS/part_pkg.pm | 34 | ||||
| -rwxr-xr-x | httemplate/edit/cust_main.cgi | 675 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/billing.html | 134 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/birthdate.html | 15 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/bottomfixup.html | 12 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/bottomfixup.js | 278 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/choose_tax_location.html | 4 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/first_pkg.html | 55 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/first_pkg/select-part_pkg.html | 164 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/first_pkg/svc_acct.html | 58 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/first_pkg/svc_phone.html | 82 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/select-domain.html | 67 | ||||
| -rw-r--r-- | httemplate/edit/cust_main/top_misc.html | 87 | ||||
| -rwxr-xr-x | httemplate/edit/process/cust_main.cgi | 93 | ||||
| -rw-r--r-- | httemplate/elements/select-domain.html | 2 | ||||
| -rw-r--r-- | httemplate/elements/select-svc_acct-domain.html | 46 | ||||
| -rw-r--r-- | httemplate/elements/selectlayers.html | 38 | ||||
| -rw-r--r-- | httemplate/misc/part_svc-columns.cgi | 13 | 
18 files changed, 1074 insertions, 783 deletions
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 8cf7d0ca1..8cfd6143c 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -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. diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 098de848e..7308c72da 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -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 ) {  @@ -19,101 +23,16 @@    <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 = ''; @@ -129,7 +48,8 @@  %  }  <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> </TD><TD> </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> </TD><TD> </TD></TR>'; - -    } - -    if ( ship_changed ) { - -      confirm_change = confirm_change +  -        '<TR><TH>Entered service address</TH>' + -          '<TH>Standardized service address</TH></TR>'; -        // + '<TR><TD> </TD><TD> </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> </TD><TD> </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'); diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html index e175e21cc..353f2b9a0 100644 --- a/httemplate/edit/cust_main/billing.html +++ b/httemplate/edit/cust_main/billing.html @@ -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) %>">  % }  @@ -27,24 +24,18 @@  %    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> !; -  <BR>Billing information +  <BR><FONT SIZE="+1"><B>Billing information</B></FONT>    <% &ntable("#cccccc") %>      <TR> @@ -128,13 +119,13 @@  %      '<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 : '' ),  %                 ). @@ -145,14 +136,14 @@  %  %          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, @@ -167,12 +158,12 @@  %                 ).  %  %        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>',  % @@ -181,21 +172,21 @@  %      '<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">!. @@ -203,14 +194,14 @@  %                    '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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -223,11 +214,11 @@  %      '<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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -243,13 +234,13 @@  %      '<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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -264,13 +255,13 @@  %      '<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 : '' ),  %                 ). @@ -290,7 +281,7 @@  %      '<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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -306,7 +297,7 @@  %      '<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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -322,7 +313,7 @@  %      '<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> </TD></TR>'.  %        '<TR><TD> </TD></TR>'. @@ -336,48 +327,33 @@  %  );  %  %  #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") %> @@ -457,8 +433,6 @@    </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 index 000000000..415aba3c4 --- /dev/null +++ b/httemplate/edit/cust_main/birthdate.html @@ -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 index 000000000..3eb43e0e5 --- /dev/null +++ b/httemplate/edit/cust_main/bottomfixup.html @@ -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 index 000000000..efe2215c8 --- /dev/null +++ b/httemplate/edit/cust_main/bottomfixup.js @@ -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> </TD><TD> </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> </TD><TD> </TD></TR>'; + +    } + +    if ( ship_changed ) { + +      confirm_change = confirm_change +  +        '<TR><TH>Entered service address</TH>' + +          '<TH>Standardized service address</TH></TR>'; +        // + '<TR><TD> </TD><TD> </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> </TD><TD> </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> diff --git a/httemplate/edit/cust_main/choose_tax_location.html b/httemplate/edit/cust_main/choose_tax_location.html index bd8b95cb6..2a4192632 100644 --- a/httemplate/edit/cust_main/choose_tax_location.html +++ b/httemplate/edit/cust_main/choose_tax_location.html @@ -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 index 000000000..0de33c025 --- /dev/null +++ b/httemplate/edit/cust_main/first_pkg.html @@ -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 index 000000000..1b62035b2 --- /dev/null +++ b/httemplate/edit/cust_main/first_pkg/select-part_pkg.html @@ -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 index 000000000..91ee7a56c --- /dev/null +++ b/httemplate/edit/cust_main/first_pkg/svc_acct.html @@ -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 index 000000000..70e013ece --- /dev/null +++ b/httemplate/edit/cust_main/first_pkg/svc_phone.html @@ -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 index bec1e834c..000000000 --- a/httemplate/edit/cust_main/select-domain.html +++ /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 index 000000000..5aaa0b0cc --- /dev/null +++ b/httemplate/edit/cust_main/top_misc.html @@ -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> !; + +</%init> diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi index 097d38204..2e58315d4 100755 --- a/httemplate/edit/process/cust_main.cgi +++ b/httemplate/edit/process/cust_main.cgi @@ -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; diff --git a/httemplate/elements/select-domain.html b/httemplate/elements/select-domain.html index a9998da06..3372e068f 100644 --- a/httemplate/elements/select-domain.html +++ b/httemplate/elements/select-domain.html @@ -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 index 000000000..c9a920636 --- /dev/null +++ b/httemplate/elements/select-svc_acct-domain.html @@ -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> diff --git a/httemplate/elements/selectlayers.html b/httemplate/elements/selectlayers.html index 82f5dd1a7..a85cea193 100644 --- a/httemplate/elements/selectlayers.html +++ b/httemplate/elements/selectlayers.html @@ -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 index 000000000..060256154 --- /dev/null +++ b/httemplate/misc/part_svc-columns.cgi @@ -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>  | 
