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