f331e5321eb7a624e92a439e030f38eb40c4d156
[freeside.git] / httemplate / edit / cust_main.cgi
1 <%
2 #<!-- $Id: cust_main.cgi,v 1.3 2001-08-12 00:07:55 ivan Exp $ -->
3
4 use vars qw( $cgi $custnum $action $cust_main $p1 @agents $agentnum 
5              $last $first $ss $company $address1 $address2 $city $zip 
6              $daytime $night $fax @invoicing_list $invoicing_list $payinfo
7              $payname %payby %paybychecked $refnum $otaker $r );
8 use vars qw ( $conf $saved_pkgpart $username $password $popnum $ulen $ulen2 );
9 use vars qw ( $error );
10 #use CGI::Switch;
11 use CGI;
12 use CGI::Carp qw(fatalsToBrowser);
13 use FS::UID qw(cgisuidsetup getotaker);
14 #use FS::Record qw(qsearch qsearchs fields);
15 use FS::Record qw(qsearch qsearchs fields dbdef);
16 use FS::CGI qw(header popurl itable table);
17 use FS::cust_main;
18 use FS::agent;
19 use FS::part_referral;
20 use FS::cust_main_county;
21
22   #for misplaced logic below
23   use FS::part_pkg;
24
25   #for false laziness below
26   use FS::svc_acct_pop;
27
28   #for (other) false laziness below
29   use FS::agent;
30   use FS::type_pkgs;
31
32 $conf = new FS::Conf;
33
34 #get record
35
36 $error = '';
37 if ( $cgi->param('error') ) {
38   $error = $cgi->param('error');
39   $cust_main = new FS::cust_main ( {
40     map { $_, scalar($cgi->param($_)) } fields('cust_main')
41   } );
42   $custnum = $cust_main->custnum;
43   $saved_pkgpart = $cgi->param('pkgpart_svcpart') || '';
44   if ( $saved_pkgpart =~ /^(\d+)_/ ) {
45     $saved_pkgpart = $1;
46   } else {
47     $saved_pkgpart = '';
48   }
49   $username = $cgi->param('username');
50   $password = $cgi->param('_password');
51   $popnum = $cgi->param('popnum');
52 } elsif ( $cgi->keywords ) { #editing
53   my( $query ) = $cgi->keywords;
54   $query =~ /^(\d+)$/;
55   $custnum=$1;
56   $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
57   $saved_pkgpart = 0;
58   $username = '';
59   $password = '';
60   $popnum = 0;
61 } else {
62   $custnum='';
63   $cust_main = new FS::cust_main ( {} );
64   $cust_main->setfield('otaker',&getotaker);
65   $saved_pkgpart = 0;
66   $username = '';
67   $password = '';
68   $popnum = 0;
69 }
70 $cgi->delete_all();
71 $action = $custnum ? 'Edit' : 'Add';
72
73 # top
74
75 $p1 = popurl(1);
76 print $cgi->header( '-expires' => 'now' ), header("Customer $action", '');
77 print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $error, "</FONT>"
78   if $error;
79
80 print qq!<FORM ACTION="${p1}process/cust_main.cgi" METHOD=POST NAME="form1">!,
81       qq!<INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum">!,
82       qq!Customer # !, ( $custnum ? $custnum : " (NEW)" ),
83       
84 ;
85
86 # agent
87
88 $r = qq!<font color="#ff0000">*</font>!;
89
90 @agents = qsearch( 'agent', {} );
91 #die "No agents created!" unless @agents;
92 die "You have not created any agents.  You must create at least one agent before adding a customer.  Go to ". popurl(2). "browse/agent.cgi and create one or more agents." unless @agents;
93 $agentnum = $cust_main->agentnum || $agents[0]->agentnum; #default to first
94 if ( scalar(@agents) == 1 ) {
95   print qq!<INPUT TYPE="hidden" NAME="agentnum" VALUE="$agentnum">!;
96 } else {
97   print qq!<BR><BR>${r}Agent <SELECT NAME="agentnum" SIZE="1">!;
98   my $agent;
99   foreach $agent (sort {
100     $a->agent cmp $b->agent;
101   } @agents) {
102       print '<OPTION VALUE="', $agent->agentnum, '"',
103       " SELECTED"x($agent->agentnum==$agentnum),
104       ">", $agent->agentnum,": ", $agent->agent;
105   }
106   print "</SELECT>";
107 }
108
109 #referral
110
111 $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0;
112 if ( $custnum && ! $conf->exists('editreferrals') ) {
113   print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$refnum">!;
114 } else {
115   my(@referrals) = qsearch('part_referral',{});
116   if ( scalar(@referrals) == 1 ) {
117     $refnum ||= $referrals[0]->refnum;
118     print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$refnum">!;
119   } else {
120     print qq!<BR><BR>${r}Referral <SELECT NAME="refnum" SIZE="1">!;
121     print "<OPTION> " unless $refnum;
122     my($referral);
123     foreach $referral (sort {
124       $a->refnum <=> $b->refnum;
125     } @referrals) {
126       print "<OPTION" . " SELECTED"x($referral->refnum==$refnum),
127       ">", $referral->refnum, ": ", $referral->referral;
128     }
129     print "</SELECT>";
130   }
131 }
132
133
134 # contact info
135
136 ($last,$first,$ss,$company,$address1,$address2,$city,$zip)=(
137   $cust_main->last,
138   $cust_main->first,
139   $cust_main->ss,
140   $cust_main->company,
141   $cust_main->address1,
142   $cust_main->address2,
143   $cust_main->city,
144   $cust_main->zip,
145 );
146
147 print "<BR><BR>Billing address", &itable("#cccccc"), <<END;
148 <TR><TH ALIGN="right">${r}Contact name<BR>(last, first)</TH><TD COLSPAN=3>
149 END
150
151 print <<END;
152 <INPUT TYPE="text" NAME="last" VALUE="$last"> , 
153 <INPUT TYPE="text" NAME="first" VALUE="$first">
154 END
155
156 print <<END;
157 </TD><TD ALIGN="right">SS#</TD><TD><INPUT TYPE="text" NAME="ss" VALUE="$ss" SIZE=11></TD></TR>
158 <TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="company" VALUE="$company" SIZE=70></TD></TR>
159 <TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="address1" VALUE="$address1" SIZE=70></TD></TR>
160 <TR><TD ALIGN="right">&nbsp;</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="address2" VALUE="$address2" SIZE=70></TD></TR>
161 <TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="city" VALUE="$city"></TD><TH ALIGN="right">${r}State/Country</TH><TD><SELECT NAME="state" SIZE="1">
162 END
163
164 $cust_main->country( $conf->config('countrydefault') || 'US' )
165   unless $cust_main->country;
166 $cust_main->state( $conf->config('statedefault') || 'CA' )
167   unless $cust_main->state || $cust_main->country ne 'US';
168 foreach ( qsearch('cust_main_county',{}) ) {
169   print "<OPTION";
170   print " SELECTED" if ( $cust_main->state eq $_->state
171                          && $cust_main->county eq $_->county 
172                          && $cust_main->country eq $_->country
173                        );
174   print ">",$_->state;
175   print " (",$_->county,")" if $_->county;
176   print " / ", $_->country;
177 }
178 print qq!</SELECT></TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="zip" VALUE="$zip" SIZE=10></TD></TR>!;
179
180 ($daytime,$night,$fax)=(
181   $cust_main->daytime,
182   $cust_main->night,
183   $cust_main->fax,
184 );
185
186 print <<END;
187 <TR><TD ALIGN="right">Day Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="daytime" VALUE="$daytime" SIZE=18></TD></TR>
188 <TR><TD ALIGN="right">Night Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="night" VALUE="$night" SIZE=18></TD></TR>
189 <TR><TD ALIGN="right">Fax</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="fax" VALUE="$fax" SIZE=12></TD></TR>
190 END
191
192 print "</TABLE>$r required fields<BR>";
193
194 # service address
195
196 if ( defined $cust_main->dbdef_table->column('ship_last') ) {
197
198   print "\n", <<END;
199   <SCRIPT>
200   function changed(what) {
201     what.form.same.checked = false;
202   }
203   function samechanged(what) {
204     if ( what.checked ) {
205 END
206 print "      what.form.ship_$_.value = what.form.$_.value;\n"
207   for (qw( last first company address1 address2 city zip daytime night fax ));
208 print <<END;
209       what.form.ship_state.selectedIndex = what.form.state.selectedIndex;
210     }
211   }
212   </SCRIPT>
213 END
214
215   print '<BR>Service address ',
216         '(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)"';
217   unless ( $cust_main->ship_last ) {
218     print ' CHECKED';
219     foreach (
220       qw( last first company address1 address2 city state zip daytime night fax)
221     ) {
222       $cust_main->set("ship_$_", $cust_main->get($_) );
223     }
224   }
225   print '>same as billing address)<BR>';
226
227   my($ship_last,$ship_first,$ship_company,$ship_address1,$ship_address2,$ship_city,$ship_zip)=(
228     $cust_main->ship_last,
229     $cust_main->ship_first,
230     $cust_main->ship_company,
231     $cust_main->ship_address1,
232     $cust_main->ship_address2,
233     $cust_main->ship_city,
234     $cust_main->ship_zip,
235   );
236
237   print &itable("#cccccc"), <<END;
238   <TR><TH ALIGN="right">${r}Contact name<BR>(last, first)</TH><TD COLSPAN=5>
239 END
240
241   print <<END;
242   <INPUT TYPE="text" NAME="ship_last" VALUE="$ship_last" onChange="changed(this)"> , 
243   <INPUT TYPE="text" NAME="ship_first" VALUE="$ship_first" onChange="changed(this)">
244 END
245
246   print <<END;
247   </TD></TR>
248   <TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_company" VALUE="$ship_company" SIZE=70 onChange="changed(this)"></TD></TR>
249   <TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address1" VALUE="$ship_address1" SIZE=70 onChange="changed(this)"></TD></TR>
250   <TR><TD ALIGN="right">&nbsp;</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address2" VALUE="$ship_address2" SIZE=70 onChange="changed(this)"></TD></TR>
251   <TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="ship_city" VALUE="$ship_city" onChange="changed(this)"></TD><TH ALIGN="right">${r}State/Country</TH><TD><SELECT NAME="ship_state" SIZE="1" onChange="changed(this)">
252 END
253
254   $cust_main->ship_country( $conf->config('countrydefault') || 'US' )
255     unless $cust_main->ship_country;
256   $cust_main->ship_state( $conf->config('statedefault') || 'CA' )
257     unless $cust_main->ship_state || $cust_main->ship_country ne 'US';
258   foreach ( qsearch('cust_main_county',{}) ) {
259     print "<OPTION";
260     print " SELECTED" if ( $cust_main->ship_state eq $_->state
261                            && $cust_main->ship_county eq $_->county 
262                            && $cust_main->ship_country eq $_->country
263                          );
264     print ">",$_->state;
265     print " (",$_->county,")" if $_->county;
266     print " / ", $_->country;
267   }
268   print qq!</SELECT></TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="ship_zip" VALUE="$ship_zip" SIZE=10 onChange="changed(this)"></TD></TR>!;
269
270   my($ship_daytime,$ship_night,$ship_fax)=(
271     $cust_main->ship_daytime,
272     $cust_main->ship_night,
273     $cust_main->ship_fax,
274   );
275
276   print <<END;
277   <TR><TD ALIGN="right">Day Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_daytime" VALUE="$ship_daytime" SIZE=18 onChange="changed(this)"></TD></TR>
278   <TR><TD ALIGN="right">Night Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_night" VALUE="$ship_night" SIZE=18 onChange="changed(this)"></TD></TR>
279   <TR><TD ALIGN="right">Fax</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_fax" VALUE="$ship_fax" SIZE=12 onChange="changed(this)"></TD></TR>
280 END
281
282   print "</TABLE>$r required fields<BR>";
283
284 }
285
286 # billing info
287
288 sub expselect {
289   my $prefix = shift;
290   my( $m, $y ) = (0, 0);
291   if ( scalar(@_) ) {
292     my $date = shift || '01-2000';
293     if ( $date  =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format
294       ( $m, $y ) = ( $2, $1 );
295     } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
296       ( $m, $y ) = ( $1, $3 );
297     } else {
298       die "unrecognized expiration date format: $date";
299     }
300   }
301
302   my $return = qq!<SELECT NAME="$prefix!. qq!_month" SIZE="1">!;
303   for ( 1 .. 12 ) {
304     $return .= "<OPTION";
305     $return .= " SELECTED" if $_ == $m;
306     $return .= ">$_";
307   }
308   $return .= qq!</SELECT>/<SELECT NAME="$prefix!. qq!_year" SIZE="1">!;
309   for ( 2001 .. 2037 ) {
310     $return .= "<OPTION";
311     $return .= " SELECTED" if $_ == $y;
312     $return .= ">$_";
313   }
314   $return .= "</SELECT>";
315
316   $return;
317 }
318
319 print "<BR>Billing information", &itable("#cccccc"),
320       qq!<TR><TD><INPUT TYPE="checkbox" NAME="tax" VALUE="Y"!;
321 print qq! CHECKED! if $cust_main->tax eq "Y";
322 print qq!>Tax Exempt</TD></TR>!;
323 print qq!<TR><TD><INPUT TYPE="checkbox" NAME="invoicing_list_POST" VALUE="POST"!;
324 @invoicing_list = $cust_main->invoicing_list;
325 print qq! CHECKED!
326   if ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list;
327 print qq!>Postal mail invoice</TD></TR>!;
328 $invoicing_list = join(', ', grep { $_ ne 'POST' } @invoicing_list );
329 print qq!<TR><TD>Email invoice <INPUT TYPE="text" NAME="invoicing_list" VALUE="$invoicing_list"></TD></TR>!;
330
331 print "<TR><TD>Billing type</TD></TR>",
332       "</TABLE>",
333       &table("#cccccc"), "<TR>";
334
335 ($payinfo, $payname)=(
336   $cust_main->payinfo,
337   $cust_main->payname,
338 );
339
340 %payby = (
341   'CARD' => qq!Credit card<BR>${r}<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="" MAXLENGTH=19><BR>${r}Exp !. expselect("CARD"). qq!<BR>${r}Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="">!,
342   'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE=""><BR>${r}Exp !. expselect("BILL", "12-2037"). qq!<BR>${r}Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="Accounts Payable">!,
343   'COMP' => qq!Complimentary<BR>${r}Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""><BR>${r}Exp !. expselect("COMP"),
344 );
345 %paybychecked = (
346   'CARD' => qq!Credit card<BR>${r}<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="$payinfo" MAXLENGTH=19><BR>${r}Exp !. expselect("CARD", $cust_main->paydate). qq!<BR>${r}Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="$payname">!,
347   'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE="$payinfo"><BR>${r}Exp !. expselect("BILL", $cust_main->paydate). qq!<BR>${r}Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="$payname">!,
348   'COMP' => qq!Complimentary<BR>${r}Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE="$payinfo"><BR>${r}Exp !. expselect("COMP", $cust_main->paydate),
349 );
350 for (qw(CARD BILL COMP)) {
351   print qq!<TD VALIGN=TOP><INPUT TYPE="radio" NAME="payby" VALUE="$_"!;
352   if ($cust_main->payby eq "$_") {
353     print qq! CHECKED> $paybychecked{$_}</TD>!;
354   } else {
355     print qq!> $payby{$_}</TD>!;
356   }
357 }
358
359 print "</TR></TABLE>$r required fields for each billing type";
360
361 if ( defined $cust_main->dbdef_table->column('comments') ) {
362     print "<BR><BR>Comments", &itable("#cccccc"),
363           qq!<TR><TD><TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments">!,
364           $cust_main->comments, "</TEXTAREA>",
365           "</TD></TR></TABLE>";
366 }
367
368 unless ( $custnum ) {
369   # pry the wrong place for this logic.  also pretty expensive
370   #use FS::part_pkg;
371
372   #false laziness, copied from FS::cust_pkg::order
373   my $pkgpart;
374   if ( scalar(@agents) == 1 ) {
375     # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART
376     my($agent)=qsearchs('agent',{'agentnum'=> $agentnum });
377     $pkgpart = $agent->pkgpart_hashref;
378   } else {
379     #can't know (agent not chosen), so, allow all
380     my %typenum;
381     foreach my $agent ( @agents ) {
382       next if $typenum{$agent->typenum}++;
383       #fixed in 5.004_05 #$pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref }
384       foreach ( keys %{ $agent->pkgpart_hashref } ) { $pkgpart->{$_}++; } #5.004_04 workaround
385     }
386   }
387   #eslaf
388
389   my @part_pkg = grep { $_->svcpart('svc_acct') && $pkgpart->{ $_->pkgpart } }
390     qsearch( 'part_pkg', {} );
391
392   if ( @part_pkg ) {
393
394     print "<BR><BR>First package", &itable("#cccccc"),
395           qq!<TR><TD COLSPAN=2><SELECT NAME="pkgpart_svcpart">!;
396
397     print qq!<OPTION VALUE="">(none)!;
398
399     foreach my $part_pkg ( @part_pkg ) {
400       print qq!<OPTION VALUE="!,
401 #              $part_pkg->pkgpart. "_". $pkgpart{ $part_pkg->pkgpart }, '"';
402               $part_pkg->pkgpart. "_". $part_pkg->svcpart, '"';
403       print " SELECTED" if $saved_pkgpart && ( $part_pkg->pkgpart == $saved_pkgpart );
404       print ">", $part_pkg->pkg, " - ", $part_pkg->comment;
405     }
406     print "</SELECT></TD></TR>";
407
408     #false laziness: (mostly) copied from edit/svc_acct.cgi
409     #$ulen = $svc_acct->dbdef_table->column('username')->length;
410     $ulen = dbdef->table('svc_acct')->column('username')->length;
411     $ulen2 = $ulen+2;
412     print <<END;
413 <TR><TD ALIGN="right">Username</TD>
414 <TD><INPUT TYPE="text" NAME="username" VALUE="$username" SIZE=$ulen2 MAXLENGTH=$ulen></TD></TR>
415 <TR><TD ALIGN="right">Password</TD>
416 <TD><INPUT TYPE="text" NAME="_password" VALUE="$password" SIZE=10 MAXLENGTH=8>
417 (blank to generate)</TD></TR>
418 END
419     print qq!<TR><TD ALIGN="right">POP</TD><TD><SELECT NAME="popnum" SIZE=1><OPTION> !;
420     my($svc_acct_pop);
421     foreach $svc_acct_pop ( qsearch ('svc_acct_pop',{} ) ) {
422     print qq!<OPTION VALUE="!, $svc_acct_pop->popnum, '"',
423           ( $popnum && $svc_acct_pop->popnum == $popnum ) ? ' SELECTED' : '', ">", 
424           $svc_acct_pop->popnum, ": ", 
425           $svc_acct_pop->city, ", ",
426           $svc_acct_pop->state,
427           " (", $svc_acct_pop->ac, ")/",
428           $svc_acct_pop->exch, "\n"
429         ;
430     }
431     print "</SELECT></TD></TR></TABLE>";
432   }
433 }
434
435 $otaker = $cust_main->otaker;
436 print qq!<INPUT TYPE="hidden" NAME="otaker" VALUE="$otaker">!,
437       qq!<BR><BR><INPUT TYPE="submit" VALUE="!,
438       $custnum ?  "Apply Changes" : "Add Customer", qq!">!,
439       "</FORM></BODY></HTML>",
440 ;
441
442 %>