From e62240840b11d5c8c74658778737a26adc243d9c Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Tue, 13 Feb 2018 09:02:56 -0500 Subject: RT# 79507 - enabled GCET import format --- FS/FS/cust_main/import_charges/gcet.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FS/FS/cust_main/import_charges/gcet.pm b/FS/FS/cust_main/import_charges/gcet.pm index 83f956545..cd0fc804c 100644 --- a/FS/FS/cust_main/import_charges/gcet.pm +++ b/FS/FS/cust_main/import_charges/gcet.pm @@ -20,7 +20,7 @@ my $charges = { 'charges' => $charges, 'name' => 'Gcet', 'weight' => '30', - 'disabled' => '1', + 'disabled' => '', ); 1; \ No newline at end of file -- cgit v1.2.1 From 88746e7e37bb89d03b6c8a5098d25842d9f88f59 Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Thu, 15 Feb 2018 11:47:39 -0500 Subject: RT# 78356 - broadband svc export to saisei --- FS/FS/part_export/saisei.pm | 453 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 FS/FS/part_export/saisei.pm diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm new file mode 100644 index 000000000..799220ef2 --- /dev/null +++ b/FS/FS/part_export/saisei.pm @@ -0,0 +1,453 @@ +package FS::part_export::saisei; + +use strict; +use base qw( FS::part_export ); +use vars qw( @ISA %info ); +use Date::Format 'time2str'; +use Cpanel::JSON::XS; +use Net::HTTPS::Any qw(https_post); +use MIME::Base64; +use REST::Client; +use Data::Dumper; + +use FS::Conf; + +#@ISA = qw( FS::part_export::http ); + +=pod + +=head1 NAME + +FS::part_export::saisei + +=head1 SYNOPSIS + +Saisei integration for Freeside + +=head1 DESCRIPTION + +This export offers basic svc_broadband provisioning for Saisei. + +This module also provides generic methods for working through the L. + +=cut + +tie my %options, 'Tie::IxHash', + 'username' => { label => 'User Name', + default => '' }, + 'password' => { label => 'Password', + default => '' }, + 'host' => { label => 'Host', + default => 'STM IP ADDRESS' }, + 'port' => { label => 'Port', + default => 5000 }, + 'customer_name' => { label => 'Customer Name', + default => 'FREESIDE CUST $custnum' }, + 'account_id' => { label => 'Account ID', + default => 'SVC$svcnum' }, + 'product_id' => { label => 'Account Product ID' }, + 'debug' => { type => 'checkbox', + label => 'Enable debug warnings' }, +; + +%info = ( + 'svc' => 'svc_broadband', + 'desc' => 'Export broadband service/account to Saisei', + 'options' => \%options, + 'notes' => <<'END', +This is customer integration with Saisei. +END +); + +#"/STM_IP:5000/rest/top/configurations/running/" is for http 5029 for https + +#Creating User Names +#Users are tracked by their name which gives access to the internal slice data which in turn allows the viewing of Applications and Geo-Locations. +#Creating a user name requires a command of the following format: - +#'put', 'users/USER_NAME', {'description':description} +#When creating a user name it is usual to add a description and since a user attribute set does not normally contain the users plan name it is best to encode it into the description field. + +sub _export_insert { + my ($self, $svc_broadband) = @_; + my $rateplan_name = $svc_broadband->{Hash}->{description}; + $rateplan_name =~ s/\s/_/g; + + + # load needed info from our end + my $cust_main = $svc_broadband->cust_main; + return "Could not load service customer" unless $cust_main; + my $conf = new FS::Conf; + + # get policy list + my $policies = $self->api_get_policies(); + + # check for existing rate plan + my $existing_rateplan; + $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'}; + + # if no existing rate plan create one and modify it. + $self->api_create_rateplan($svc_broadband, $rateplan_name) unless $existing_rateplan; + $self->api_modify_rateplan($policies->{collection}, $svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan); + + # set rateplan to existing one or newly created one. + my $rateplan = $existing_rateplan ? $existing_rateplan : $self->api_get_rateplan($rateplan_name); + + my @email = map { $_->emailaddress } FS::Record::qsearch({ + 'table' => 'cust_contact', + 'select' => 'emailaddress', + 'addl_from' => ' JOIN contact_email USING (contactnum)', + 'hashref' => { 'custnum' => $cust_main->{Hash}->{custnum}, }, + }); + my $username = $email[0]; + my $description = $cust_main->{Hash}->{first}." ".$cust_main->{Hash}->{last}; + + # check for existing user. + my $existing_user; + $existing_user = $self->api_get_user($username) unless ( $self->{'__saisei_error'} || !$username); + + # if no existing user create one. + $self->api_create_user($username, $description) unless $existing_user; + + # set user to existing one or newly created one. + my $user = $existing_user ? $existing_user : $self->api_get_user($username); + + ## add access point ? + + ## tie host to user + $self->api_add_host_to_user($user->{collection}->[0]->{name}, $rateplan->{collection}->[0]->{name}, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'}; + + #die('ending for testing'); + return ''; + +} + +sub _export_replace { + my ($self, $svc_phone) = @_; + return ''; +} + +sub _export_delete { + my ($self, $svc_broadband) = @_; + + my $cust_main = $svc_broadband->cust_main; + return "Could not load service customer" unless $cust_main; + my $conf = new FS::Conf; + + my $rateplan_name = $svc_broadband->{Hash}->{description}; + $rateplan_name =~ s/\s/_/g; + + my @email = map { $_->emailaddress } FS::Record::qsearch({ + 'table' => 'cust_contact', + 'select' => 'emailaddress', + 'addl_from' => ' JOIN contact_email USING (contactnum)', + 'hashref' => { 'custnum' => $cust_main->{Hash}->{custnum}, }, + }); + my $username = $email[0]; + + ## tie host to user + $self->api_delete_host_to_user($username, $rateplan_name, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'}; + + return ''; +} + +sub _export_suspend { + my ($self, $svc_phone) = @_; + return ''; +} + +sub _export_unsuspend { + my ($self, $svc_phone) = @_; + return ''; +} + +=head1 Saisei API + +These methods allow access to the Saisei API using the credentials +set in the export options. + +=cut + +=head2 api_call + +Accepts I<$service>, I<$method>, I<$params> hashref and optional +I<$returnfield>. Places an api call to the specified service +and method with the specified params. Returns the decoded json +object returned by the api call. If I<$returnfield> is specified, +returns only that field of the decoded object, and errors out if +that field does not exist. Returns empty on failure; retrieve +error messages using L. + +Must run L first. + +=cut + +sub api_call { + my ($self,$method,$path,$params) = @_; + $self->{'__saisei_error'} = ''; + my $auth_info = $self->option('username') . ':' . $self->option('password'); + $params ||= {}; + + print "Calling /$method\n" if $self->option('debug'); + + my $data = encode_json($params) if keys %{ $params }; + + my $client = REST::Client->new(); + $client->addHeader("Authorization", "Basic ".encode_base64($auth_info)); + $client->setHost('http://'.$self->option('host').':'.$self->option('port')); + $client->$method('/rest/stm/configurations/running/'.$path, $data, { "Content-type" => 'application/json'}); + + my $result; + + if ($client->responseCode() eq '200' || $client->responseCode() eq '201') { + eval { $result = decode_json($client->responseContent()) }; + unless ($result) { + $self->{'__saisei_error'} = "Error decoding json: $@"; + return; + } + } + else { + $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent(); + print "My response content fo /$method\n". Dumper($client->responseContent) if $self->option('debug'); + return; + } + + return $result; + +} + +=head2 api_error + +Returns the error string set by L methods, +or a blank string if most recent call produced no errors. + +=cut + +sub api_error { + my $self = shift; + return $self->{'__saisei_error'} || ''; +} + +=head2 api_get_policies + +Gets a list of global policies. + +=cut + +sub api_get_policies { + my $self = shift; + + my $get_policies = $self->api_call("GET", 'policies/?token=1&order=name&start=0&limit=20&select=name%2Cpercent_rate%2Cassured%2C'); + return if $self->api_error; + $self->{'__saisei_error'} = "Did not receive any global policies" + unless $get_policies; + + return $get_policies; +} + +=head2 api_get_rateplan + +Gets rateplan info for specific rateplan. + +=cut + +sub api_get_rateplan { + my $self = shift; + my $rateplan = shift; + + my $get_rateplan = $self->api_call("GET", "rate_plans/$rateplan"); + return if $self->api_error; + $self->{'__saisei_error'} = "Did not receive any rateplan info" + unless $get_rateplan; + + return $get_rateplan; +} + +=head2 api_get_user + +Gets user info for specific user. + +=cut + +sub api_get_user { + my $self = shift; + my $user = shift; + + my $get_user = $self->api_call("GET", "users/$user"); + return if $self->api_error; + $self->{'__saisei_error'} = "Did not receive any user info" + unless $get_user; + + return $get_user; +} + +=head2 api_get_accesspoint + +Gets user info for specific access point. + +=cut + +sub api_get_accesspoint { + my $self = shift; + my $accesspoint; + + my $get_accesspoint = $self->api_call("GET", "access_points/$accesspoint"); + return if $self->api_error; + $self->{'__saisei_error'} = "Did not receive any user info" + unless $get_accesspoint; + + return; +} + +=head2 api_create_rateplan + +Creates a rateplan. + +=cut + +sub api_create_rateplan { + my ($self, $svc, $rateplan) = @_; + + my $new_rateplan = $self->api_call( + "PUT", + "rate_plans/$rateplan", + { + 'downstream_rate' => $svc->{Hash}->{speed_down}, + 'upstream_rate' => $svc->{Hash}->{speed_up}, + }, + ); + + $self->{'__saisei_error'} = "Rate Plan not created" + unless $new_rateplan; # should never happen + return $new_rateplan; + +} + +=head2 api_modify_rateplan + +Modify a rateplan. + +=cut + +sub api_modify_rateplan { + my ($self,$policies,$svc,$rateplan_name) = @_; + + foreach my $policy (@$policies) { + my $policyname = $policy->{name}; + my $rate_multiplier = ''; + if ($policy->{background}) { $rate_multiplier = ".01"; } + my $modified_rateplan = $self->api_call( + "PUT", + "rate_plans/$rateplan_name/partitions/$policyname", + { + 'restricted' => $policy->{assured}, # policy_assured_flag + 'rate_multiplier' => $rate_multiplier, # policy_background 0.1 + 'rate' => $policy->{percent_rate}, # policy_percent_rate + }, + ); + + $self->{'__saisei_error'} = "Rate Plan not modified" + unless $modified_rateplan; # should never happen + + } + + return; + +} + +=head2 api_create_user + +Creates a rateplan. + +=cut + +sub api_create_user { + my ($self,$user, $description) = @_; + + my $new_user = $self->api_call( + "PUT", + "users/$user", + { + 'description' => $description, + }, + ); + + $self->{'__saisei_error'} = "User not created" + unless $new_user; # should never happen + + return $new_user; + +} + +=head2 api_create_accesspoint + +Creates a access point. + +=cut + +sub api_create_accesspoint { + my ($self,$accesspoint) = @_; + + my $new_accesspoint = $self->api_call( + "PUT", + "access_points/$accesspoint", + { + 'description' => 'my description', + }, + ); + + $self->{'__saisei_error'} = "Access point not created" + unless $new_accesspoint; # should never happen + return; + +} + +=head2 api_add_host_to_user + +ties host to user and rateplan. + +=cut + +sub api_add_host_to_user { + my ($self,$user, $rateplan, $ip) = @_; + + my $new_host = $self->api_call( + "PUT", + "hosts/$ip", + { + 'user' => $user, + 'rate_plan' => $rateplan, + }, + ); + + $self->{'__saisei_error'} = "Host not created" + unless $new_host; # should never happen + + return $new_host; + +} + +=head2 api_add_host_to_user + +ties host to user and rateplan. + +=cut + +sub api_delete_host_to_user { + my ($self,$user, $rateplan, $ip) = @_; + + my $delete_host = $self->api_call("DELETE", "hosts/$ip"); + + $self->{'__saisei_error'} = "Host not created" + unless $delete_host; # should never happen + + return $delete_host; + +} + +=head1 SEE ALSO + +L + +=cut + +1; \ No newline at end of file -- cgit v1.2.1 From 4e1b23ad46e7ca072eab50fa346d6c0cc5981866 Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Fri, 16 Feb 2018 13:22:05 -0500 Subject: RT# 78356 - cleaned up code and added debug code --- FS/FS/part_export/saisei.pm | 71 +++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 799220ef2..5e6279b68 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -1,15 +1,13 @@ package FS::part_export::saisei; use strict; -use base qw( FS::part_export ); use vars qw( @ISA %info ); +use base qw( FS::part_export ); use Date::Format 'time2str'; use Cpanel::JSON::XS; -use Net::HTTPS::Any qw(https_post); use MIME::Base64; use REST::Client; use Data::Dumper; - use FS::Conf; #@ISA = qw( FS::part_export::http ); @@ -33,19 +31,12 @@ This module also provides generic methods for working through the L =cut tie my %options, 'Tie::IxHash', + 'port' => { label => 'Port', + default => 5000 }, 'username' => { label => 'User Name', default => '' }, 'password' => { label => 'Password', default => '' }, - 'host' => { label => 'Host', - default => 'STM IP ADDRESS' }, - 'port' => { label => 'Port', - default => 5000 }, - 'customer_name' => { label => 'Customer Name', - default => 'FREESIDE CUST $custnum' }, - 'account_id' => { label => 'Account ID', - default => 'SVC$svcnum' }, - 'product_id' => { label => 'Account Product ID' }, 'debug' => { type => 'checkbox', label => 'Enable debug warnings' }, ; @@ -101,22 +92,28 @@ sub _export_insert { my $username = $email[0]; my $description = $cust_main->{Hash}->{first}." ".$cust_main->{Hash}->{last}; - # check for existing user. - my $existing_user; - $existing_user = $self->api_get_user($username) unless ( $self->{'__saisei_error'} || !$username); + if (!$username) { + $self->{'__saisei_error'} = 'no username - can not export'; + warn "No email found $username\n" if $self->option('debug'); + return; + } + else { + # check for existing user. + my $existing_user; + $existing_user = $self->api_get_user($username) unless $self->{'__saisei_error'}; - # if no existing user create one. - $self->api_create_user($username, $description) unless $existing_user; + # if no existing user create one. + $self->api_create_user($username, $description) unless $existing_user; - # set user to existing one or newly created one. - my $user = $existing_user ? $existing_user : $self->api_get_user($username); + # set user to existing one or newly created one. + my $user = $existing_user ? $existing_user : $self->api_get_user($username); - ## add access point ? + ## add access point ? - ## tie host to user - $self->api_add_host_to_user($user->{collection}->[0]->{name}, $rateplan->{collection}->[0]->{name}, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'}; + ## tie host to user + $self->api_add_host_to_user($user->{collection}->[0]->{name}, $rateplan->{collection}->[0]->{name}, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'}; + } - #die('ending for testing'); return ''; } @@ -187,15 +184,19 @@ sub api_call { my $auth_info = $self->option('username') . ':' . $self->option('password'); $params ||= {}; - print "Calling /$method\n" if $self->option('debug'); + warn "Calling $method on http://" + .$self->{Hash}->{machine}.':'.$self->option('port') + ."/rest/stm/configurations/running/$path\n" if $self->option('debug'); my $data = encode_json($params) if keys %{ $params }; my $client = REST::Client->new(); $client->addHeader("Authorization", "Basic ".encode_base64($auth_info)); - $client->setHost('http://'.$self->option('host').':'.$self->option('port')); + $client->setHost('http://'.$self->{Hash}->{machine}.':'.$self->option('port')); $client->$method('/rest/stm/configurations/running/'.$path, $data, { "Content-type" => 'application/json'}); + warn "Response Code is ".$client->responseCode()."\n" if $self->option('debug'); + my $result; if ($client->responseCode() eq '200' || $client->responseCode() eq '201') { @@ -207,7 +208,7 @@ sub api_call { } else { $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent(); - print "My response content fo /$method\n". Dumper($client->responseContent) if $self->option('debug'); + warn "Response Content is\n".$client->responseContent."\n" if $self->option('debug'); return; } @@ -387,16 +388,16 @@ Creates a access point. sub api_create_accesspoint { my ($self,$accesspoint) = @_; - my $new_accesspoint = $self->api_call( - "PUT", - "access_points/$accesspoint", - { - 'description' => 'my description', - }, - ); + #my $new_accesspoint = $self->api_call( + # "PUT", + # "access_points/$accesspoint", + # { + # 'description' => 'my description', + # }, + #); - $self->{'__saisei_error'} = "Access point not created" - unless $new_accesspoint; # should never happen + #$self->{'__saisei_error'} = "Access point not created" + # unless $new_accesspoint; # should never happen return; } -- cgit v1.2.1 From 2250a4d2812ae83e8e32cc206a6e697c3daa174f Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Mon, 19 Feb 2018 14:55:07 -0500 Subject: RT# 78356 - added ability to remove service thru api when service is unprovisioned. --- FS/FS/part_export/saisei.pm | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 5e6279b68..98079cbc4 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -193,7 +193,7 @@ sub api_call { my $client = REST::Client->new(); $client->addHeader("Authorization", "Basic ".encode_base64($auth_info)); $client->setHost('http://'.$self->{Hash}->{machine}.':'.$self->option('port')); - $client->$method('/rest/stm/configurations/running/'.$path, $data, { "Content-type" => 'application/json'}); + $client->$method('/rest/stm/configurations/running'.$path, $data, { "Content-type" => 'application/json'}); warn "Response Code is ".$client->responseCode()."\n" if $self->option('debug'); @@ -237,7 +237,7 @@ Gets a list of global policies. sub api_get_policies { my $self = shift; - my $get_policies = $self->api_call("GET", 'policies/?token=1&order=name&start=0&limit=20&select=name%2Cpercent_rate%2Cassured%2C'); + my $get_policies = $self->api_call("GET", '/policies/?token=1&order=name&start=0&limit=20&select=name%2Cpercent_rate%2Cassured%2C'); return if $self->api_error; $self->{'__saisei_error'} = "Did not receive any global policies" unless $get_policies; @@ -255,7 +255,7 @@ sub api_get_rateplan { my $self = shift; my $rateplan = shift; - my $get_rateplan = $self->api_call("GET", "rate_plans/$rateplan"); + my $get_rateplan = $self->api_call("GET", "/rate_plans/$rateplan"); return if $self->api_error; $self->{'__saisei_error'} = "Did not receive any rateplan info" unless $get_rateplan; @@ -273,7 +273,7 @@ sub api_get_user { my $self = shift; my $user = shift; - my $get_user = $self->api_call("GET", "users/$user"); + my $get_user = $self->api_call("GET", "/users/$user"); return if $self->api_error; $self->{'__saisei_error'} = "Did not receive any user info" unless $get_user; @@ -291,7 +291,7 @@ sub api_get_accesspoint { my $self = shift; my $accesspoint; - my $get_accesspoint = $self->api_call("GET", "access_points/$accesspoint"); + my $get_accesspoint = $self->api_call("GET", "/access_points/$accesspoint"); return if $self->api_error; $self->{'__saisei_error'} = "Did not receive any user info" unless $get_accesspoint; @@ -310,7 +310,7 @@ sub api_create_rateplan { my $new_rateplan = $self->api_call( "PUT", - "rate_plans/$rateplan", + "/rate_plans/$rateplan", { 'downstream_rate' => $svc->{Hash}->{speed_down}, 'upstream_rate' => $svc->{Hash}->{speed_up}, @@ -338,7 +338,7 @@ sub api_modify_rateplan { if ($policy->{background}) { $rate_multiplier = ".01"; } my $modified_rateplan = $self->api_call( "PUT", - "rate_plans/$rateplan_name/partitions/$policyname", + "/rate_plans/$rateplan_name/partitions/$policyname", { 'restricted' => $policy->{assured}, # policy_assured_flag 'rate_multiplier' => $rate_multiplier, # policy_background 0.1 @@ -366,7 +366,7 @@ sub api_create_user { my $new_user = $self->api_call( "PUT", - "users/$user", + "/users/$user", { 'description' => $description, }, @@ -390,7 +390,7 @@ sub api_create_accesspoint { #my $new_accesspoint = $self->api_call( # "PUT", - # "access_points/$accesspoint", + # "/access_points/$accesspoint", # { # 'description' => 'my description', # }, @@ -413,7 +413,7 @@ sub api_add_host_to_user { my $new_host = $self->api_call( "PUT", - "hosts/$ip", + "/hosts/$ip", { 'user' => $user, 'rate_plan' => $rateplan, @@ -436,7 +436,22 @@ ties host to user and rateplan. sub api_delete_host_to_user { my ($self,$user, $rateplan, $ip) = @_; - my $delete_host = $self->api_call("DELETE", "hosts/$ip"); + my $default_rate_plan = $self->api_call("GET", '?token=1&select=default_rate_plan'); + return if $self->api_error; + $self->{'__saisei_error'} = "Did not receive a default rate plan" + unless $default_rate_plan; + + my $default_rateplan_name = $default_rate_plan->{collection}->[0]->{default_rate_plan}->{link}->{name}; + + my $delete_host = $self->api_call( + "PUT", + "/hosts/$ip", + { + 'user' => '', + 'access_point' => '', + 'rate_plan' => $default_rateplan_name, + }, + ); $self->{'__saisei_error'} = "Host not created" unless $delete_host; # should never happen -- cgit v1.2.1 From 7331f919ceb91069b9ac68ad1218c344ea4342b1 Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Tue, 20 Feb 2018 09:14:06 -0500 Subject: RT# 78356 - Added user documentation --- FS/FS/part_export/saisei.pm | 60 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index 98079cbc4..fc0dee5ad 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -10,8 +10,6 @@ use REST::Client; use Data::Dumper; use FS::Conf; -#@ISA = qw( FS::part_export::http ); - =pod =head1 NAME @@ -26,6 +24,19 @@ Saisei integration for Freeside This export offers basic svc_broadband provisioning for Saisei. +This is a customer integration with Saisei. This will setup a rate plan and tie +the rate plan to a host via the Saisei API when the broadband service is provisioned. +It will also untie the rate plan via the API upon unprovisioning of the broadband service. + +This export will use the broadband service descriptive label for the Saisei rate plan name and +will use the email from the first contact for the Saisei username that will be +attached to this rate plan. It will use the Saisei default Access Point. + +Hostname or IP - Host name to Saisei API +Port - Port number to Saisei API +User Name - Saisei API user name +Password - Saisei API password + This module also provides generic methods for working through the L. =cut @@ -46,18 +57,23 @@ tie my %options, 'Tie::IxHash', 'desc' => 'Export broadband service/account to Saisei', 'options' => \%options, 'notes' => <<'END', -This is customer integration with Saisei. +This is a customer integration with Saisei. This will setup a rate plan and tie +the rate plan to a host via the Saisei API when the broadband service is provisioned. +It will also untie the rate plan via the API upon unprovisioning of the broadband service. +

