RT# 83450 - fixed rateplan export
[freeside.git] / FS / FS / part_export / bulkvs_e911.pm
1 package FS::part_export::bulkvs_e911;
2
3 use strict;
4 use vars qw(%info $me $DEBUG);
5 use base 'FS::part_export';
6 use FS::svc_phone;
7 use Tie::IxHash;
8
9 use SOAP::Lite;
10 use Digest::MD5 'md5_hex';
11 use Data::Dumper;
12
13 $DEBUG = 2;
14 $me = '['.__PACKAGE__.']';
15
16 tie my %options, 'Tie::IxHash', (
17   'apikey'    => { label=>'Bulkvs.com API key' },
18   'password'  => { label=>'Bulkvs.com website password' },
19 );
20
21 %info = (
22   'svc'     => 'svc_phone',
23   'desc'    => 'Provision e911 services via BulkVS',
24   'notes'   => <<END
25 <p>Provision e911 services via BulkVS.  Currently does not support provisioning
26 phone numbers, only e911 service itself.</p>
27 <p><i>apikey</i> is available through the web interface (look under the E911 
28 Portal submenu). <i>password</i> is your password for the website, which will
29 be used to calculate your API password.</p>
30 END
31   ,
32   'no_machine' => 1,
33   'options' => \%options,
34 );
35
36 my $client;
37
38 sub client {
39   my $self = shift;
40   my $endpoint = 'https://portal.bulkvs.com/api';
41   my $wsdl = $endpoint . '?wsdl';
42   # it's expensive to create but completely stateless, so cache it freely
43   $client ||= SOAP::Lite->service( $wsdl )->proxy( $endpoint );
44 }
45
46 sub login {
47   my $self = shift;
48   my $apikey = $self->option('apikey')
49       or die "no Bulkvs.com API key configured";
50   my $pass = $self->option('password')
51       or die "no Bulkvs.com password configured";
52
53   ( $apikey, md5_hex($pass) );
54 }
55
56 sub _export_insert {
57   my ($self, $svc_phone) = @_;
58   my @login = $self->login;
59
60   my $location = $svc_phone->cust_location_or_main
61     or return 'no e911 location defined for this phone service';
62
63   warn "$me validating address for svcnum ".$svc_phone->svcnum."\n"
64     if $DEBUG;
65   my $result = $self->client->e911validateAddress( @login,
66     $location->address1,
67     $location->address2,
68     $location->city,
69     $location->state,
70     $location->zip,
71   );
72   warn Dumper $result if $DEBUG > 1;
73   if ( $result->{'faultstring'} ) {
74     return "E911 provisioning error: ".$result->{'faultstring'};
75   } elsif ( !exists($result->{entry0}->{addressid}) ) {
76     return "E911 provisioning error: server returned no address ID";
77   }
78
79   my $caller_name = $svc_phone->cust_linked ?
80                     $svc_phone->cust_main->name_short :
81                     'unknown';
82
83   warn "$me provisioning address for svcnum ".$svc_phone->svcnum."\n"
84     if $DEBUG;
85   $result = $self->client->e911provisionAddress( @login,
86     '1'.$svc_phone->phonenum,
87     $caller_name,
88     $result->{entry0}->{addressid},
89   );
90   warn Dumper $result if $DEBUG > 1;
91   if ( $result->{'faultstring'} ) {
92     return "E911 provisioning error: ".$result->{'faultstring'};
93   }
94   '';
95 }
96
97 sub _export_delete {
98   my ($self, $svc_phone) = @_;
99   my @login = $self->login;
100   warn "$me removing address for svcnum ".$svc_phone->svcnum."\n"
101     if $DEBUG;
102   my $result = $self->client->e911removeRecord( @login,
103     '1'.$svc_phone->phonenum
104   );
105   warn Dumper $result if $DEBUG > 1;
106   if ( $result->{'faultstring'} ) {
107     return "E911 unprovisioning error: ".$result->{'faultstring'};
108   }
109   '';
110 }
111
112 sub _export_replace {
113   my ($self, $new, $old) = @_;
114   # BulkVS says that to change an address for an existing number,
115   # we should reprovision it without removing the old record.
116   if ( $new->phonenum ne $old->phonenum ) {
117     my $error = $self->_export_delete($old);
118     return $error if $error;
119   }
120   $self->_export_insert($new);
121 }
122
123 1;
124