diff options
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/AccessRight.pm | 1 | ||||
-rw-r--r-- | FS/FS/Mason.pm | 4 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 74 | ||||
-rw-r--r-- | FS/FS/UI/Web.pm | 19 | ||||
-rwxr-xr-x | FS/FS/addr_block.pm | 18 | ||||
-rw-r--r-- | FS/FS/circuit_provider.pm | 101 | ||||
-rw-r--r-- | FS/FS/circuit_termination.pm | 98 | ||||
-rw-r--r-- | FS/FS/circuit_type.pm | 98 | ||||
-rwxr-xr-x | FS/FS/router.pm | 7 | ||||
-rw-r--r-- | FS/FS/svc_circuit.pm | 230 | ||||
-rw-r--r-- | FS/FS/svc_phone.pm | 35 | ||||
-rw-r--r-- | FS/MANIFEST | 8 | ||||
-rw-r--r-- | FS/t/circuit_provider.t | 5 | ||||
-rw-r--r-- | FS/t/circuit_termination.t | 5 | ||||
-rw-r--r-- | FS/t/circuit_type.t | 5 | ||||
-rw-r--r-- | FS/t/svc_circuit.t | 5 |
16 files changed, 710 insertions, 3 deletions
diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm index bad831a94..92cede6a5 100644 --- a/FS/FS/AccessRight.pm +++ b/FS/FS/AccessRight.pm @@ -310,6 +310,7 @@ tie my %rights, 'Tie::IxHash', 'Services: Mailing lists', 'Services: Alarm services', 'Services: Video', + 'Services: Circuits', 'Services: External services', 'Usage: RADIUS sessions', 'Usage: Call Detail Records (CDRs)', diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 900da1005..d3e45dfee 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -392,6 +392,10 @@ if ( -e $addl_handler_use_file ) { use FS::deploy_zone_vertex; use FS::TaxEngine; use FS::tax_status; + use FS::circuit_type; + use FS::circuit_provider; + use FS::circuit_termination; + use FS::svc_circuit; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 715a603f8..91dfc5d97 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -5653,6 +5653,7 @@ sub tables_hashref { 'max_simultaneous', 'int', 'NULL', '', '', '', 'e911_class', 'char', 'NULL', 1, '', '', 'e911_type', 'char', 'NULL', 1, '', '', + 'circuit_svcnum', 'int', 'NULL', '', '', '', ], 'primary_key' => 'svcnum', 'unique' => [ [ 'sms_carrierid', 'sms_account'] ], @@ -5678,6 +5679,10 @@ sub tables_hashref { table => 'cdr_carrier', references => [ 'carrierid' ], }, + { columns => [ 'circuit_svcnum' ], + table => 'svc_circuit', + references => [ 'svcnum' ], + }, ], }, @@ -6527,6 +6532,75 @@ sub tables_hashref { ], }, + 'circuit_type' => { + 'columns' => [ + 'typenum', 'serial', '', '', '', '', + 'typename', 'varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + # speed? number of voice lines? anything else? + ], + 'primary_key' => 'typenum', + 'unique' => [ [ 'typename' ] ], + 'index' => [], + }, + + 'circuit_provider' => { + 'columns' => [ + 'providernum', 'serial', '', '', '', '', + 'provider', 'varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'providernum', + 'unique' => [ [ 'provider' ], ], + 'index' => [], + }, + + 'circuit_termination' => { + 'columns' => [ + 'termnum', 'serial', '', '', '', '', + 'termination','varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'termnum', + 'unique' => [ [ 'termination' ] ], + 'index' => [], + }, + + 'svc_circuit' => { + 'columns' => [ + 'svcnum', 'int', '', '', '', '', + 'typenum', 'int', '', '', '', '', + 'providernum', 'int', '', '', '', '', + 'termnum', 'int', '', '', '', '', + 'circuit_id', 'varchar', '', 64, '', '', + 'desired_due_date', 'int', 'NULL', '', '', '', + 'due_date', 'int', 'NULL', '', '', '', + 'vendor_order_id', 'varchar', 'NULL', $char_d, '', '', + 'vendor_qual_id', 'varchar', 'NULL', $char_d, '', '', + 'vendor_order_type', 'varchar', 'NULL', $char_d, '', '', + 'vendor_order_status', 'varchar', 'NULL', $char_d, '', '', + 'endpoint_ip_addr', 'varchar', 'NULL', 40, '', '', + 'endpoint_mac_addr', 'varchar', 'NULL', 12, '', '', + ], + 'primary_key' => 'svcnum', + 'unique' => [], + 'index' => [ [ 'providernum' ], [ 'typenum' ] ], + 'foreign_keys' => [ + { columns => [ 'svcnum' ], + table => 'cust_svc', + }, + { columns => [ 'typenum' ], + table => 'circuit_type', + }, + { columns => [ 'providernum' ], + table => 'circuit_provider', + }, + { columns => [ 'termnum' ], + table => 'circuit_termination', + }, + ], + }, + 'vend_main' => { 'columns' => [ 'vendnum', 'serial', '', '', '', '', diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm index 99c35609e..e13869265 100644 --- a/FS/FS/UI/Web.pm +++ b/FS/FS/UI/Web.pm @@ -113,16 +113,16 @@ sub svc_url { if $DEBUG; if ( $opt{m}->interp->comp_exists("/$opt{action}/$svcdb.cgi") ) { $url = "$svcdb.cgi?"; + } elsif ( $opt{m}->interp->comp_exists("/$opt{action}/$svcdb.html") ) { + $url = "$svcdb.html?"; } else { - my $generic = $opt{action} eq 'search' ? 'cust_svc' : 'svc_Common'; $url = "$generic.html?svcdb=$svcdb;"; $url .= 'svcnum=' if $query =~ /^\d+(;|$)/ or $query eq ''; } - import FS::CGI 'rooturl'; #WTF! why is this necessary - my $return = rooturl(). "$opt{action}/$url$query"; + my $return = FS::CGI::rooturl(). "$opt{action}/$url$query"; $return = qq!<A HREF="$return">! if $opt{ahref}; @@ -574,6 +574,19 @@ sub cust_aligns { } } +=item cust_links + +Returns an array of links to view/cust_main.cgi, for use with cust_fields. + +=cut + +sub cust_links { + my $link = [ FS::CGI::rooturl().'view/cust_main.cgi?', 'custnum' ]; + + return map { $_ eq 'cust_status_label' ? '' : $link } + @cust_fields; +} + =item is_mobile Utility function to determine if the client is a mobile browser. diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm index 3e62a688b..ba0f61db1 100755 --- a/FS/FS/addr_block.pm +++ b/FS/FS/addr_block.pm @@ -388,6 +388,24 @@ sub label { ($router ? $router->routername : '(unallocated)'). ':'. $self->NetAddr; } +=item router + +Returns the router assigned to this block. + +=cut + +# necessary, because this can't be foreign keyed + +sub router { + my $self = shift; + my $routernum = $self->routernum; + if ( $routernum ) { + return FS::router->by_key($routernum); + } else { + return; + } +} + =back =head1 BUGS diff --git a/FS/FS/circuit_provider.pm b/FS/FS/circuit_provider.pm new file mode 100644 index 000000000..6cb784117 --- /dev/null +++ b/FS/FS/circuit_provider.pm @@ -0,0 +1,101 @@ +package FS::circuit_provider; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::circuit_provider - Object methods for circuit_provider records + +=head1 SYNOPSIS + + use FS::circuit_provider; + + $record = new FS::circuit_provider \%hash; + $record = new FS::circuit_provider { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::circuit_provider object represents a telecom carrier that provides +physical circuits (L<FS::svc_circuit>). FS::circuit_provider inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item providernum - primary key + +=item provider - provider name + +=item disabled - disabled + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new record. To add the record to the database, see L<"insert">. + +=cut + +sub table { 'circuit_provider'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +# the check method should currently be supplied - FS::Record contains some +# data checking routines + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('providernum') + || $self->ut_text('provider') + || $self->ut_flag('disabled') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/circuit_termination.pm b/FS/FS/circuit_termination.pm new file mode 100644 index 000000000..3f0afc1f9 --- /dev/null +++ b/FS/FS/circuit_termination.pm @@ -0,0 +1,98 @@ +package FS::circuit_termination; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::circuit_termination - Object methods for circuit_termination records + +=head1 SYNOPSIS + + use FS::circuit_termination; + + $record = new FS::circuit_termination \%hash; + $record = new FS::circuit_termination { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::circuit_termination object represents a central office circuit +interface type. FS::circuit_termination inherits from FS::Record. The +following fields are currently supported: + +=over 4 + +=item termnum - primary key + +=item termination - description of the termination type + +=item disabled - 'Y' if this is disabled + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example. To add the example to the database, see L<"insert">. + +=cut + +sub table { 'circuit_termination'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('termnum') + || $self->ut_text('termination') + || $self->ut_flag('disabled') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/circuit_type.pm b/FS/FS/circuit_type.pm new file mode 100644 index 000000000..3b3653693 --- /dev/null +++ b/FS/FS/circuit_type.pm @@ -0,0 +1,98 @@ +package FS::circuit_type; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::circuit_type - Object methods for circuit_type records + +=head1 SYNOPSIS + + use FS::circuit_type; + + $record = new FS::circuit_type \%hash; + $record = new FS::circuit_type { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::circuit_type object represents a circuit type (such as "DS1" or "OC3"). +FS::circuit_type inherits from FS::Record. The following fields are currently +supported: + +=over 4 + +=item typenum - primary key + +=item typename - name of the circuit type + +=item disabled - 'Y' if this is disabled + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new example. To add the example to the database, see L<"insert">. + +=cut + +sub table { 'circuit_type'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid example. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('typenum') + || $self->ut_text('typename') + || $self->ut_flag('disabled') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/router.pm b/FS/FS/router.pm index 4011bb097..c0c93dd32 100755 --- a/FS/FS/router.pm +++ b/FS/FS/router.pm @@ -200,6 +200,13 @@ sub delete { Returns a list of FS::addr_block objects (address blocks) associated with this object. +=cut + +sub addr_block { + my $self = shift; + qsearch('addr_block', { routernum => $self->routernum }); +} + =item auto_addr_block Returns a list of address blocks on which auto-assignment of IP addresses diff --git a/FS/FS/svc_circuit.pm b/FS/FS/svc_circuit.pm new file mode 100644 index 000000000..f705c68f4 --- /dev/null +++ b/FS/FS/svc_circuit.pm @@ -0,0 +1,230 @@ +package FS::svc_circuit; + +use strict; +use base qw( + FS::svc_IP_Mixin + FS::MAC_Mixin + FS::svc_Common +); +use FS::Record qw( qsearch qsearchs ); +use FS::circuit_provider; +use FS::circuit_type; +use FS::circuit_termination; + +=head1 NAME + +FS::svc_circuit - Object methods for svc_circuit records + +=head1 SYNOPSIS + + use FS::svc_circuit; + + $record = new FS::svc_circuit \%hash; + $record = new FS::svc_circuit { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::svc_circuit object represents a telecom circuit service (other than +an analog phone line, which is svc_phone, or a DSL Internet connection, +which is svc_dsl). FS::svc_circuit inherits from FS::svc_IP_Mixin, +FS::MAC_Mixin, and FS::svc_Common. The following fields are currently +supported: + +=over 4 + +=item svcnum - primary key; see also L<FS::cust_svc> + +=item typenum - circuit type (such as DS1, DS1-PRI, DS3, OC3, etc.); foreign +key to L<FS::circuit_type>. + +=item providernum - circuit provider (telco); foreign key to +L<FS::circuit_provider>. + +=item termnum - circuit termination type; foreign key to +L<FS::circuit_termination> + +=item circuit_id - circuit ID string defined by the provider + +=item desired_due_date - the requested date for completion of the circuit +order + +=item due_date - the provider's committed date for completion of the circuit +order + +=item vendor_order_id - the provider's order number + +=item vendor_qual_id - the qualification number, if a qualification was +performed + +=item vendor_order_type - + +=item vendor_order_status - the order status: ACCEPTED, PENDING, COMPLETED, +etc. + +=item endpoint_ip_addr - the IP address of the endpoint equipment, if any. +This will be validated as an IP address but not assigned from managed address +space or checked for uniqueness. + +=item endpoint_mac_addr - the MAC address of the endpoint. + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new circuit service. To add the record to the database, see +L<"insert">. + +=cut + +sub table { 'svc_circuit'; } + +sub table_info { + my %dis = ( disable_default => 1, disable_fixed => 1, + disabled_inventory => 1, disable_select => 1 ); + + tie my %fields, 'Tie::IxHash', ( + 'svcnum' => 'Service', + 'providernum' => { + label => 'Provider', + type => 'select', + select_table => 'circuit_provider', + select_key => 'providernum', + select_label => 'provider', + disable_inventory => 1, + }, + 'typenum' => { + label => 'Circuit type', + type => 'select', + select_table => 'circuit_type', + select_key => 'typenum', + select_label => 'typename', + disable_inventory => 1, + }, + 'termnum' => { + label => 'Termination type', + type => 'select', + select_table => 'circuit_termination', + select_key => 'termnum', + select_label => 'termination', + disable_inventory => 1, + }, + 'circuit_id' => { label => 'Circuit ID', %dis }, + 'desired_due_date' => { label => 'Desired due date', + %dis + }, + 'due_date' => { label => 'Due date', + %dis + }, + 'vendor_order_id' => { label => 'Vendor order ID', %dis }, + 'vendor_qual_id' => { label => 'Vendor qualification ID', %dis }, + 'vendor_order_type' => { + label => 'Vendor order type', + disable_inventory => 1 + }, # should be a select? + 'vendor_order_status' => { + label => 'Vendor order status', + disable_inventory => 1 + }, # should also be a select? + 'endpoint_ip_addr' => { + label => 'Endpoint IP address', + }, + 'endpoint_mac_addr' => { + label => 'Endpoint MAC address', + type => 'input-mac_addr', + disable_inventory => 1, + }, + ); + return { + 'name' => 'Circuit', + 'name_plural' => 'Circuits', + 'longname_plural' => 'Voice and data circuit services', + 'display_weight' => 72, + 'cancel_weight' => 85, # after svc_phone + 'fields' => \%fields, + }; +} + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=item delete + +Delete this record from the database. + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=item check + +Checks all fields to make sure this is a valid service. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $mac_addr = uc($self->get('endpoint_mac_addr')); + $mac_addr =~ s/[\W_]//g; + $self->set('endpoint_mac_addr', $mac_addr); + + my $error = + $self->ut_numbern('svcnum') + || $self->ut_number('typenum') + || $self->ut_number('providernum') + || $self->ut_text('circuit_id') + || $self->ut_numbern('desired_due_date') + || $self->ut_numbern('due_date') + || $self->ut_textn('vendor_order_id') + || $self->ut_textn('vendor_qual_id') + || $self->ut_textn('vendor_order_type') + || $self->ut_textn('vendor_order_status') + || $self->ut_ipn('endpoint_ip_addr') + || $self->ut_textn('endpoint_mac_addr') + ; + + # no canonical values yet for vendor_order_status or _type + + return $error if $error; + + $self->SUPER::check; +} + +=item label + +Returns the circuit ID. + +=cut + +sub label { + my $self = shift; + $self->get('circuit_id'); +} + +=back + +=head1 SEE ALSO + +L<FS::Record> + +=cut + +1; + diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 4ca8d82fa..bd35cbac4 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -189,6 +189,14 @@ sub table_info { select_label => 'domain', disable_inventory => 1, }, + 'circuit_svcnum' => { label => 'Circuit', + type => 'select', + select_table => 'svc_domain', + select_key => 'svcnum', + select_label => 'circuit_label', + disable_inventory => 1, + }, + 'sms_carrierid' => { label => 'SMS Carrier', type => 'select', select_table => 'cdr_carrier', @@ -711,6 +719,8 @@ sub radius_groups { =item sms_cdr_carrier +Returns the L<FS::cdr_carrier> assigned as the SMS carrier for this phone. + =cut sub sms_cdr_carrier { @@ -721,6 +731,8 @@ sub sms_cdr_carrier { =item sms_carriername +Returns the name of the SMS carrier, or an empty string if there isn't one. + =cut sub sms_carriername { @@ -729,6 +741,29 @@ sub sms_carriername { $cdr_carrier->carriername; } +=item svc_circuit + +Returns the L<FS::svc_circuit> assigned as the trunk for this phone line. + +=item circuit_label + +Returns the label of the circuit (the part_svc label followed by the +circuit ID), or an empty string if there isn't one. + +=cut + +sub svc_circuit { + my $self = shift; + my $svcnum = $self->get('circuit_svcnum') or return ''; + return FS::svc_circuit->by_key($svcnum); +} + +sub circuit_label { + my $self = shift; + my $svc_circuit = $self->svc_circuit or return ''; + return join(' ', $svc_circuit->part_svc->svc, $svc_circuit->circuit_id); +} + =item phone_device Returns any FS::phone_device records associated with this service. diff --git a/FS/MANIFEST b/FS/MANIFEST index 79a7dc523..105447c6b 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -821,3 +821,11 @@ FS/deploy_zone_vertex.pm t/deploy_zone_vertex.t FS/tax_status.pm t/tax_status.t +FS/circuit_type.pm +t/circuit_type.t +FS/circuit_provider.pm +t/circuit_provider.t +FS/circuit_termination.pm +t/circuit_termination.t +FS/svc_circuit.pm +t/svc_circuit.t diff --git a/FS/t/circuit_provider.t b/FS/t/circuit_provider.t new file mode 100644 index 000000000..753a156d5 --- /dev/null +++ b/FS/t/circuit_provider.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::circuit_provider; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/circuit_termination.t b/FS/t/circuit_termination.t new file mode 100644 index 000000000..6f5127195 --- /dev/null +++ b/FS/t/circuit_termination.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::circuit_termination; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/circuit_type.t b/FS/t/circuit_type.t new file mode 100644 index 000000000..dbb6e0ac5 --- /dev/null +++ b/FS/t/circuit_type.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::circuit_type; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/svc_circuit.t b/FS/t/svc_circuit.t new file mode 100644 index 000000000..7fefcc04b --- /dev/null +++ b/FS/t/svc_circuit.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::svc_circuit; +$loaded=1; +print "ok 1\n"; |