diff options
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/Schema.pm | 1 | ||||
-rw-r--r-- | FS/FS/part_export/sipwise.pm | 143 | ||||
-rw-r--r-- | FS/FS/svc_acct.pm | 11 | ||||
-rw-r--r-- | FS/FS/svc_phone.pm | 14 |
4 files changed, 111 insertions, 58 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 36418acca..d20385e8a 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -5842,6 +5842,7 @@ sub tables_hashref { 'pbxsvc', 'int', 'NULL', '', '', '', 'domsvc', 'int', 'NULL', '', '', '', 'locationnum', 'int', 'NULL', '', '', '', + 'forward_svcnum', 'int', 'NULL', '', '', '', 'forwarddst', 'varchar', 'NULL', 15, '', '', 'email', 'varchar', 'NULL', 255, '', '', 'lnp_status', 'varchar', 'NULL', $char_d, '', '', diff --git a/FS/FS/part_export/sipwise.pm b/FS/FS/part_export/sipwise.pm index 690a14cbf..d2af7daf0 100644 --- a/FS/FS/part_export/sipwise.pm +++ b/FS/FS/part_export/sipwise.pm @@ -5,7 +5,6 @@ use strict; use FS::Record qw(qsearch qsearchs dbh); use Tie::IxHash; -use Carp; use LWP::UserAgent; use URI; use Cpanel::JSON::XS; @@ -13,6 +12,7 @@ use HTTP::Request::Common qw(GET POST PUT DELETE); use FS::Misc::DateTime qw(parse_datetime); use DateTime; use Number::Phone; +use Try::Tiny; our $me = '[sipwise]'; our $DEBUG = 2; @@ -34,7 +34,7 @@ tie my %options, 'Tie::IxHash', tie my %roles, 'Tie::IxHash', 'subscriber' => { label => 'Subscriber', - svcdb => 'svc_phone', + svcdb => 'svc_acct', multiple => 1, }, 'did' => { label => 'DID', @@ -44,7 +44,7 @@ tie my %roles, 'Tie::IxHash', ; our %info = ( - 'svc' => [qw( svc_phone )], + 'svc' => [qw( svc_acct svc_phone )], 'desc' => 'Provision to a Sipwise sip:provider server', 'options' => \%options, 'roles' => \%roles, @@ -52,12 +52,12 @@ our %info = ( <P>Export to a <b>sip:provider</b> server.</P> <P>This requires two service definitions to be configured on the same package: <OL> - <LI>A phone service for a SIP client account ("subscriber"). The - <i>phonenum</i> will be the SIP username. The <i>domsvc</i> should point + <LI>An account service for a SIP client account ("subscriber"). The + <i>username</i> will be the SIP username. The <i>domsvc</i> should point to a domain service to use as the SIP domain name.</LI> <LI>A phone service for a DID. The <i>phonenum</i> here will be a PSTN - number. The <i>forwarddst</i> field should be set to the SIP username - of the subscriber who should receive calls directed to this number.</LI> + number. The <i>forward_svcnum</i> field should be set to the account that + will receive calls at this number. </OL> </P> <P>Export options: @@ -68,63 +68,61 @@ END sub export_insert { my($self, $svc_x) = (shift, shift); - local $@; + my $error; my $role = $self->svc_role($svc_x); if ( $role eq 'subscriber' ) { - eval { $self->insert_subscriber($svc_x) }; - return "$me $@" if $@; + try { $self->insert_subscriber($svc_x) } + catch { $error = $_ }; } elsif ( $role eq 'did' ) { - # only export the DID if it's set to forward to somewhere... - return if $svc_x->forwarddst eq ''; - my $subscriber = qsearchs('svc_phone', { phonenum => $svc_x->forwarddst }); - # and there is a service for the forwarding destination... - return if !$subscriber; - # and that service is managed by this export. - return if !$self->svc_role($subscriber); - - eval { $self->replace_subscriber($subscriber) }; - return "$me $@" if $@; + try { $self->export_did($svc_x) } + catch { $error = $_ }; } + return "$me $error" if $error; ''; } sub export_replace { my ($self, $svc_new, $svc_old) = @_; my $role = $self->svc_role($svc_new); - local $@; + + my $error; if ( $role eq 'subscriber' ) { - eval { $self->replace_subscriber($svc_new, $svc_old) }; + + try { $self->replace_subscriber($svc_new, $svc_old) } + catch { $error = $_ }; + } elsif ( $role eq 'did' ) { - eval { $self->replace_did($svc_new, $svc_old) }; + + try { $self->export_did($svc_new, $svc_old) } + catch { $error = $_ }; + } - return "$me $@" if $@; + return "$me $error" if $error; ''; } sub export_delete { my ($self, $svc_x) = (shift, shift); my $role = $self->svc_role($svc_x); - local $@; + my $error; + if ( $role eq 'subscriber' ) { # no need to remove DIDs from it, just drop the subscriber record - eval { $self->delete_subscriber($svc_x) }; + try { $self->delete_subscriber($svc_x) } + catch { $error = $_ }; } elsif ( $role eq 'did' ) { - return if !$svc_x->forwarddst; - my $subscriber = qsearchs('svc_phone', { phonenum => $svc_x->forwarddst }); - return if !$subscriber; - return if !$self->svc_role($subscriber); - - eval { $self->delete_did($svc_x, $subscriber) }; + try { $self->export_did($svc_x) } + catch { $error = $_ }; } - return "$me $@" if $@; + return "$me $error" if $error; ''; } @@ -194,7 +192,7 @@ sub find_or_create_customer { ] ); if (!$billing_profile) { - croak "can't find billing profile '". $self->option('billing_profile') . "'"; + die "can't find billing profile '". $self->option('billing_profile') . "'\n"; } my $bpid = $billing_profile->{id}; @@ -255,6 +253,41 @@ sub find_or_create_domain { ); } +######## +# DIDS # +######## + +=item acct_for_did SVC_PHONE + +Returns the subscriber svc_acct linked to SVC_PHONE. + +=cut + +sub acct_for_did { + my $self = shift; + my $svc_phone = shift; + my $svcnum = $svc_phone->forward_svcnum or return; + my $svc_acct = FS::svc_acct->by_key($svcnum) or return; + $self->svc_role($svc_acct) eq 'subscriber' or return; + $svc_acct; +} + +=item export_did NEW, OLD + +Refreshes the subscriber information for the service the DID was linked to +previously, and the one it's linked to now. + +=cut + +sub export_did { + my $self = shift; + my ($new, $old) = @_; + if ( $old and $new->forward_svcnum ne $old->forward_svcnum ) { + $self->replace_subscriber( $self->acct_for_did($old) ); + } + $self->replace_subscriber( $self->acct_for_did($new) ); +} + ############### # SUBSCRIBERS # ############### @@ -270,7 +303,7 @@ sub get_subscriber { my $svc = shift; my $svcnum = $svc->svcnum; - my $svcid = "svc_phone#$svcnum"; + my $svcid = "svc#$svcnum"; my $pkgnum = $svc->cust_svc->pkgnum; my $custid = "cust_pkg#$pkgnum"; @@ -291,12 +324,11 @@ sub did_numbers_for_svc { my $self = shift; my $svc = shift; my @numbers; - my @possible_dids = qsearch({ + my @dids = qsearch({ 'table' => 'svc_phone', - 'hashref' => { 'forwarddst' => $svc->phonenum }, - 'order_by' => ' ORDER BY phonenum' + 'hashref' => { 'forward_svcnum' => $svc->svcnum } }); - foreach my $did (@possible_dids) { + foreach my $did (@dids) { # only include them if they're interesting to this export if ( $self->svc_role($did) eq 'did' ) { my $phonenum; @@ -308,7 +340,7 @@ sub did_numbers_for_svc { $phonenum = Number::Phone->new($country, $did->phonenum); } if (!$phonenum) { - croak "Can't process phonenum ".$did->countrycode . $did->phonenum; + die "Can't process phonenum ".$did->countrycode . $did->phonenum . "\n"; } push @numbers, { 'cc' => $phonenum->country_code, @@ -325,7 +357,7 @@ sub insert_subscriber { my $svc = shift; my $cust = $self->find_or_create_customer($svc); - my $svcid = "svc_phone#" . $svc->svcnum; + my $svcid = "svc#" . $svc->svcnum; my $status = $svc->cust_svc->cust_pkg->susp ? 'locked' : 'active'; my $domain = $self->find_or_create_domain($svc->domain); @@ -336,14 +368,13 @@ sub insert_subscriber { { 'alias_numbers' => \@numbers, 'customer_id' => $cust->{id}, - 'display_name' => $svc->phone_name, + 'display_name' => $svc->finger, 'domain_id' => $domain->{id}, - 'email' => $svc->email, 'external_id' => $svcid, - 'password' => $svc->sip_password, + 'password' => $svc->_password, 'primary_number' => $first_number, 'status' => $status, - 'username' => $svc->phonenum, + 'username' => $svc->username, } ); } @@ -351,8 +382,8 @@ sub insert_subscriber { sub replace_subscriber { my $self = shift; my $svc = shift; - my $old = shift; - my $svcid = "svc_phone#" . $svc->svcnum; + my $old = shift || $svc->replace_old; + my $svcid = "svc#" . $svc->svcnum; my $cust = $self->find_or_create_customer($svc); my $status = $svc->cust_svc->cust_pkg->susp ? 'locked' : 'active'; @@ -365,7 +396,7 @@ sub replace_subscriber { if ( $subscriber ) { my $id = $subscriber->{id}; - if ( $svc->phonenum ne $old->phonenum ) { + if ( $svc->username ne $old->username ) { # have to delete and recreate $self->api_delete("subscribers/$id"); $self->insert_subscriber($svc); @@ -374,14 +405,14 @@ sub replace_subscriber { { 'alias_numbers' => \@numbers, 'customer_id' => $cust->{id}, - 'display_name' => $svc->phone_name, + 'display_name' => $svc->finger, 'domain_id' => $domain->{id}, 'email' => $svc->email, 'external_id' => $svcid, - 'password' => $svc->sip_password, + 'password' => $svc->_password, 'primary_number' => $first_number, 'status' => $status, - 'username' => $svc->phonenum, + 'username' => $svc->username, } ); } @@ -394,7 +425,7 @@ sub replace_subscriber { sub delete_subscriber { my $self = shift; my $svc = shift; - my $svcid = "svc_phone#" . $svc->svcnum; + my $svcid = "svc#" . $svc->svcnum; my $pkgnum = $svc->cust_svc->pkgnum; my $custid = "cust_pkg#$pkgnum"; @@ -490,7 +521,7 @@ sub api_create { if ( $result->{location} ) { return $self->api_request('GET', $result->{location}); } else { - croak $result->{message}; + die $result->{message} . "\n"; } } @@ -508,7 +539,7 @@ sub api_update { my ($endpoint, $content) = @_; my $result = $self->api_request('PUT', $endpoint, $content); if ( $result->{message} ) { - croak $result->{message}; + die $result->{message} . "\n"; } return; } @@ -529,7 +560,7 @@ sub api_delete { warn "$me api_delete $endpoint: does not exist\n"; return; } elsif ( $result->{message} ) { - croak $result->{message}; + die $result->{message} . "\n"; } return; } @@ -591,7 +622,7 @@ sub api_request { if ( $@ ) { # then it can't be parsed; probably a low-level error of some kind. warn "$me Parse error.\n".$response->content."\n\n"; - croak $response->content; + die "$me Parse error:".$response->content . "\n"; } } if ( $response->header('Location') ) { diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index c2f5d7122..67fce4129 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -847,6 +847,17 @@ sub delete { } } + foreach my $svc_phone ( + qsearch( 'svc_phone', { 'forward_svcnum' => $self->svcnum }) + ) { + $svc_phone->set('forward_svcnum', ''); + my $error = $svc_phone->replace; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + my $error = $self->delete_password_history || $self->SUPER::delete; # usergroup here if ( $error ) { diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index cf9d9b440..3a58b465c 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -93,9 +93,14 @@ Voicemail PIN Optional svcnum from svc_pbx +=item forward_svcnum + +Forward destination, if it's another service. Some exports use this +configuration. + =item forwarddst -Forwarding destination +Forwarding destination, if it's not a service. =item email @@ -225,6 +230,9 @@ sub table_info { 'forwarddst' => { label => 'Forward Destination', %dis2, }, + 'forward_svcnum' => { label => 'Route to service', + %dis2, + }, 'email' => { label => 'Email', %dis2, }, @@ -529,7 +537,9 @@ sub check { || $self->ut_alphan('sms_account') || $self->ut_numbern('max_simultaneous') || $self->ut_foreign_keyn('locationnum', 'cust_location', 'locationnum') - || $self->ut_numbern('forwarddst') + || $self->ut_numbern('forward_svcnum') + || $self->ut_foreign_keyn('forward_svcnum', 'cust_svc', 'svcnum') + || $self->ut_textn('forwarddst') || $self->ut_textn('email') || $self->ut_numbern('lrn') || $self->ut_numbern('lnp_desired_due_date') |