This export will use the broadband service descriptive label for the Saisei rate plan name and +will use the email from the first contact for the Saisei username that will be +attached to this rate plan. It will use the Saisei default Access Point. +

+Required Fields: +

    +
  • Hostname or IP - Host name to Saisei API
  • +
  • Port - Port number to Saisei API
  • +
  • User Name - Saisei API user name
  • +
  • Password - Saisei API password
  • +
END ); -#"/STM_IP:5000/rest/top/configurations/running/" is for http 5029 for https - -#Creating User Names -#Users are tracked by their name which gives access to the internal slice data which in turn allows the viewing of Applications and Geo-Locations. -#Creating a user name requires a command of the following format: - -#'put', 'users/USER_NAME', {'description':description} -#When creating a user name it is usual to add a description and since a user attribute set does not normally contain the users plan name it is best to encode it into the description field. - sub _export_insert { my ($self, $svc_broadband) = @_; my $rateplan_name = $svc_broadband->{Hash}->{description}; @@ -166,15 +182,10 @@ set in the export options. =head2 api_call -Accepts I<$service>, I<$method>, I<$params> hashref and optional -I<$returnfield>. Places an api call to the specified service -and method with the specified params. Returns the decoded json -object returned by the api call. If I<$returnfield> is specified, -returns only that field of the decoded object, and errors out if -that field does not exist. Returns empty on failure; retrieve -error messages using L. - -Must run L first. +Accepts I<$method>, I<$path>, I<$params> hashref and optional. +Places an api call to the specified path and method with the specified params. +Returns the decoded json object returned by the api call. +Returns empty on failure; retrieve error messages using L. =cut @@ -357,7 +368,7 @@ sub api_modify_rateplan { =head2 api_create_user -Creates a rateplan. +Creates a user. =cut @@ -388,6 +399,7 @@ Creates a access point. sub api_create_accesspoint { my ($self,$accesspoint) = @_; + # this has not been tested, but should work, if needed. #my $new_accesspoint = $self->api_call( # "PUT", # "/access_points/$accesspoint", @@ -404,7 +416,7 @@ sub api_create_accesspoint { =head2 api_add_host_to_user -ties host to user and rateplan. +ties host to user, rateplan and default access point. =cut @@ -427,9 +439,9 @@ sub api_add_host_to_user { } -=head2 api_add_host_to_user +=head2 api_delete_host_to_user -ties host to user and rateplan. +unties host to user and rateplan. =cut -- cgit v1.2.1 From 906379279f9c1de0254d58313e97435aed2329e1 Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Tue, 20 Feb 2018 10:46:56 -0500 Subject: RT# 78356 - fix for email address lookup on V3 --- FS/FS/part_export/saisei.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm index fc0dee5ad..c7ee6f638 100644 --- a/FS/FS/part_export/saisei.pm +++ b/FS/FS/part_export/saisei.pm @@ -100,7 +100,7 @@ sub _export_insert { my $rateplan = $existing_rateplan ? $existing_rateplan : $self->api_get_rateplan($rateplan_name); my @email = map { $_->emailaddress } FS::Record::qsearch({ - 'table' => 'cust_contact', + 'table' => 'contact', 'select' => 'emailaddress', 'addl_from' => ' JOIN contact_email USING (contactnum)', 'hashref' => { 'custnum' => $cust_main->{Hash}->{custnum}, }, @@ -150,7 +150,7 @@ sub _export_delete { $rateplan_name =~ s/\s/_/g; my @email = map { $_->emailaddress } FS::Record::qsearch({ - 'table' => 'cust_contact', + 'table' => 'contact', 'select' => 'emailaddress', 'addl_from' => ' JOIN contact_email USING (contactnum)', 'hashref' => { 'custnum' => $cust_main->{Hash}->{custnum}, }, -- cgit v1.2.1