summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Burger <burgerc@freeside.biz>2018-03-27 09:20:05 -0400
committerChristopher Burger <burgerc@freeside.biz>2018-03-28 10:15:52 -0400
commitda355fb20a69bbe5710ce7dca16e2c84a207a084 (patch)
tree398bbeeb4b301e4389a222a72e9f300ae562eafb
parent0b8b48e7c6306be3b7418cb23e8318317d041caf (diff)
RT# 78356 - added ability to create and modify rateplans and access point when changed on freeside. cleanded up documentation.
Conflicts: FS/FS/tower_sector.pm httemplate/edit/process/tower.html httemplate/edit/tower.html
-rw-r--r--FS/FS/Schema.pm8
-rw-r--r--FS/FS/part_export/saisei.pm454
-rw-r--r--FS/FS/part_svc.pm17
-rw-r--r--FS/FS/tower.pm12
-rw-r--r--FS/FS/tower_sector.pm33
-rw-r--r--httemplate/edit/part_export.cgi14
-rw-r--r--httemplate/edit/process/elements/process.html8
-rw-r--r--httemplate/edit/process/tower.html2
-rw-r--r--httemplate/edit/tower.html10
-rw-r--r--httemplate/elements/tr-tower_sectors.html14
10 files changed, 442 insertions, 130 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index cc74703..431f125 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -4891,8 +4891,8 @@ sub tables_hashref {
'height', 'decimal', 'NULL', '', '', '',
'veg_height', 'decimal', 'NULL', '', '', '',
'color', 'varchar', 'NULL', 6, '', '',
- 'up_rate', 'int', 'NULL', '', '', '',
- 'down_rate', 'int', 'NULL', '', '', '',
+ 'up_rate_limit', 'int', 'NULL', '', '', '',
+ 'down_rate_limit', 'int', 'NULL', '', '', '',
],
'primary_key' => 'towernum',
'unique' => [ [ 'towername' ] ], # , 'agentnum' ] ],
@@ -4919,8 +4919,8 @@ sub tables_hashref {
'south', 'decimal', 'NULL', '10,7', '', '',
'north', 'decimal', 'NULL', '10,7', '', '',
'title', 'varchar', 'NULL', $char_d,'', '',
- 'up_rate', 'int', 'NULL', '', '', '',
- 'down_rate', 'int', 'NULL', '', '', '',
+ 'up_rate_limit', 'int', 'NULL', '', '', '',
+ 'down_rate_limit', 'int', 'NULL', '', '', '',
],
'primary_key' => 'sectornum',
'unique' => [ [ 'towernum', 'sectorname' ], [ 'ip_addr' ], ],
diff --git a/FS/FS/part_export/saisei.pm b/FS/FS/part_export/saisei.pm
index f76051e..1c95081 100644
--- a/FS/FS/part_export/saisei.pm
+++ b/FS/FS/part_export/saisei.pm
@@ -28,30 +28,47 @@ This is a customer integration with Saisei. This will setup a rate plan and tie
the rate plan to a host and access point 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 will create and modify the rate plans at Saisei as soon as the broadband service attached to this export is created or modified.
+This will also create and modify a access point at Saisei as soon as the tower is created or modified.
+
+To use this export, follow the below instructions:
+
Add a new export and fill out required fields:
-<UL>
-<LI>Hostname or IP - <I>Host name to Saisei API</I></LI>
-<LI>Port - <I>Port number to Saisei API</I></LI>
-<LI>User Name - <I>Saisei API user name</I></LI>
-<LI>Password - <I>Saisei API password</I></LI>
-</UL>
+
+Hostname or IP - <I>Host name to Saisei API
+User Name - <I>Saisei API user name
+Password - <I>Saisei API password
+
Create a broadband service. The broadband service name will become the Saisei rate plan name.
-Set the upload and download speed, and set the modifier to fixed.
-Set IP Address to required.
-Attach Saisei export to service
+Set the upload and download speed for the service. This is required to be able to export the service to Saisei.
+Attach above created Saisei export to this broadband service.
Create a tower and add a sector to that tower. The sector name will be the name of the access point,
-Make sure you have set an up and down rate for the Tower and Sector.
+Make sure you have set the up and down rate limit for the Tower and Sector. This is required to be able to export the access point.
-When you provision the service, enter the ip address associated to this service.
-Select the Tower and Sector for it's access point.
+Create a package for the above created broadband service, and order this package for a customer.
-When the service is provisioned it will auto setup the rate plan.
+When you provision the service, enter the ip address associated to this service and select the Tower and Sector for it's access point.
+This provisioned service will then be exported as a host to Saisei.
+
+when you un provision this service, the host entry at Saisei will be deleted.
+
+When setting this up, if you wish to export your allready provisioned services, make sure the broadband service has this export attached and
+on export edit screen there will be a link to export Provisioned Services attached to this export. Clicking on that will export all services
+not currently exported to Saisei.
This module also provides generic methods for working through the L</Saisei API>.
=cut
+tie my %scripts, 'Tie::IxHash',
+ 'export_provisioned_services' => { component => '/elements/popup_link.html',
+ label => 'Export provisioned services',
+ description => 'will export provisioned services of part service with Saisei export attached.',
+ html_label => '<b>Export Provisioned Services attached to this export.</b>',
+ },
+;
+
tie my %options, 'Tie::IxHash',
'port' => { label => 'Port',
default => 5000 },
@@ -67,11 +84,19 @@ tie my %options, 'Tie::IxHash',
'svc' => 'svc_broadband',
'desc' => 'Export broadband service/account to Saisei',
'options' => \%options,
+ 'scripts' => \%scripts,
'notes' => <<'END',
This is a customer integration with Saisei. This will setup a rate plan and tie
the rate plan to a host and access point 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.
<P>
+This will create and modify the rate plans at Saisei as soon as the broadband service attached to this export is created or modified.
+This will also create and modify a access point at Saisei as soon as the tower is created or modified.
+<P>
+To use this export, follow the below instructions:
+<P>
+<OL>
+<LI>
Add a new export and fill out required fields:
<UL>
<LI>Hostname or IP - <I>Host name to Saisei API</I></LI>
@@ -79,18 +104,34 @@ Add a new export and fill out required fields:
<LI>User Name - <I>Saisei API user name</I></LI>
<LI>Password - <I>Saisei API password</I></LI>
</UL>
+</LI>
+<P>
+<LI>
Create a broadband service. The broadband service name will become the Saisei rate plan name.
-Set the upload and download speed, and set the modifier to fixed.
-Set IP Address to required.
-Attach Saisei export to service
+Set the upload and download speed for the service. This is required to be able to export the service to Saisei.
+Attach above created Saisei export to this broadband service.
+</LI>
<P>
+<LI>
Create a tower and add a sector to that tower. The sector name will be the name of the access point,
-Make sure you have set an up and down rate for the Tower and Sector.
+Make sure you have set the up and down rate limit for the Tower and Sector. This is required to be able to export the access point.
+</LI>
+<P>
+<LI>
+Create a package for the above created broadband service, and order this package for a customer.
+</LI>
+<P>
+<LI>
+When you provision the service, enter the ip address associated to this service and select the Tower and Sector for it's access point.
+This provisioned service will then be exported as a host to Saisei.
<P>
-When you provision the service, enter the ip address associated to this service.
-Select the Tower and Sector for it's access point.
+when you un provision this service, the host entry at Saisei will be deleted.
+</LI>
+</OL>
<P>
-When the service is provisioned it will auto setup the rate plan.
+When setting this up, if you wish to export your allready provisioned services, make sure the broadband service has this export attached and
+on export edit screen there will be a link to export Provisioned Services attached to this export. Clicking on that will export all services
+not currently exported to Saisei.
END
);
@@ -101,21 +142,14 @@ sub _export_insert {
my $rateplan_name = $service_part->{Hash}->{svc};
$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);
+ $self->api_modify_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan);
+ return $self->api_error if $self->{'__saisei_error'};
# set rateplan to existing one or newly created one.
my $rateplan = $existing_rateplan ? $existing_rateplan : $self->api_get_rateplan($rateplan_name);
@@ -125,7 +159,6 @@ sub _export_insert {
if (!$username) {
$self->{'__saisei_error'} = 'no username - can not export';
- warn "No user $username\n" if $self->option('debug');
return $self->api_error;
}
else {
@@ -135,59 +168,49 @@ sub _export_insert {
# if no existing user create one.
$self->api_create_user($username, $description) unless $existing_user;
+ return $self->api_error if $self->{'__saisei_error'};
# 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
my $tower_sector = FS::Record::qsearchs({
'table' => 'tower_sector',
'select' => 'tower.towername,
- tower.up_rate as toweruprate,
- tower.down_rate as towerdownrate,
+ tower.up_rate_limit as tower_upratelimit,
+ tower.down_rate_limit as tower_downratelimit,
tower_sector.sectorname,
- tower_sector.up_rate as sectoruprate,
- tower_sector.down_rate as sectordownrate ',
+ tower_sector.up_rate_limit as sector_upratelimit,
+ tower_sector.down_rate_limit as sector_downratelimit ',
'addl_from' => 'LEFT JOIN tower USING ( towernum )',
'hashref' => {
'sectornum' => $svc_broadband->{Hash}->{sectornum},
},
});
- my $existing_tower_ap;
my $tower_name = $tower_sector->{Hash}->{towername};
$tower_name =~ s/\s/_/g;
- #check if tower has been set up as an access point.
- $existing_tower_ap = $self->api_get_accesspoint($tower_name) unless $self->{'__saisei_error'};;
+ my $tower_opt = {
+ 'tower_name' => $tower_name,
+ 'tower_uprate_limit' => $tower_sector->{Hash}->{tower_upratelimit},
+ 'tower_downrate_limit' => $tower_sector->{Hash}->{tower_downratelimit},
+ };
- #if tower does not exist as an access point create it.
- $self->api_create_accesspoint(
- $tower_name,
- $tower_sector->{Hash}->{toweruprate},
- $tower_sector->{Hash}->{towerdownrate}
- ) unless $existing_tower_ap;
+ my $tower_ap = process_tower($self, $tower_opt);
+ return $self->api_error if $self->{'__saisei_error'};
- my $existing_sector_ap;
my $sector_name = $tower_sector->{Hash}->{sectorname};
$sector_name =~ s/\s/_/g;
- #check if sector has been set up as an access point.
- $existing_sector_ap = $self->api_get_accesspoint($sector_name);
-
- #if sector does not exist as an access point create it.
- $self->api_create_accesspoint(
- $sector_name,
- $tower_sector->{Hash}->{sectoruprate},
- $tower_sector->{Hash}->{sectordownrate},
- $tower_name,
- ) unless $existing_sector_ap;
-
- # Attach newly created sector to it's tower.
- $self->api_modify_accesspoint($sector_name, $tower_name) unless ($self->{'__saisei_error'} || $existing_sector_ap);
-
- # set access point to existing one or newly created one.
- my $accesspoint = $existing_sector_ap ? $existing_sector_ap : $self->api_get_accesspoint($sector_name);
+ my $sector_opt = {
+ 'tower_name' => $tower_name,
+ 'sector_name' => $sector_name,
+ 'sector_uprate_limit' => $tower_sector->{Hash}->{sector_upratelimit},
+ 'sector_downrate_limit' => $tower_sector->{Hash}->{sector_downratelimit},
+ };
+ my $accesspoint = process_sector($self, $sector_opt);
+ return $self->api_error if $self->{'__saisei_error'};
## tie host to user add sector name as access point.
$self->api_add_host_to_user(
@@ -203,27 +226,17 @@ sub _export_insert {
}
sub _export_replace {
- my ($self, $svc_phone) = @_;
+ my ($self, $svc_broadband) = @_;
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};
+ my $service_part = FS::Record::qsearchs( 'part_svc', { 'svcpart' => $svc_broadband->{Hash}->{svcpart} } );
+ my $rateplan_name = $service_part->{Hash}->{svc};
$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];
+ my $username = $svc_broadband->{Hash}->{svcnum};
## tie host to user
$self->api_delete_host_to_user($username, $rateplan_name, $svc_broadband->{Hash}->{ip_addr}) unless $self->{'__saisei_error'};
@@ -232,15 +245,81 @@ sub _export_delete {
}
sub _export_suspend {
- my ($self, $svc_phone) = @_;
+ my ($self, $svc_broadband) = @_;
return '';
}
sub _export_unsuspend {
- my ($self, $svc_phone) = @_;
+ my ($self, $svc_broadband) = @_;
return '';
}
+sub export_partsvc {
+ my ($self, $svc_part) = @_;
+
+ my $rateplan_name = $svc_part->{Hash}->{svc};
+ $rateplan_name =~ s/\s/_/g;
+ my $speeddown = $svc_part->{Hash}->{svc_broadband__speed_down};
+ my $speedup = $svc_part->{Hash}->{svc_broadband__speed_up};
+
+ my $temp_svc = $svc_part->{Hash};
+ my $svc_broadband = {};
+ map { if ($_ =~ /^svc_broadband__(.*)$/) { $svc_broadband->{Hash}->{$1} = $temp_svc->{$_}; } } keys %$temp_svc;
+
+ # check for existing rate plan
+ my $existing_rateplan;
+ $existing_rateplan = $self->api_get_rateplan($rateplan_name) unless $self->{'__saisei_error'};
+
+ # Modify the existing rate plan with new service data.
+ $self->api_modify_existing_rateplan($svc_broadband, $rateplan_name) unless ($self->{'__saisei_error'} || !$existing_rateplan);
+
+ # 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($svc_part, $rateplan_name) unless ($self->{'__saisei_error'} || $existing_rateplan);
+
+ return $self->api_error;
+
+}
+
+sub export_tower_sector {
+ my ($self, $tower) = @_;
+
+ #modify tower or create it.
+ my $tower_name = $tower->{Hash}->{towername};
+ $tower_name =~ s/\s/_/g;
+ my $tower_opt = {
+ 'tower_name' => $tower_name,
+ 'tower_uprate_limit' => $tower->{Hash}->{up_rate_limit},
+ 'tower_downrate_limit' => $tower->{Hash}->{down_rate_limit},
+ 'modify_existing' => '1', # modify an existing access point with this info
+ };
+
+ my $tower_access_point = process_tower($self, $tower_opt);
+
+ #get list of all access points
+ my $hash_opt = {
+ 'table' => 'tower_sector',
+ 'select' => '*',
+ 'hashref' => { 'towernum' => $tower->{Hash}->{towernum}, },
+ };
+
+ #for each one modify or create it.
+ foreach my $tower_sector ( FS::Record::qsearch($hash_opt) ) {
+ my $sector_name = $tower_sector->{Hash}->{sectorname};
+ $sector_name =~ s/\s/_/g;
+ my $sector_opt = {
+ 'tower_name' => $tower_name,
+ 'sector_name' => $sector_name,
+ 'sector_uprate_limit' => $tower_sector->{Hash}->{up_rate_limit},
+ 'sector_downrate_limit' => $tower_sector->{Hash}->{down_rate_limit},
+ 'modify_existing' => '1', # modify an existing access point with this info
+ };
+ my $sector_access_point = process_sector($self, $sector_opt);
+ }
+
+ return $self->api_error;
+}
+
=head1 Saisei API
These methods allow access to the Saisei API using the credentials
@@ -259,6 +338,7 @@ Returns empty on failure; retrieve error messages using L</api_error>.
sub api_call {
my ($self,$method,$path,$params) = @_;
+
$self->{'__saisei_error'} = '';
my $auth_info = $self->option('username') . ':' . $self->option('password');
$params ||= {};
@@ -286,7 +366,8 @@ sub api_call {
}
}
else {
- $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent();
+ $self->{'__saisei_error'} = "Bad response from server during $method: " . $client->responseContent()
+ unless ($method eq "GET");
warn "Response Content is\n".$client->responseContent."\n" if $self->option('debug');
return;
}
@@ -321,7 +402,7 @@ sub api_get_policies {
$self->{'__saisei_error'} = "Did not receive any global policies"
unless $get_policies;
- return $get_policies;
+ return $get_policies->{collection};
}
=head2 api_get_rateplan
@@ -336,8 +417,6 @@ sub api_get_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;
return $get_rateplan;
}
@@ -354,8 +433,6 @@ sub api_get_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;
return $get_user;
}
@@ -372,12 +449,27 @@ sub api_get_accesspoint {
my $get_accesspoint = $self->api_call("GET", "/access_points/$accesspoint");
return if $self->api_error;
- $self->{'__saisei_error'} = "Did not receive any access point info"
- unless $get_accesspoint;
return $get_accesspoint;
}
+=head2 api_get_host
+
+Gets user info for specific host.
+
+=cut
+
+sub api_get_host {
+ my $self = shift;
+ my $ip = shift;
+
+ my $get_host = $self->api_call("GET", "/hosts/$ip");
+
+ return if $self->api_error;
+
+ return $get_host;
+}
+
=head2 api_create_rateplan
Creates a rateplan.
@@ -387,6 +479,9 @@ Creates a rateplan.
sub api_create_rateplan {
my ($self, $svc, $rateplan) = @_;
+ $self->{'__saisei_error'} = "No downrate listed for service $rateplan" if !$svc->{Hash}->{speed_down};
+ $self->{'__saisei_error'} = "No uprate listed for service $rateplan" if !$svc->{Hash}->{speed_up};
+
my $new_rateplan = $self->api_call(
"PUT",
"/rate_plans/$rateplan",
@@ -394,22 +489,26 @@ sub api_create_rateplan {
'downstream_rate' => $svc->{Hash}->{speed_down},
'upstream_rate' => $svc->{Hash}->{speed_up},
},
- );
+ ) unless $self->{'__saisei_error'};
$self->{'__saisei_error'} = "Rate Plan not created"
- unless $new_rateplan; # should never happen
+ unless ($new_rateplan || $self->{'__saisei_error'});
+
return $new_rateplan;
}
=head2 api_modify_rateplan
-Modify a rateplan.
+Modify a new rateplan.
=cut
sub api_modify_rateplan {
- my ($self,$policies,$svc,$rateplan_name) = @_;
+ my ($self,$svc,$rateplan_name) = @_;
+
+ # get policy list
+ my $policies = $self->api_get_policies();
foreach my $policy (@$policies) {
my $policyname = $policy->{name};
@@ -425,8 +524,8 @@ sub api_modify_rateplan {
},
);
- $self->{'__saisei_error'} = "Rate Plan not modified"
- unless $modified_rateplan; # should never happen
+ $self->{'__saisei_error'} = "Rate Plan not modified after create"
+ unless ($modified_rateplan || $self->{'__saisei_error'}); # should never happen
}
@@ -434,6 +533,31 @@ sub api_modify_rateplan {
}
+=head2 api_modify_existing_rateplan
+
+Modify a existing rateplan.
+
+=cut
+
+sub api_modify_existing_rateplan {
+ my ($self,$svc,$rateplan_name) = @_;
+
+ my $modified_rateplan = $self->api_call(
+ "PUT",
+ "/rate_plans/$rateplan_name",
+ {
+ 'downstream_rate' => $svc->{Hash}->{speed_down},
+ 'upstream_rate' => $svc->{Hash}->{speed_up},
+ },
+ );
+
+ $self->{'__saisei_error'} = "Rate Plan not modified"
+ unless ($modified_rateplan || $self->{'__saisei_error'}); # should never happen
+
+ return;
+
+}
+
=head2 api_create_user
Creates a user.
@@ -452,7 +576,7 @@ sub api_create_user {
);
$self->{'__saisei_error'} = "User not created"
- unless $new_user; # should never happen
+ unless ($new_user || $self->{'__saisei_error'}); # should never happen
return $new_user;
@@ -465,34 +589,34 @@ Creates a access point.
=cut
sub api_create_accesspoint {
- my ($self,$accesspoint, $uprate, $downrate) = @_;
+ my ($self,$accesspoint, $upratelimit, $downratelimit) = @_;
# this has not been tested, but should work, if needed.
my $new_accesspoint = $self->api_call(
"PUT",
"/access_points/$accesspoint",
{
- 'downstream_rate_limit' => $downrate,
- 'upstream_rate_limit' => $uprate,
+ 'downstream_rate_limit' => $downratelimit,
+ 'upstream_rate_limit' => $upratelimit,
},
);
$self->{'__saisei_error'} = "Access point not created"
- unless $new_accesspoint; # should never happen
+ unless ($new_accesspoint || $self->{'__saisei_error'}); # should never happen
return;
}
=head2 api_modify_accesspoint
-Modify a access point.
+Modify a new access point.
=cut
sub api_modify_accesspoint {
my ($self, $accesspoint, $uplink) = @_;
- my $modified_rateplan = $self->api_call(
+ my $modified_accesspoint = $self->api_call(
"PUT",
"/access_points/$accesspoint",
{
@@ -501,7 +625,33 @@ sub api_modify_accesspoint {
);
$self->{'__saisei_error'} = "Rate Plan not modified"
- unless $modified_rateplan; # should never happen
+ unless ($modified_accesspoint || $self->{'__saisei_error'}); # should never happen
+
+ return;
+
+}
+
+=head2 api_modify_existing_accesspoint
+
+Modify a existing accesspoint.
+
+=cut
+
+sub api_modify_existing_accesspoint {
+ my ($self, $accesspoint, $uplink, $upratelimit, $downratelimit) = @_;
+
+ my $modified_accesspoint = $self->api_call(
+ "PUT",
+ "/access_points/$accesspoint",
+ {
+ 'downstream_rate_limit' => $downratelimit,
+ 'upstream_rate_limit' => $upratelimit,
+# 'uplink' => $uplink, # name of attached access point
+ },
+ );
+
+ $self->{'__saisei_error'} = "Access point not modified"
+ unless ($modified_accesspoint || $self->{'__saisei_error'}); # should never happen
return;
@@ -527,7 +677,7 @@ sub api_add_host_to_user {
);
$self->{'__saisei_error'} = "Host not created"
- unless $new_host; # should never happen
+ unless ($new_host || $self->{'__saisei_error'}); # should never happen
return $new_host;
@@ -560,12 +710,114 @@ sub api_delete_host_to_user {
);
$self->{'__saisei_error'} = "Host not created"
- unless $delete_host; # should never happen
+ unless ($delete_host || $self->{'__saisei_error'}); # should never happen
return $delete_host;
}
+sub process_tower {
+ my ($self, $opt) = @_;
+
+ my $existing_tower_ap;
+ my $tower_name = $opt->{tower_name};
+
+ #check if tower has been set up as an access point.
+ $existing_tower_ap = $self->api_get_accesspoint($tower_name) unless $self->{'__saisei_error'};
+
+ # modify the existing accesspoint if changing tower .
+ $self->api_modify_existing_accesspoint (
+ $tower_name,
+ '', # tower does not have a uplink on sectors.
+ $opt->{tower_uprate_limit},
+ $opt->{tower_downrate_limit},
+ ) if $existing_tower_ap && $opt->{modify_existing};
+
+ #if tower does not exist as an access point create it.
+ $self->api_create_accesspoint(
+ $tower_name,
+ $opt->{tower_uprate_limit},
+ $opt->{tower_downrate_limit}
+ ) unless $existing_tower_ap;
+
+ my $accesspoint = $self->api_get_accesspoint($tower_name);
+
+ return $accesspoint;
+}
+
+sub process_sector {
+ my ($self, $opt) = @_;
+
+ my $existing_sector_ap;
+ my $sector_name = $opt->{sector_name};
+
+ #check if sector has been set up as an access point.
+ $existing_sector_ap = $self->api_get_accesspoint($sector_name);
+
+ # modify the existing accesspoint if changing sector .
+ $self->api_modify_existing_accesspoint (
+ $sector_name,
+ $opt->{tower_name},
+ $opt->{sector_uprate_limit},
+ $opt->{sector_downrate_limit},
+ ) if $existing_sector_ap && $opt->{modify_existing};
+
+ #if sector does not exist as an access point create it.
+ $self->api_create_accesspoint(
+ $sector_name,
+ $opt->{sector_uprate_limit},
+ $opt->{sector_downrate_limit},
+ ) unless $existing_sector_ap;
+
+ # Attach newly created sector to it's tower.
+ $self->api_modify_accesspoint($sector_name, $opt->{tower_name}) unless ($self->{'__saisei_error'} || $existing_sector_ap);
+
+ # set access point to existing one or newly created one.
+ my $accesspoint = $existing_sector_ap ? $existing_sector_ap : $self->api_get_accesspoint($sector_name);
+
+ return $accesspoint;
+}
+
+sub export_provisioned_services {
+ my $job = shift;
+ my $param = shift;
+
+ my $part_export = FS::Record::qsearchs('part_export', { 'exportnum' => $param->{export_provisioned_services_exportnum}, } )
+ or die "unknown exportnum $param->{export_provisioned_services_exportnum}";
+ bless $part_export;
+
+ my @svcparts = FS::Record::qsearch({
+ 'table' => 'export_svc',
+ 'addl_from' => 'LEFT JOIN part_svc USING ( svcpart ) ',
+ 'hashref' => { 'exportnum' => $param->{export_provisioned_services_exportnum}, },
+ });
+ my $part_count = scalar @svcparts;
+
+ my $parts = join "', '", map { $_->{Hash}->{svcpart} } @svcparts;
+
+ my @svcs = FS::Record::qsearch({
+ 'table' => 'cust_svc',
+ 'addl_from' => 'LEFT JOIN svc_broadband USING ( svcnum ) ',
+ 'extra_sql' => " WHERE svcpart in ('".$parts."')",
+ });
+
+ my $svc_count = scalar @svcs;
+
+ my %status = {};
+ for (my $c=10; $c <=100; $c=$c+10) { $status{int($svc_count * ($c/100))} = $c; }
+
+ my $process_count=0;
+ foreach my $svc (@svcs) {
+ if ($status{$process_count}) { my $s = $status{$process_count}; $job->update_statustext($s); }
+ ## check if service exists as host if not export it.
+ _export_insert($part_export,$svc) unless api_get_host($part_export, $svc->{Hash}->{ip_addr});
+ $process_count++;
+ }
+
+ return;
+
+}
+
=head1 SEE ALSO
L<FS::part_export>
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index dcc7843..3415595 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -519,6 +519,18 @@ sub part_export_dsl_pull {
grep $_->can('dsl_pull'), $self->part_export;
}
+=item part_export_partsvc
+
+Returns a list of any exports (see L<FS::part_export>) for this service that
+are capable of pushing a change after part svc is changed.
+
+=cut
+
+sub part_export_partsvc {
+ my $self = shift;
+ grep $_->can('export_partsvc'), $self->part_export;
+}
+
=item cust_svc [ PKGPART ]
Returns a list of associated customer services (FS::cust_svc records).
@@ -909,6 +921,11 @@ sub process {
);
die "$error\n" if $error;
+
+ foreach my $part_svc_export ( $new->part_export_partsvc ) {
+ $error = $part_svc_export->export_partsvc($new);
+ }
+ return $error if $error;
}
=item process_bulk_cust_svc
diff --git a/FS/FS/tower.pm b/FS/FS/tower.pm
index 5dcf1f8..13453f1 100644
--- a/FS/FS/tower.pm
+++ b/FS/FS/tower.pm
@@ -44,13 +44,13 @@ Tower name
Disabled flag, empty or 'Y'
-=item up_rate
+=item up_rate_limit
-Up Rate for towner
+Up Rate limit for towner
-=item down_rate
+=item down_rate_limit
-Down Rate for tower
+Down Rate limit for tower
=back
@@ -105,8 +105,8 @@ sub check {
|| $self->ut_floatn('height')
|| $self->ut_floatn('veg_height')
|| $self->ut_alphan('color')
- || $self->ut_numbern('up_rate')
- || $self->ut_numbern('down_rate')
+ || $self->ut_numbern('up_rate_limit')
+ || $self->ut_numbern('down_rate_limit')
;
return $error if $error;
diff --git a/FS/FS/tower_sector.pm b/FS/FS/tower_sector.pm
index b58cacf..90d6a9c 100644
--- a/FS/FS/tower_sector.pm
+++ b/FS/FS/tower_sector.pm
@@ -92,13 +92,13 @@ The coordinate boundaries of the coverage map.
The sector title.
-=item up_rate
+=item up_rate_limit
-Up rate for sector.
+Up rate limit for sector.
-=item down_rate
+=item down_rate_limit
-down rate for sector.
+down rate limit for sector.
=back
@@ -162,8 +162,8 @@ sub check {
|| $self->ut_numbern('downtilt')
|| $self->ut_floatn('sector_range')
|| $self->ut_numbern('margin')
- || $self->ut_numbern('up_rate')
- || $self->ut_numbern('down_rate')
+ || $self->ut_numbern('up_rate_limit')
+ || $self->ut_numbern('down_rate_limit')
|| $self->ut_anything('image')
|| $self->ut_sfloatn('west')
|| $self->ut_sfloatn('east')
@@ -251,6 +251,27 @@ sub queue_generate_coverage {
=back
+=head1 CLASS METHODS
+
+=over 4
+
+=item part_export_svc_broadband
+
+Returns all svc_broadband exports.
+
+=cut
+
+sub part_export_svc_broadband {
+ my $info = $FS::part_export::exports{'svc_broadband'} or return;
+ my @exporttypes = map { dbh->quote($_) } keys %$info or return;
+ qsearch({
+ 'table' => 'part_export',
+ 'extra_sql' => 'WHERE exporttype IN(' . join(',', @exporttypes) . ')'
+ });
+}
+
+=back
+
=head1 SUBROUTINES
=over 4
diff --git a/httemplate/edit/part_export.cgi b/httemplate/edit/part_export.cgi
index 5411feb..381fbca 100644
--- a/httemplate/edit/part_export.cgi
+++ b/httemplate/edit/part_export.cgi
@@ -290,6 +290,20 @@ my $widget = new HTML::Widgets::SelectLayers(
$html .= ' CHECKED' if $part_export->no_suspend eq 'Y';
$html .= '></TD></TR>';
+ foreach my $script ( keys %{$exports->{$layer}{scripts}} ) {
+ $html .= '<TR><TD ALIGN="left" COLSPAN=2>' .
+ include('/elements/progress-init.html',
+ $part_export->exportname,
+ [ $script.'_exportnum', $script.'_script' ],
+ rooturl().'view/svc_export/run_script.cgi',
+ rooturl().'edit/part_export.cgi?'.$part_export->{Hash}->{exportnum},
+ $script,
+ ) .
+ '<INPUT TYPE="hidden" NAME="'.$script.'_exportnum" VALUE="'.$part_export->{Hash}->{exportnum}.'">
+ <INPUT TYPE="hidden" NAME="'.$script.'_script" VALUE="'.$script.'">
+ <A HREF="#" onClick="'.$script.'process();">'.$exports->{$layer}{scripts}{$script}->{html_label}.'</A></TD></TR>';
+ }
+
$html .= '</TABLE>';
# false laziness with config_element above
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 76722c9..8c307f0 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -459,6 +459,14 @@ foreach my $value ( @values ) {
}
+if ($class eq "FS::tower") {
+ foreach my $part_svc_broadband_export ( FS::tower_sector->part_export_svc_broadband ) {
+ if ($part_svc_broadband_export and $part_svc_broadband_export->can('export_tower_sector')) {
+ $error = $part_svc_broadband_export->export_tower_sector($new);
+ }
+ }
+}
+
# set up redirect URLs
my $redirect;
diff --git a/httemplate/edit/process/tower.html b/httemplate/edit/process/tower.html
index e17cd55..ba7309c 100644
--- a/httemplate/edit/process/tower.html
+++ b/httemplate/edit/process/tower.html
@@ -5,7 +5,7 @@
'fields' => [qw(
sectorname ip_addr height freq_mhz direction width
downtilt v_width margin
- sector_range up_rate down_rate
+ sector_range up_rate_limit down_rate_limit
)],
},
&>
diff --git a/httemplate/edit/tower.html b/httemplate/edit/tower.html
index 6607888..b9fea77 100644
--- a/httemplate/edit/tower.html
+++ b/httemplate/edit/tower.html
@@ -12,8 +12,8 @@
'altitude',
'height',
'veg_height',
- 'up_rate',
- 'down_rate',
+ 'up_rate_limit',
+ 'down_rate_limit',
{ field => 'sectornum',
type => 'tower_sector',
o2m_table => 'tower_sector',
@@ -32,8 +32,8 @@
'height' => 'Height (feet)',
'veg_height' => 'Vegetation height (feet)',
'color' => 'Color',
- 'up_rate' => 'Up Rate (Kbps)',
- 'down_rate' => 'Down Rate (Kbps)',
+ 'up_rate_limit' => 'Up Rate Limit(Kbps)',
+ 'down_rate_limit' => 'Down Rate Limit(Kbps)',
},
&>
<%init>
@@ -43,7 +43,7 @@ my $m2_error_callback = sub { # reconstruct the list
my @fields = qw(
sectorname ip_addr height freq_mhz direction width tilt v_width margin
- sector_range up_rate down_rate
+ sector_range up_rate_limit down_rate_limit
);
map {
diff --git a/httemplate/elements/tr-tower_sectors.html b/httemplate/elements/tr-tower_sectors.html
index 6843f4f..8acedb8 100644
--- a/httemplate/elements/tr-tower_sectors.html
+++ b/httemplate/elements/tr-tower_sectors.html
@@ -17,7 +17,7 @@ my $tabcounter = 0;
my @fields = qw(
sectorname ip_addr height freq_mhz direction width downtilt v_width
db_high db_low sector_range
- power line_loss antenna_gain hardware_typenum up_rate down_rate
+ power line_loss antenna_gain hardware_typenum up_rate_limit down_rate_limit
);
my @sectors;
@@ -294,16 +294,16 @@ $(function() {
<p>
<label><% emt('Up Rate (Kbps)') %></label>
<input style="text-align: left"
- id="<% $id %>_up_rate"
- name="<% $id %>_up_rate"
- value="<% $sector->up_rate |h %>">
+ id="<% $id %>_up_rate_limit"
+ name="<% $id %>_up_rate_limit"
+ value="<% $sector->up_rate_limit |h %>">
</p>
<p>
<label><% emt('Down Rate (Kbps)') %></label>
<input style="text-align: left"
- id="<% $id %>_down_rate"
- name="<% $id %>_down_rate"
- value="<% $sector->down_rate |h %>">
+ id="<% $id %>_down_rate_limit"
+ name="<% $id %>_down_rate_limit"
+ value="<% $sector->down_rate_limit |h %>">
</p>
</div>