add cust_main-require_address2 config, reimplement address2-search config ("Unit...
[freeside.git] / httemplate / edit / cust_main.cgi
1 %
2 %
3 %  #for misplaced logic below
4 %  #use FS::part_pkg;
5 %
6 %  #for false laziness below (now more properly lazy)
7 %  #use FS::svc_acct_pop;
8 %
9 %  #for (other) false laziness below
10 %  #use FS::agent;
11 %  #use FS::type_pkgs;
12 %
13 %my $conf = new FS::Conf;
14 %
15 %#get record
16 %
17 %my $error = '';
18 %my($custnum, $username, $password, $popnum, $cust_main, $saved_pkgpart, $saved_domsvc);
19 %my(@invoicing_list);
20 %my ($ss,$stateid,$payinfo);
21 %my $same = '';
22 %if ( $cgi->param('error') ) {
23 %  $error = $cgi->param('error');
24 %  $cust_main = new FS::cust_main ( {
25 %    map { $_, scalar($cgi->param($_)) } fields('cust_main')
26 %  } );
27 %  $custnum = $cust_main->custnum;
28 %  $saved_domsvc = $cgi->param('domsvc') || '';
29 %  if ( $saved_domsvc =~ /^(\d+)$/ ) {
30 %    $saved_domsvc = $1;
31 %  } else {
32 %    $saved_domsvc = '';
33 %  }
34 %  $saved_pkgpart = $cgi->param('pkgpart_svcpart') || '';
35 %  if ( $saved_pkgpart =~ /^(\d+)_/ ) {
36 %    $saved_pkgpart = $1;
37 %  } else {
38 %    $saved_pkgpart = '';
39 %  }
40 %  $username = $cgi->param('username');
41 %  $password = $cgi->param('_password');
42 %  $popnum = $cgi->param('popnum');
43 %  @invoicing_list = split( /\s*,\s*/, $cgi->param('invoicing_list') );
44 %  $same = $cgi->param('same');
45 %  $cust_main->setfield('paid' => $cgi->param('paid')) if $cgi->param('paid');
46 %  $ss = $cust_main->ss;           # don't mask an entered value on errors
47 %  $stateid = $cust_main->stateid; # don't mask an entered value on errors
48 %  $payinfo = $cust_main->payinfo; # don't mask an entered value on errors
49 %} elsif ( $cgi->keywords ) { #editing
50 %  my( $query ) = $cgi->keywords;
51 %  $query =~ /^(\d+)$/;
52 %  $custnum=$1;
53 %  $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
54 %  if ( $cust_main->dbdef_table->column('paycvv')
55 %       && length($cust_main->paycvv)             ) {
56 %    my $paycvv = $cust_main->paycvv;
57 %    $paycvv =~ s/./*/g;
58 %    $cust_main->paycvv($paycvv);
59 %  }
60 %  $saved_pkgpart = 0;
61 %  $saved_domsvc = 0;
62 %  $username = '';
63 %  $password = '';
64 %  $popnum = 0;
65 %  @invoicing_list = $cust_main->invoicing_list;
66 %  $ss = $cust_main->masked('ss');
67 %  $stateid = $cust_main->masked('stateid');
68 %  $payinfo = $cust_main->paymask;
69 %} else {
70 %  $custnum='';
71 %  $cust_main = new FS::cust_main ( {} );
72 %  $cust_main->otaker( &getotaker );
73 %  $cust_main->referral_custnum( $cgi->param('referral_custnum') );
74 %  $saved_pkgpart = 0;
75 %  $saved_domsvc = 0;
76 %  $username = '';
77 %  $password = '';
78 %  $popnum = 0;
79 %  @invoicing_list = ();
80 %  push @invoicing_list, 'POST'
81 %    unless $conf->exists('disablepostalinvoicedefault');
82 %  $ss = '';
83 %  $stateid = '';
84 %  $payinfo = '';
85 %}
86 %$cgi->delete_all();
87 %
88 %my $action = $custnum ? 'Edit' : 'Add';
89 %$action .= ": ". $cust_main->name if $custnum;
90 %
91 %my $r = qq!<font color="#ff0000">*</font>&nbsp;!;
92 %
93 %
94
95
96 <!-- top -->
97
98 <% include('/elements/header.html',
99       "Customer $action",
100       '',
101       ' onUnload="myclose()"'
102 ) %>
103 % if ( $error ) { 
104
105 <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error %></FONT><BR><BR>
106 % } 
107
108
109 <FORM NAME="topform" STYLE="margin-bottom: 0">
110 <INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum %>">
111 % if ( $custnum ) { 
112
113   Customer #<B><% $custnum %></B> - 
114   <B><FONT COLOR="#<% $cust_main->statuscolor %>">
115     <% ucfirst($cust_main->status) %>
116   </FONT></B>
117   <BR><BR>
118 % } 
119
120
121 <% &ntable("#cccccc") %>
122
123 <!-- agent -->
124
125 <% include('/elements/tr-select-agent.html', 
126               'curr_value'    => $cust_main->agentnum,
127               'label'         => "<B>${r}Agent</B>",
128               'empty_label'   => 'Select agent',
129               'disable_empty' => ( $cust_main->agentnum ? 1 : 0 ),
130            )
131 %>
132
133 <!-- referral (advertising source) -->
134 %
135 %my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
136 %if ( $custnum && ! $conf->exists('editreferrals') ) {
137 %
138
139
140   <INPUT TYPE="hidden" NAME="refnum" VALUE="<% $refnum %>">
141 % } else { 
142
143
144    <% include('/elements/tr-select-part_referral.html',
145                 'curr_value' => $refnum
146              )
147    %>
148 % } 
149
150
151 <!-- referring customer -->
152 %
153 %my $referring_cust_main = '';
154 %if ( $cust_main->referral_custnum
155 %     and $referring_cust_main =
156 %           qsearchs('cust_main', { custnum => $cust_main->referral_custnum } )
157 %) {
158 %
159
160
161   <TR>
162     <TD ALIGN="right">Referring customer</TD>
163     <TD>
164       <A HREF="<% popurl(1) %>/cust_main.cgi?<% $cust_main->referral_custnum %>"><% $cust_main->referral_custnum %>: <% $referring_cust_main->name %></A>
165     </TD>
166   </TR>
167   <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<% $cust_main->referral_custnum %>">
168 % } elsif ( ! $conf->exists('disable_customer_referrals') ) { 
169
170
171   <TR>
172     <TD ALIGN="right">Referring customer</TD>
173     <TD>
174       <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> -->
175       <% include('/elements/search-cust_main.html',
176                     'field_name' => 'referral_custnum',
177                  )
178       %>
179     </TD>
180   </TR>
181 % } else { 
182
183
184   <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">
185 % } 
186
187
188 </TABLE>
189
190 <!-- birthdate -->
191
192 % if ( $conf->exists('cust_main-enable_birthdate') ) {
193
194   <BR>
195   <% ntable("#cccccc", 2) %>
196   <% include ('/elements/tr-input-date-field.html',
197               'birthdate',
198               $cust_main->birthdate,
199               'Date of Birth',
200               $conf->config('date_format') || "%m/%d/%Y",
201               1)
202   %>
203
204   </TABLE>
205
206 % }
207
208 <!-- contact info -->
209
210 %  my $same_checked = '';
211 %  my $ship_disabled = '';
212 %  unless ( $cust_main->ship_last && $same ne 'Y' ) {
213 %    $same_checked = 'CHECKED';
214 %    $ship_disabled = 'DISABLED STYLE="background-color: #dddddd"';
215 %    foreach (
216 %      qw( last first company address1 address2 city county state zip country
217 %          daytime night fax )
218 %    ) {
219 %      $cust_main->set("ship_$_", $cust_main->get($_) );
220 %    }
221 %  }
222
223 <BR><BR>
224 Billing address
225 <% include('cust_main/contact.html',
226              'cust_main'    => $cust_main,
227              'pre'          => '',
228              'onchange'     => 'bill_changed(this)',
229              'disabled'     => '',
230              'ss'           => $ss,
231              'stateid'      => $stateid,
232              'same_checked' => $same_checked, #for address2 "Unit #" labeling
233           )
234 %>
235
236 <SCRIPT>
237 function bill_changed(what) {
238   if ( what.form.same.checked ) {
239 % for (qw( last first company address1 address2 city zip daytime night fax )) { 
240
241     what.form.ship_<%$_%>.value = what.form.<%$_%>.value;
242 % } 
243
244     what.form.ship_country.selectedIndex = what.form.country.selectedIndex;
245
246     function fix_ship_county() {
247       what.form.ship_county.selectedIndex = what.form.county.selectedIndex;
248     }
249
250     function fix_ship_state() {
251       what.form.ship_state.selectedIndex = what.form.state.selectedIndex;
252       ship_state_changed(what.form.ship_state, fix_ship_county );
253     }
254
255     ship_country_changed(what.form.ship_country, fix_ship_state );
256
257   }
258 }
259 function samechanged(what) {
260   if ( what.checked ) {
261     bill_changed(what);
262
263 %   for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
264       what.form.ship_<%$_%>.disabled = true;
265       what.form.ship_<%$_%>.style.backgroundColor = '#dddddd';
266 %   } 
267
268 %   if ( $conf->exists('cust_main-require_address2') ) {
269       document.getElementById('address2_required').style.visibility = '';
270       document.getElementById('address2_label').style.visibility = '';
271       document.getElementById('ship_address2_required').style.visibility = 'hidden';
272       document.getElementById('ship_address2_label').style.visibility = 'hidden';
273 %   }
274
275   } else {
276
277 %   for (qw( last first company address1 address2 city county state zip country daytime night fax )) { 
278       what.form.ship_<%$_%>.disabled = false;
279       what.form.ship_<%$_%>.style.backgroundColor = '#ffffff';
280 %   } 
281
282 %   if ( $conf->exists('cust_main-require_address2') ) {
283       document.getElementById('address2_required').style.visibility = 'hidden';
284       document.getElementById('address2_label').style.visibility = 'hidden';
285       document.getElementById('ship_address2_required').style.visibility = '';
286       document.getElementById('ship_address2_label').style.visibility = '';
287 %   }
288
289   }
290 }
291 </SCRIPT>
292
293 <BR>
294 Service address 
295 (<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%$same_checked%>>same as billing address)
296 <% include('cust_main/contact.html',
297              'cust_main' => $cust_main,
298              'pre'       => 'ship_',
299              'onchange'  => '',
300              'disabled'  => $ship_disabled,
301           )
302 %>
303
304
305 <!-- billing info -->
306
307 <% include( 'cust_main/billing.html', $cust_main,
308                'payinfo'        => $payinfo,
309                'invoicing_list' => \@invoicing_list,
310            )
311 %>
312
313 <SCRIPT>
314 function bottomfixup(what) {
315
316   var topvars = new Array(
317     'birthdate',
318
319     'custnum', 'agentnum', 'refnum', 'referral_custnum',
320
321     'last', 'first', 'ss', 'company',
322     'address1', 'address2', 'city',
323     'county', 'state', 'zip', 'country',
324     'daytime', 'night', 'fax',
325     'stateid', 'stateid_state',
326
327     'same',
328
329     'ship_last', 'ship_first', 'ship_company',
330     'ship_address1', 'ship_address2', 'ship_city',
331     'ship_county', 'ship_state', 'ship_zip', 'ship_country',
332     'ship_daytime','ship_night', 'ship_fax',
333
334     'select' // XXX key
335   );
336
337   var layervars = new Array(
338     'payauto',
339     'payinfo', 'payinfo1', 'payinfo2', 'paytype',
340     'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
341     'paystart_month', 'paystart_year', 'payissue',
342     'payip',
343     'paid'
344   );
345
346   var billing_bottomvars = new Array(
347     'tax',
348     'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
349     'invoice_terms',
350     'spool_cdr'
351   );
352
353   for ( f=0; f < topvars.length; f++ ) {
354     var field = topvars[f];
355     copyelement( document.topform.elements[field],
356                  document.bottomform.elements[field]
357                );
358   }
359
360   var layerform = document.topform.select.options[document.topform.select.selectedIndex].value;
361   for ( f=0; f < layervars.length; f++ ) {
362     var field = layervars[f];
363     copyelement( document.forms[layerform].elements[field],
364                  document.bottomform.elements[field]
365                );
366   }
367
368   for ( f=0; f < billing_bottomvars.length; f++ ) {
369     var field = billing_bottomvars[f];
370     copyelement( document.billing_bottomform.elements[field],
371                  document.bottomform.elements[field]
372                );
373   }
374
375 }
376
377 function copyelement(from, to) {
378   if ( from == undefined ) {
379     to.value = '';
380   } else if ( from.type == 'select-one' ) {
381     to.value = from.options[from.selectedIndex].value;
382     //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
383   } else if ( from.type == 'checkbox' ) {
384     if ( from.checked ) {
385       to.value = from.value;
386     } else {
387       to.value = '';
388     }
389   } else {
390     if ( from.value == undefined ) {
391       to.value = '';
392     } else {
393       to.value = from.value;
394     }
395   }
396   //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
397 }
398
399 </SCRIPT>
400
401 <FORM ACTION="<% popurl(1) %>process/cust_main.cgi" METHOD=POST NAME="bottomform" onSubmit="document.bottomform.submit.disabled=true; bottomfixup(this.form);" STYLE="margin-top: 0; margin-bottom: 0">
402 % foreach my $hidden (
403 %     'birthdate',
404 %
405 %     'custnum', 'agentnum', 'refnum', 'referral_custnum',
406 %     'last', 'first', 'ss', 'company',
407 %     'address1', 'address2', 'city',
408 %     'county', 'state', 'zip', 'country',
409 %     'daytime', 'night', 'fax',
410 %     'stateid', 'stateid_state',
411 %     
412 %     'same',
413 %     
414 %     'ship_last', 'ship_first', 'ship_company',
415 %     'ship_address1', 'ship_address2', 'ship_city',
416 %     'ship_county', 'ship_state', 'ship_zip', 'ship_country',
417 %     'ship_daytime','ship_night', 'ship_fax',
418 %     
419 %     'select', #XXX key
420 %
421 %     'payauto',
422 %     'payinfo', 'payinfo1', 'payinfo2', 'paytype',
423 %     'payname', 'paystate', 'exp_month', 'exp_year', 'paycvv',
424 %     'paystart_month', 'paystart_year', 'payissue',
425 %     'payip',
426 %     'paid',
427 %     
428 %     'tax',
429 %     'invoicing_list', 'invoicing_list_POST', 'invoicing_list_FAX',
430 %     'invoice_terms',
431 %     'spool_cdr'
432 %   ) {
433 %
434
435   <INPUT TYPE="hidden" NAME="<% $hidden %>" VALUE="">
436 % } 
437 %
438 % my $ro_comments = $conf->exists('cust_main-use_comments')?'':'readonly';
439 % if (!$ro_comments || $cust_main->comments) {
440
441 <BR>Comments
442 <% &ntable("#cccccc") %>
443   <TR>
444     <TD>
445       <TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments" <%$ro_comments%>><% $cust_main->comments %></TEXTAREA>
446     </TD>
447   </TR>
448 </TABLE>
449 %
450 % }
451 %
452 %unless ( $custnum ) {
453 %  # pry the wrong place for this logic.  also pretty expensive
454 %  #use FS::part_pkg;
455 %
456 %  #false laziness, copied from FS::cust_pkg::order
457 %  my $pkgpart;
458 %  my @agents = $FS::CurrentUser::CurrentUser->agents;
459 %  if ( scalar(@agents) == 1 ) {
460 %    # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
461 %    $pkgpart = $agents[0]->pkgpart_hashref;
462 %  } else {
463 %    #can't know (agent not chosen), so, allow all
464 %    my %typenum;
465 %    foreach my $agent ( @agents ) {
466 %      next if $typenum{$agent->typenum}++;
467 %      #fixed in 5.004_05 #$pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
468 %      foreach ( keys %{ $agent->pkgpart_hashref } ) { $pkgpart->{$_}++; } #5.004_04 workaround
469 %    }
470 %  }
471 %  #eslaf
472 %
473 %  my @part_pkg = grep { $_->svcpart('svc_acct') && $pkgpart->{ $_->pkgpart } }
474 %    qsearch( 'part_pkg', { 'disabled' => '' }, '', 'ORDER BY pkg' ); # case?
475 %
476 %  if ( @part_pkg ) {
477 %
478 %    #    print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"),
479 %    #apiabuse & undesirable wrapping
480 %
481 %    
482
483     <BR>First package
484     <% ntable("#cccccc") %>
485     
486       <TR>
487         <TD COLSPAN=2>
488           <% include('cust_main/select-domain.html',
489                        'pkgparts'      => \@part_pkg,
490                        'saved_pkgpart' => $saved_pkgpart,
491                        'saved_domsvc' => $saved_domsvc,
492                     )
493           %>
494         </TD>
495       </TR>
496
497 %        #false laziness: (mostly) copied from edit/svc_acct.cgi
498 %        #$ulen = $svc_acct->dbdef_table->column('username')->length;
499 %        my $ulen = dbdef->table('svc_acct')->column('username')->length;
500 %        my $ulen2 = $ulen+2;
501 %        my $passwordmax = $conf->config('passwordmax') || 8;
502 %        my $pmax2 = $passwordmax + 2;
503 %      
504
505     
506       <TR>
507         <TD ALIGN="right">Username</TD>
508         <TD>
509           <INPUT TYPE="text" NAME="username" VALUE="<% $username %>" SIZE=<% $ulen2 %> MAXLENGTH=<% $ulen %>>
510         </TD>
511       </TR>
512     
513       <TR>
514         <TD ALIGN="right">Domain</TD>
515         <TD>
516           <SELECT NAME="domsvc">
517             <OPTION>(none)</OPTION>
518           </SELECT>
519         </TD>
520       </TR>
521     
522       <TR>
523         <TD ALIGN="right">Password</TD>
524         <TD>
525           <INPUT TYPE="text" NAME="_password" VALUE="<% $password %>" SIZE=<% $pmax2 %> MAXLENGTH=<% $passwordmax %>>
526           (blank to generate)
527         </TD>
528       </TR>
529     
530       <TR>
531         <TD ALIGN="right">Access number</TD>
532         <TD><% FS::svc_acct_pop::popselector($popnum) %></TD>
533       </TR>
534     </TABLE>
535 % } 
536 % } 
537
538
539 <INPUT TYPE="hidden" NAME="otaker" VALUE="<% $cust_main->otaker %>">
540 <BR>
541 <INPUT TYPE="submit" NAME="submit" VALUE="<% $custnum ?  "Apply Changes" : "Add Customer" %>">
542 <BR>
543 </FORM>
544
545 <% include('/elements/footer.html') %>
546