export host selection per service, RT#17914
[freeside.git] / FS / FS / part_export / infostreet.pm
1 package FS::part_export::infostreet;
2
3 use vars qw(@ISA %info %infostreet2cust_main $DEBUG);
4 use Tie::IxHash;
5 use FS::UID qw(dbh);
6 use FS::part_export;
7
8 @ISA = qw(FS::part_export);
9
10 tie my %options, 'Tie::IxHash',
11   'url'      => { label=>'XML-RPC Access URL', },
12   'login'    => { label=>'InfoStreet login', },
13   'password' => { label=>'InfoStreet password', },
14   'groupID'  => { label=>'InfoStreet groupID', },
15 ;
16
17 %info = (
18   'svc'      => 'svc_acct',
19   'desc'     => 'Real-time export to InfoStreet streetSmartAPI',
20   'options'  => \%options,
21   'nodomain' => 'Y',
22   'no_machine' => 1,
23   'notes'    => <<'END'
24 Real-time export to
25 <a href="http://www.infostreet.com/">InfoStreet</a> streetSmartAPI.
26 Requires installation of
27 <a href="http://search.cpan.org/dist/Frontier-Client">Frontier::Client</a> from CPAN.
28 END
29 );
30
31 $DEBUG = 0;
32
33 %infostreet2cust_main = (
34   'firstName'   => 'first',
35   'lastName'    => 'last',
36   'address1'    => 'address1',
37   'address2'    => 'address2',
38   'city'        => 'city',
39   'state'       => 'state',
40   'zipCode'     => 'zip',
41   'country'     => 'country',
42   'phoneNumber' => 'daytime',
43   'faxNumber'   => 'night', #noment-request...
44 );
45
46 sub rebless { shift; }
47
48 sub _export_insert {
49   my( $self, $svc_acct ) = (shift, shift);
50   my $cust_main = $svc_acct->cust_svc->cust_pkg->cust_main;
51
52   local $SIG{HUP} = 'IGNORE';
53   local $SIG{INT} = 'IGNORE';
54   local $SIG{QUIT} = 'IGNORE';
55   local $SIG{TERM} = 'IGNORE';
56   local $SIG{TSTP} = 'IGNORE';
57   local $SIG{PIPE} = 'IGNORE';
58   my $oldAutoCommit = $FS::UID::AutoCommit;
59   local $FS::UID::AutoCommit = 0;
60   my $dbh = dbh;
61
62   my $err_or_queue = $self->infostreet_err_or_queue( $svc_acct->svcnum,
63     'createUser', $svc_acct->username, $svc_acct->_password );
64   return $err_or_queue unless ref($err_or_queue);
65   my $jobnum = $err_or_queue->jobnum;
66
67   my %contact_info = ( map {
68     $_ => $cust_main->getfield( $infostreet2cust_main{$_} );
69   } keys %infostreet2cust_main );
70
71   my @emails = grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;
72   $contact_info{'email'} = $emails[0] if @emails;
73
74   #this one is kinda noment-specific
75   $contact_info{'organization'} = $cust_main->agent->agent;
76
77   $err_or_queue = $self->infostreet_queueContact( $svc_acct->svcnum,
78     $svc_acct->username, %contact_info );
79   return $err_or_queue unless ref($err_or_queue);
80
81   # If a quota has been specified set the quota because it is not the default
82   $err_or_queue = $self->infostreet_queueSetQuota( $svc_acct->svcnum, 
83     $svc_acct->username, $svc_acct->quota ) if $svc_acct->quota;
84   return $err_or_queue unless ref($err_or_queue);
85
86   my $error = $err_or_queue->depend_insert( $jobnum );
87   return $error if $error;
88
89   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
90
91   '';
92
93 }
94
95 sub _export_replace {
96   my( $self, $new, $old ) = (shift, shift, shift);
97   return "can't change username with InfoStreet"
98     if $old->username ne $new->username;
99
100   # If the quota has changed then do the export to setQuota
101   my $err_or_queue = $self->infostreet_queueSetQuota( $new->svcnum, $new->username, $new->quota ) 
102         if ( $old->quota != $new->quota );  
103   return $err_or_queue unless ref($err_or_queue);
104
105
106   return '' unless $old->_password ne $new->_password;
107   $self->infostreet_queue( $new->svcnum,
108     'passwd', $new->username, $new->_password );
109 }
110
111 sub _export_delete {
112   my( $self, $svc_acct ) = (shift, shift);
113   $self->infostreet_queue( $svc_acct->svcnum,
114     'purgeAccount,releaseUsername', $svc_acct->username );
115 }
116
117 sub _export_suspend {
118   my( $self, $svc_acct ) = (shift, shift);
119   $self->infostreet_queue( $svc_acct->svcnum,
120     'setStatus', $svc_acct->username, 'DISABLED' );
121 }
122
123 sub _export_unsuspend {
124   my( $self, $svc_acct ) = (shift, shift);
125   $self->infostreet_queue( $svc_acct->svcnum,
126     'setStatus', $svc_acct->username, 'ACTIVE' );
127 }
128
129 sub infostreet_queue {
130   my( $self, $svcnum, $method ) = (shift, shift, shift);
131   my $queue = new FS::queue {
132     'svcnum' => $svcnum,
133     'job'    => 'FS::part_export::infostreet::infostreet_command',
134   };
135   $queue->insert(
136     $self->option('url'),
137     $self->option('login'),
138     $self->option('password'),
139     $self->option('groupID'),
140     $method,
141     @_,
142   );
143 }
144
145 #ick false laziness
146 sub infostreet_err_or_queue {
147   my( $self, $svcnum, $method ) = (shift, shift, shift);
148   my $queue = new FS::queue {
149     'svcnum' => $svcnum,
150     'job'    => 'FS::part_export::infostreet::infostreet_command',
151   };
152   $queue->insert(
153     $self->option('url'),
154     $self->option('login'),
155     $self->option('password'),
156     $self->option('groupID'),
157     $method,
158     @_,
159   ) or $queue;
160 }
161
162 sub infostreet_queueContact {
163   my( $self, $svcnum ) = (shift, shift);
164   my $queue = new FS::queue {
165     'svcnum' => $svcnum,
166     'job'    => 'FS::part_export::infostreet::infostreet_setContact',
167   };
168   $queue->insert(
169     $self->option('url'),
170     $self->option('login'),
171     $self->option('password'),
172     $self->option('groupID'),
173     @_,
174   ) or $queue;
175 }
176
177 sub infostreet_setContact {
178   my($url, $is_username, $is_password, $groupID, $username, %contact_info) = @_;
179   my $accountID = infostreet_command($url, $is_username, $is_password, $groupID,
180     'getAccountID', $username);
181   foreach my $field ( keys %contact_info ) {
182     infostreet_command($url, $is_username, $is_password, $groupID,
183       'setContactField', [ 'int'=>$accountID ], $field, $contact_info{$field} );
184   }
185
186 }
187
188 sub infostreet_queueSetQuota {
189
190  my( $self, $svcnum) = (shift, shift);
191  my $queue = new FS::queue {
192     'svcnum' => $svcnum,
193     'job'    => 'FS::part_export::infostreet::infostreet_setQuota',
194  };
195
196  $queue->insert(
197     $self->option('url'),
198     $self->option('login'),
199     $self->option('password'),
200     $self->option('groupID'),
201     @_,
202  ) or $queue;
203
204 }
205
206 sub infostreet_setQuota {
207   my($url, $is_username, $is_password, $groupID, $username, $quota) = @_;
208   infostreet_command($url, $is_username, $is_password, $groupID, 'setQuota', $username, [ 'int'=> $quota ]  );
209 }
210
211
212 sub infostreet_command { #subroutine, not method
213   my($url, $username, $password, $groupID, $method, @args) = @_;
214
215   warn "[FS::part_export::infostreet] $method ".join(' ', @args)."\n" if $DEBUG;
216
217   #quelle hack
218   if ( $method =~ /,/ ) {
219     foreach my $part ( split(/,\s*/, $method) ) {
220       infostreet_command($url, $username, $password, $groupID, $part, @args);
221     }
222     return;
223   }
224
225   eval "use Frontier::Client;";
226   die $@ if $@;
227
228   eval 'sub Frontier::RPC2::String::repr {
229     my $self = shift;
230     my $value = $$self;
231     $value =~ s/([&<>\"])/$Frontier::RPC2::char_entities{$1}/ge;
232     $value;
233   }';
234   die $@ if $@;
235
236   my $conn = Frontier::Client->new( url => $url );
237   my $key_result = $conn->call( 'authenticate', $username, $password, $groupID);
238   my %key_result = _infostreet_parse($key_result);
239   die $key_result{error} unless $key_result{success};
240   my $key = $key_result{data};
241
242   #my $result = $conn->call($method, $key, @args);
243   my $result = $conn->call( $method, $key,
244                             map {
245                                   if ( ref($_) ) {
246                                     my( $type, $value) = @{$_};
247                                     $conn->$type($value);
248                                   } else {
249                                     $conn->string($_);
250                                   }
251                                 } @args );
252   my %result = _infostreet_parse($result);
253   die $result{error} unless $result{success};
254
255   $result->{data};
256
257 }
258
259 #sub infostreet_command_byid { #subroutine, not method;
260 #  my($url, $username, $password, $groupID, $method, @args ) = @_;
261 #
262 #  infostreet_command
263 #
264 #}
265
266 sub _infostreet_parse { #subroutine, not method
267   my $arg = shift;
268   map {
269     my $value = $arg->{$_};
270     #warn ref($value);
271     $value = $value->value()
272       if ref($value) && $value->isa('Frontier::RPC2::DataType');
273     $_=>$value;
274   } keys %$arg;
275 }
276
277 1;
278