- bring prepaid support into this century (close: Bug#1124)
[freeside.git] / fs_selfservice / FS-SelfService / cgi / agent.cgi
1 #!/usr/bin/perl -Tw
2
3 #some false laziness w/selfservice.cgi
4
5 use strict;
6 use vars qw($DEBUG $me $cgi $session_id $form_max $template_dir);
7 use subs qw(do_template);
8 use CGI;
9 use CGI::Carp qw(fatalsToBrowser);
10 use Business::CreditCard;
11 use Text::Template;
12 #use HTML::Entities;
13 use FS::SelfService qw( agent_login agent_logout agent_info
14                         agent_list_customers
15                         signup_info new_customer
16                         customer_info list_pkgs order_pkg
17                         part_svc_info provision_acct provision_external
18                         unprovision_svc
19                       );
20
21 $DEBUG = 0;
22 $me = 'agent.cgi:';
23
24 $template_dir = '.';
25
26 $form_max = 255;
27
28 warn "$me starting\n" if $DEBUG;
29
30 warn "$me initializing CGI\n" if $DEBUG;
31 $cgi = new CGI;
32
33 unless ( defined $cgi->param('session') ) {
34   warn "$me no session defined, sending login page\n" if $DEBUG;
35   do_template('agent_login',{});
36   exit;
37 }
38
39 if ( $cgi->param('session') eq 'login' ) {
40
41   warn "$me processing login\n" if $DEBUG;
42
43   $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i
44     or die "illegal username";
45   my $username = $1;
46
47   $cgi->param('password') =~ /^(.{0,$form_max})$/
48     or die "illegal password";
49   my $password = $1;
50
51   my $rv = agent_login(
52     'username' => $username,
53     'password' => $password,
54   );
55   if ( $rv->{error} ) {
56     do_template('agent_login', {
57       'error'    => $rv->{error},
58       'username' => $username,
59     } );
60     exit;
61   } else {
62     $cgi->param('session' => $rv->{session_id} );
63     $cgi->param('action'  => 'agent_main' );
64   }
65 }
66
67 $session_id = $cgi->param('session');
68
69 warn "$me checking action\n" if $DEBUG;
70 $cgi->param('action') =~
71    /^(agent_main|signup|process_signup|list_customers|view_customer|agent_provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|agent_order_pkg|process_order_pkg|logout)$/
72   or die "unknown action ". $cgi->param('action');
73 my $action = $1;
74
75 warn "$me running $action\n" if $DEBUG;
76 my $result = eval "&$action();";
77 die $@ if $@;
78
79 if ( $result->{error} eq "Can't resume session" ) { #ick
80   do_template('agent_login',{});
81   exit;
82 }
83
84 warn "$me processing template $action\n" if $DEBUG;
85 do_template($action, {
86   'session_id' => $session_id,
87   %{$result}
88 });
89 warn "$me done processing template $action\n" if $DEBUG;
90
91 #-- 
92
93 sub logout {
94   $action = 'agent_logout';
95   agent_logout( 'session_id' => $session_id );
96 }
97
98 sub agent_main { agent_info( 'session_id' => $session_id ); }
99
100 sub signup { signup_info( 'session_id' => $session_id ); }
101
102 sub process_signup {
103
104   my $init_data = signup_info( 'session_id' => $session_id );
105   if ( $init_data->{'error'} ) {
106     if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
107       do_template('agent_login',{});
108       exit;
109     } else { #?
110       die $init_data->{'error'};
111     }
112   }
113
114   my $error = '';
115
116   #false laziness w/signup.cgi, identical except for agentnum vs session_id
117   my $payby = $cgi->param('payby');
118   if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
119     #$payinfo = join('@', map { $cgi->param( $payby. "_payinfo$_" ) } (1,2) );
120     $cgi->param('payinfo' => $cgi->param($payby. '_payinfo1'). '@'. 
121                              $cgi->param($payby. '_payinfo2')
122                );
123   } else {
124     $cgi->param('payinfo' => $cgi->param( $payby. '_payinfo' ) );
125   }
126   $cgi->param('paydate' => $cgi->param( $payby. '_month' ). '-'.
127                            $cgi->param( $payby. '_year' )
128              );
129   $cgi->param('payname' => $cgi->param( $payby. '_payname' ) );
130   $cgi->param('paycvv' => defined $cgi->param( $payby. '_paycvv' )
131                             ? $cgi->param( $payby. '_paycvv' )
132                             : ''
133              );
134
135   if ( $cgi->param('invoicing_list') ) {
136     $cgi->param('invoicing_list' => $cgi->param('invoicing_list'). ', POST')
137       if $cgi->param('invoicing_list_POST');
138   } else {
139     $cgi->param('invoicing_list' => 'POST' );
140   }
141
142   if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
143     $error = $init_data->{msgcat}{passwords_dont_match}; #msgcat
144     $cgi->param('_password', '');
145     $cgi->param('_password2', '');
146   }
147
148   if ( $payby =~ /^(CARD|DCRD)$/ && $cgi->param('CARD_type') ) {
149     my $payinfo = $cgi->param('payinfo');
150     $payinfo =~ s/\D//g;
151
152     $payinfo =~ /^(\d{13,16})$/
153       or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
154     $payinfo = $1;
155     validate($payinfo)
156       or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
157     cardtype($payinfo) eq $cgi->param('CARD_type')
158       or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
159   }
160
161   unless ( $error ) {
162     my $rv = new_customer ( {
163       'session_id'       => $session_id,
164       map { $_ => scalar($cgi->param($_)) }
165         qw( last first ss company
166             address1 address2 city county state zip country
167             daytime night fax
168
169             ship_last ship_first ship_company
170             ship_address1 ship_address2 ship_city ship_county ship_state
171               ship_zip ship_country
172             ship_daytime ship_night ship_fax
173
174             payby payinfo paycvv paydate payname invoicing_list
175             referral_custnum promo_code reg_code
176             pkgpart username sec_phrase _password popnum refnum
177           ),
178         grep { /^snarf_/ } $cgi->param
179     } );
180     $error = $rv->{'error'};
181   }
182   #eslaf
183
184   if ( $error ) { 
185     $action = 'signup';
186     my $r = { 
187       $cgi->Vars,
188       %{$init_data},
189       'error' => $error,
190     };
191     #warn join('\n', map "$_ => $r->{$_}", keys %$r )."\n";
192     $r;
193   } else {
194     $action = 'agent_main';
195     my $agent_info = agent_info( 'session_id' => $session_id );
196     $agent_info->{'message'} = 'Signup sucessful';
197     $agent_info;
198   }
199
200 }
201
202 sub list_customers {
203
204   my $results = 
205     agent_list_customers( 'session_id' => $session_id,
206                           map { $_ => $cgi->param($_) }
207                             grep defined($cgi->param($_)),
208                                  qw(prospect active susp cancel),
209                                  'search',
210                         );
211
212   if ( scalar( @{$results->{'customers'}} ) == 1 ) {
213     $action = 'view_customer';
214     customer_info (
215       'agent_session_id' => $session_id,
216       'custnum'          => $results->{'customers'}[0]{'custnum'},
217     );
218   } else {
219     $results;
220   }
221
222 }
223
224 sub view_customer {
225
226   #my $init_data = signup_info( 'session_id' => $session_id );
227   #if ( $init_data->{'error'} ) {
228   #  if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
229   #    do_template('agent_login',{});
230   #    exit;
231   #  } else { #?
232   #    die $init_data->{'error'};
233   #  }
234   #}
235   #
236   #my $customer_info =
237   customer_info (
238     'agent_session_id' => $session_id,
239     'custnum'          => $cgi->param('custnum'),
240   );
241   #
242   #return {
243   #  ( map { $_ => $init_data->{$_} }
244   #        qw( part_pkg security_phrase svc_acct_pop ),
245   #  ),
246   #  %$customer_info,
247   #};
248 }
249
250 sub agent_order_pkg {
251
252   my $init_data = signup_info( 'session_id' => $session_id );
253   if ( $init_data->{'error'} ) {
254     if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
255       do_template('agent_login',{});
256       exit;
257     } else { #?
258       die $init_data->{'error'};
259     }
260   }
261
262   my $customer_info = customer_info (
263     'agent_session_id' => $session_id,
264     'custnum'          => $cgi->param('custnum'),
265   );
266
267   return {
268     ( map { $_ => $init_data->{$_} }
269           qw( part_pkg security_phrase svc_acct_pop ),
270     ),
271     %$customer_info,
272   };
273
274 }
275
276 sub agent_provision {
277   my $result = list_pkgs(
278     'agent_session_id' => $session_id,
279     'custnum'          => $cgi->param('custnum'),
280   );
281   die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
282   $result;
283 }
284
285 sub provision_svc {
286
287   my $result = part_svc_info(
288     'agent_session_id' => $session_id,
289     map { $_ => $cgi->param($_) } qw( pkgnum svcpart custnum ),
290   );
291   die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
292
293   $result->{'svcdb'} =~ /^svc_(.*)$/
294     #or return { 'error' => 'Unknown svcdb '. $result->{'svcdb'} };
295     or die 'Unknown svcdb '. $result->{'svcdb'};
296   $action .= "_$1";
297   $action = "agent_$action";
298
299   $result;
300 }
301
302 sub process_svc_acct {
303
304   my $result = provision_acct (
305     'agent_session_id' => $session_id,
306     map { $_ => $cgi->param($_) } qw(
307       custnum pkgnum svcpart username _password _password2 sec_phrase popnum )
308   );
309
310   if ( exists $result->{'error'} && $result->{'error'} ) { 
311     #warn "$result $result->{'error'}"; 
312     $action = 'provision_svc_acct';
313     $action = "agent_$action";
314     return {
315       $cgi->Vars,
316       %{ part_svc_info( 'agent_session_id' => $session_id,
317                         map { $_ => $cgi->param($_) } qw(pkgnum svcpart custnum)
318                       )
319       },
320       'error' => $result->{'error'},
321     };
322   } else {
323     #warn "$result $result->{'error'}"; 
324     $action = 'agent_provision';
325     return {
326       %{agent_provision()},
327       'message' => $result->{'svc'}. ' setup sucessfully.',
328     };
329   }
330
331 }
332
333 sub process_svc_external {
334
335   my $result = provision_external (
336     'agent_session_id' => $session_id,
337     map { $_ => $cgi->param($_) } qw( custnum pkgnum svcpart )
338   );
339
340   #warn "$result $result->{'error'}"; 
341   $action = 'agent_provision';
342   return {
343     %{agent_provision()},
344     'message' => $result->{'error'}
345                    ? '<FONT COLOR="#FF0000">'. $result->{'error'}. '</FONT>'
346                    : $result->{'svc'}. ' setup sucessfully'.
347                      ': serial number '.
348                      sprintf('%010d', $result->{'id'}). '-'. $result->{'title'}
349   };
350
351 }
352
353 sub delete_svc {
354   my $result = unprovision_svc(
355     'agent_session_id' => $session_id,
356     'custnum'          => $cgi->param('custnum'),
357     'svcnum'           => $cgi->param('svcnum'),
358   );
359
360   $action = 'agent_provision';
361
362   return {
363     %{agent_provision()},
364     'message' => $result->{'error'}
365                    ? '<FONT COLOR="#FF0000">'. $result->{'error'}. '</FONT>'
366                    : $result->{'svc'}. ' removed.'
367   };
368
369 }
370
371 sub process_order_pkg {
372
373   my $results = '';
374
375   unless ( length($cgi->param('_password')) ) {
376     my $init_data = signup_info( 'session_id' => $session_id );
377     #die $init_data->{'error'} if $init_data->{'error'};
378     $results = { 'error' => $init_data->{msgcat}{empty_password} };
379   }
380   if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
381     my $init_data = signup_info( 'session_id' => $session_id );
382     $results = { 'error' => $init_data->{msgcat}{passwords_dont_match} };
383     $cgi->param('_password', '');
384     $cgi->param('_password2', '');
385   }
386
387   $results ||= order_pkg (
388     'agent_session_id' => $session_id,
389     map { $_ => $cgi->param($_) }
390         qw( custnum pkgpart username _password _password2 sec_phrase popnum )
391   );
392
393   if ( $results->{'error'} ) {
394     $action = 'agent_order_pkg';
395     return {
396       $cgi->Vars,
397       %{agent_order_pkg()},
398       #'message' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
399       'error' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
400     };
401   } else {
402     $action = 'view_customer';
403     #$cgi->delete( grep { $_ ne 'custnum' } $cgi->param );
404     return {
405       %{view_customer()},
406       'message' => 'Package order sucessful.',
407     };
408   }
409
410 }
411
412 #--
413
414 sub do_template {
415   my $name = shift;
416   my $fill_in = shift;
417   #warn join(' / ', map { "$_=>".$fill_in->{$_} } keys %$fill_in). "\n";
418
419   $cgi->delete_all();
420   $fill_in->{'selfurl'} = $cgi->self_url; #OLD
421   $fill_in->{'self_url'} = $cgi->self_url;
422   $fill_in->{'cgi'} = \$cgi;
423
424   my $template = new Text::Template( TYPE    => 'FILE',
425                                      SOURCE  => "$template_dir/$name.html",
426                                      DELIMITERS => [ '<%=', '%>' ],
427                                      UNTAINT => 1,                    )
428     or die $Text::Template::ERROR;
429
430   local $^W = 0;
431   print $cgi->header( '-expires' => 'now' ),
432         $template->fill_in( PACKAGE => 'FS::SelfService::_agentcgi',
433                             HASH    => $fill_in
434                           );
435 }
436
437 package FS::SelfService::_agentcgi;
438
439 use HTML::Entities;
440 use FS::SelfService qw(regionselector expselect popselector);
441
442 #false laziness w/selfservice.cgi
443 sub include {
444   my $name = shift;
445   my $template = new Text::Template( TYPE   => 'FILE',
446                                      SOURCE => "$main::template_dir/$name.html",
447                                      DELIMITERS => [ '<%=', '%>' ],
448                                      UNTAINT => 1,                   
449                                    )
450     or die $Text::Template::ERROR;
451
452   $template->fill_in( PACKAGE => 'FS::SelfService::_agentcgi',
453                       #HASH    => $fill_in
454                     );
455
456 }
457