add agent email, RT#18231
[freeside.git] / FS / FS / ClientAPI / Agent.pm
1 package FS::ClientAPI::Agent;
2
3 #some false laziness w/MyAccount
4
5 use strict;
6 use vars qw($cache);
7 use subs qw(_cache);
8 use Digest::MD5 qw(md5_hex);
9 use FS::Record qw(qsearchs); # qsearch dbdef dbh);
10 use FS::ClientAPI_SessionCache;
11 use FS::agent;
12 use FS::cust_main::Search qw(smart_search);
13 use FS::svc_domain;
14 use FS::svc_acct;
15
16 sub _cache {
17   $cache ||= new FS::ClientAPI_SessionCache( {
18                'namespace' => 'FS::ClientAPI::Agent',
19              } );
20 }
21
22 sub new_agent {
23   my $p = shift;
24
25   my $conf = new FS::Conf;
26   return { error=>'Disabled' } unless $conf->exists('selfservice-agent_signup');
27
28   #add a customer record and set agent_custnum?
29
30   my $agent = new FS::agent {
31     'typenum'   => $conf->config('selfservice-agent_signup-agent_type'),
32     'agent'     => $p->{'agent'},
33     'username'  => $p->{'username'},
34     '_password' => $p->{'password'},
35     #
36   };
37
38   my $error = $agent->insert;
39   
40   return { 'error' => $error } if $error;
41
42   agent_login({ 'username' => $p->{'username'},
43                 'password' => $p->{'password'},
44              });
45 }
46
47 sub agent_login {
48   my $p = shift;
49
50   #don't allow a blank login to first unconfigured agent with no user/pass
51   return { error => 'Must specify your reseller username and password.' }
52     unless length($p->{'username'}) && length($p->{'password'});
53
54   my $agent = qsearchs( 'agent', {
55     'username'  => $p->{'username'},
56     '_password' => $p->{'password'},
57   } );
58
59   unless ( $agent ) { return { error => 'Incorrect password.' } }
60
61   my $session = { 
62     'agentnum' => $agent->agentnum,
63     'agent'    => $agent->agent,
64   };
65
66   my $session_id;
67   do {
68     $session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
69   } until ( ! defined _cache->get($session_id) ); #just in case
70
71   _cache->set( $session_id, $session, '1 hour' );
72
73   { 'error'      => '',
74     'session_id' => $session_id,
75   };
76 }
77
78 sub agent_logout {
79   my $p = shift;
80   if ( $p->{'session_id'} ) {
81     _cache->remove($p->{'session_id'});
82     return { 'error' => '' };
83   } else {
84     return { 'error' => "Can't resume session" }; #better error message
85   }
86 }
87
88 sub agent_info {
89   my $p = shift;
90
91   my $session = _cache->get($p->{'session_id'})
92     or return { 'error' => "Can't resume session" }; #better error message
93
94   #my %return;
95
96   my $agentnum = $session->{'agentnum'};
97
98   my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
99     or return { 'error' => "unknown agentnum $agentnum" };
100
101   { 'error'        => '',
102     'agentnum'     => $agentnum,
103     'agent'        => $agent->agent,
104     'num_prospect' => $agent->num_prospect_cust_main,
105     'num_active'   => $agent->num_active_cust_main,
106     'num_susp'     => $agent->num_susp_cust_main,
107     'num_cancel'   => $agent->num_cancel_cust_main,
108     #%return,
109   };
110
111 }
112
113 sub agent_list_customers {
114   my $p = shift;
115
116   my $session = _cache->get($p->{'session_id'})
117     or return { 'error' => "Can't resume session" }; #better error message
118
119   #my %return;
120
121   my $agentnum = $session->{'agentnum'};
122
123   my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
124     or return { 'error' => "unknown agentnum $agentnum" };
125
126   my @cust_main = smart_search( 'search'   => $p->{'search'},
127                                 'agentnum' => $agentnum,
128                               );
129
130   #aggregate searches
131   push @cust_main,
132     map $agent->$_(), map $_.'_cust_main',
133       grep $p->{$_}, qw( prospect active susp cancel );
134
135   #eliminate dups?
136   my %saw = ();
137   @cust_main = grep { !$saw{$_->custnum}++ } @cust_main;
138
139   { customers => [ map {
140                          my $cust_main = $_;
141                          my $hashref = $cust_main->hashref;
142                          $hashref->{$_} = $cust_main->$_()
143                            foreach qw(name status statuscolor);
144                          delete $hashref->{$_} foreach qw( payinfo paycvv );
145                          $hashref;
146                    } @cust_main
147                  ],
148   }
149
150 }
151
152 sub check_username {
153   my $p = shift;
154   my($session, $agentnum, $svc_acct) = _session_agentnum_svc_acct($p);
155   return { 'error' => $session } unless ref($session);
156
157   { 'error'     => '',
158     #'username'  => $username,
159     #'domain'    => $domain,
160     'available' => $svc_acct ? 0 : 1,
161   };
162
163 }
164
165 sub _session_agentnum_svc_acct {
166   my $p = shift;
167
168   my $session = _cache->get($p->{'session_id'})
169     or return "Can't resume session"; #better error message
170
171   my $username = $p->{'username'};
172
173   #XXX some way to default this per agent (by default product's service def?)
174   my $domain = $p->{'domain'};
175
176   my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } )
177     or return { 'error' => 'Unknown domain' };
178
179   my $svc_acct = qsearchs('svc_acct', { 'username' => $username,
180                                         'domsvc'   => $svc_domain->svcnum, } );
181
182   ( $session, $session->{'agentnum'}, $svc_acct );
183
184 }
185
186 sub _session_agentnum_cust_pkg {
187   my $p = shift;
188   my($session, $agentnum, $svc_acct) = _session_agentnum_svc_acct($p);
189   return $session unless ref($session);
190   return 'Account not found' unless $svc_acct;
191   my $cust_svc = $svc_acct->cust_svc;
192   return 'Unlinked account' unless $cust_svc->pkgnum;
193   my $cust_pkg = $cust_svc->cust_pkg;
194   return 'Not your account' unless $cust_pkg->cust_main->agentnum == $agentnum;
195   ($session, $agentnum, $cust_pkg);
196 }
197
198 sub suspend_username {
199   my $p = shift;
200   my($session, $agentnum, $cust_pkg) = _session_agentnum_cust_pkg($p);
201   return { 'error' => $session } unless ref($session);
202
203   return { 'error' => $cust_pkg->suspend };
204 }
205
206 sub unsuspend_username {
207   my $p = shift;
208   my($session, $agentnum, $cust_pkg) = _session_agentnum_cust_pkg($p);
209   return { 'error' => $session } unless ref($session);
210
211   return { 'error' => $cust_pkg->unsuspend };
212 }
213
214 1;