diff options
author | mark <mark> | 2011-04-01 02:52:24 +0000 |
---|---|---|
committer | mark <mark> | 2011-04-01 02:52:24 +0000 |
commit | b65b8096089410001dfbcd35f9a56f9405b9f5f1 (patch) | |
tree | df16b0422007bd876bc969bdff857d8a510b0aca /FS | |
parent | 19b0c403fbf697a1de92f12abc8a2104daca07bc (diff) |
svc_hardware and svc_dish, #11454
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/Mason.pm | 5 | ||||
-rw-r--r-- | FS/FS/Record.pm | 30 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 60 | ||||
-rw-r--r-- | FS/FS/cust_pkg.pm | 2 | ||||
-rw-r--r-- | FS/FS/cust_svc.pm | 14 | ||||
-rw-r--r-- | FS/FS/hardware_class.pm | 127 | ||||
-rw-r--r-- | FS/FS/hardware_status.pm | 116 | ||||
-rw-r--r-- | FS/FS/hardware_type.pm | 131 | ||||
-rw-r--r-- | FS/FS/part_svc.pm | 5 | ||||
-rw-r--r-- | FS/FS/part_svc_column.pm | 10 | ||||
-rw-r--r-- | FS/FS/svc_dish.pm | 131 | ||||
-rw-r--r-- | FS/FS/svc_hardware.pm | 211 | ||||
-rw-r--r-- | FS/MANIFEST | 10 | ||||
-rw-r--r-- | FS/t/hardware_class.t | 5 | ||||
-rw-r--r-- | FS/t/hardware_status.t | 5 | ||||
-rw-r--r-- | FS/t/hardware_type.t | 5 | ||||
-rw-r--r-- | FS/t/svc_dish.t | 5 | ||||
-rw-r--r-- | FS/t/svc_hardware.t | 5 |
18 files changed, 872 insertions, 5 deletions
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index ccab79339..dd1871739 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -273,6 +273,11 @@ if ( -e $addl_handler_use_file ) { use FS::torrus_srvderive; use FS::torrus_srvderive_component; use FS::areacode; + use FS::svc_dish; + use FS::svc_hardware; + use FS::hardware_class; + use FS::hardware_type; + use FS::hardware_status; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index fb83faa3f..7b52f508e 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -21,6 +21,7 @@ use FS::CurrentUser; use FS::Schema qw(dbdef); use FS::SearchCache; use FS::Msgcat qw(gettext); +use NetAddr::IP; # for validation #use FS::Conf; #dependency loop bs, in install_callback below instead use FS::part_virtual_field; @@ -2376,6 +2377,35 @@ sub ut_ipn { } } +=item ut_ip46 COLUMN + +Check/untaint IPv4 or IPv6 address. + +=cut + +sub ut_ip46 { + my( $self, $field ) = @_; + my $ip = NetAddr::IP->new($self->getfield($field)) + or return "Illegal (IP address) $field: ".$self->getfield($field); + $self->setfield($field, lc($ip->addr)); + return ''; +} + +=item ut_ip46n + +Check/untaint IPv6 or IPv6 address. May be null. + +=cut + +sub ut_ip46n { + my( $self, $field ) = @_; + if ( $self->getfield($field) =~ /^$/ ) { + $self->setfield($field, ''); + return ''; + } + $self->ut_ip46($field); +} + =item ut_coord COLUMN [ LOWER [ UPPER ] ] Check/untaint coordinates. diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 25eafa345..66847b6c0 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1586,7 +1586,7 @@ sub tables_hashref { 'index' => [ [ 'svcnum' ], [ 'optionname' ] ], }, - 'part_pkg' => { + 'part_pkg' => { 'columns' => [ 'pkgpart', 'serial', '', '', '', '', 'pkg', 'varchar', '', $char_d, '', '', @@ -1745,6 +1745,7 @@ sub tables_hashref { 'svc', 'varchar', '', $char_d, '', '', 'svcdb', 'varchar', '', $char_d, '', '', 'disabled', 'char', 'NULL', 1, '', '', + 'preserve', 'char', 'NULL', 1, '', '', ], 'primary_key' => 'svcpart', 'unique' => [], @@ -2003,6 +2004,63 @@ sub tables_hashref { 'index' => [ ['svcnum'] ], }, + 'svc_dish' => { + 'columns' => [ + 'svcnum', 'int', '', '', '', '', + 'acctnum', 'varchar', '', 16, '', '', + 'note', 'text', 'NULL', '', '', '', + ], + 'primary_key' => 'svcnum', + 'unique' => [ ], + 'index' => [ ], + }, + + 'svc_hardware' => { + 'columns' => [ + 'svcnum', 'int', '', '', '', '', + 'typenum', 'int', '', '', '', '', + 'serial', 'varchar', 'NULL', $char_d, '', '', + 'ip_addr', 'varchar', 'NULL', 40, '', '', + 'hw_addr', 'varchar', 'NULL', 12, '', '', + 'statusnum','int', 'NULL', '', '', '', + 'note', 'text', 'NULL', '', '', '', + ], + 'primary_key' => 'svcnum', + 'unique' => [ ], + 'index' => [ ], + }, + + 'hardware_class' => { + 'columns' => [ + 'classnum', 'serial', '', '', '', '', + 'classname', 'varchar', '', $char_d, '', '', + ], + 'primary_key' => 'classnum', + 'unique' => [ ], + 'index' => [ ], + }, + + 'hardware_type' => { + 'columns' => [ + 'typenum', 'serial', '', '', '', '', + 'classnum', 'int', '', '', '', '', + 'model', 'varchar', '', $char_d, '', '', + ], + 'primary_key' => 'typenum', + 'unique' => [ ], + 'index' => [ ], + }, + + 'hardware_status' => { + 'columns' => [ + 'statusnum', 'serial', '', '', '', '', + 'label' ,'varchar', '', $char_d, '', '', + ], + 'primary_key' => 'statusnum', + 'unique' => [ ], + 'index' => [ ], + }, + 'domain_record' => { 'columns' => [ 'recnum', 'serial', '', '', '', '', diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 2efd4fd87..13a3b6eb7 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -761,6 +761,8 @@ sub cancel { map { [ $_, $_->svc_x->table_info->{'cancel_weight'} ]; } qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ) ) { + my $part_svc = $cust_svc->part_svc; + next if ( defined($part_svc) and $part_svc->preserve ); my $error = $cust_svc->cancel( %svc_cancel_opt ); if ( $error ) { diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index 30e49c598..8cce7afb4 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -371,6 +371,20 @@ sub date_inserted { $self->h_date('insert'); } +=item pkg_cancel_date + +Returns the date this service's package was canceled. This normally only +exists for a service that's been preserved through cancellation with the +part_pkg.preserve flag. + +=cut + +sub pkg_cancel_date { + my $self = shift; + my $cust_pkg = $self->cust_pkg or return; + return $cust_pkg->getfield('cancel') || ''; +} + =item label Returns a list consisting of: diff --git a/FS/FS/hardware_class.pm b/FS/FS/hardware_class.pm new file mode 100644 index 000000000..073a97f88 --- /dev/null +++ b/FS/FS/hardware_class.pm @@ -0,0 +1,127 @@ +package FS::hardware_class; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::hardware_class - Object methods for hardware_class records + +=head1 SYNOPSIS + + use FS::hardware_class; + + $record = new FS::hardware_class \%hash; + $record = new FS::hardware_class { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::hardware_class object represents a class of hardware types which can +be assigned to similar services (see L<FS::svc_hardware>). FS::hardware_class +inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item classnum - primary key + +=item classname - classname + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new record. To add the record to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'hardware_class'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=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. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid hardware class. 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('classnum') + || $self->ut_text('classname') + ; + return $error if $error; + + $self->SUPER::check; +} + +=item hardware_type + +Returns all L<FS::hardware_type> objects belonging to this class. + +=cut + +sub hardware_type { + my $self = shift; + return qsearch('hardware_type', { 'classnum' => $self->classnum }); +} + +=back + +=head1 SEE ALSO + +L<FS::hardware_type>, L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/hardware_status.pm b/FS/FS/hardware_status.pm new file mode 100644 index 000000000..4836fc5cb --- /dev/null +++ b/FS/FS/hardware_status.pm @@ -0,0 +1,116 @@ +package FS::hardware_status; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::hardware_status - Object methods for hardware_status records + +=head1 SYNOPSIS + + use FS::hardware_status; + + $record = new FS::hardware_status \%hash; + $record = new FS::hardware_status { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::hardware_status object represents an installation status for hardware +services. FS::hardware_status inherits from FS::Record. The following fields +are currently supported: + +=over 4 + +=item statusnum - primary key + +=item label - descriptive label + + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new record. To add the record to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'hardware_status'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=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. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid status. 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('statusnum') + || $self->ut_text('label') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 SEE ALSO + +L<FS::svc_hardware>, L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/hardware_type.pm b/FS/FS/hardware_type.pm new file mode 100644 index 000000000..ba19fcb21 --- /dev/null +++ b/FS/FS/hardware_type.pm @@ -0,0 +1,131 @@ +package FS::hardware_type; + +use strict; +use base qw( FS::Record ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::hardware_type - Object methods for hardware_type records + +=head1 SYNOPSIS + + use FS::hardware_type; + + $record = new FS::hardware_type \%hash; + $record = new FS::hardware_type { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::hardware_type object represents a device type (a model name or +number) assignable as a hardware service (L<FS::svc_hardware)>). +FS::hardware_type inherits from FS::Record. The following fields are +currently supported: + +=over 4 + +=item typenum - primary key + +=item classnum - key to an L<FS::hardware_class> record defining the class +to which this device type belongs. + +=item model - descriptive model name or number + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new record. To add the record to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'hardware_type'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=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. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid hardware type. 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('typenum') + || $self->ut_foreign_key('classnum', 'hardware_class', 'classnum') + || $self->ut_text('model') + ; + return $error if $error; + + $self->SUPER::check; +} + +=item hardware_class + +Returns the L<FS::hardware_class> associated with this device. + +=cut + +sub hardware_class { + my $self = shift; + return qsearchs('hardware_class', { 'classnum' => $self->classnum }); +} + +=back + +=head1 SEE ALSO + +L<FS::svc_hardware>, L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm index 164bad079..e15b22590 100644 --- a/FS/FS/part_svc.pm +++ b/FS/FS/part_svc.pm @@ -53,6 +53,8 @@ L<FS::svc_domain>, and L<FS::svc_forward>, among others. =item disabled - Disabled flag, empty or `Y' +=item preserve - Preserve after cancellation, empty or 'Y' + =back =head1 METHODS @@ -381,6 +383,7 @@ sub check { || $self->ut_text('svc') || $self->ut_alpha('svcdb') || $self->ut_enum('disabled', [ '', 'Y' ] ) + || $self->ut_enum('preserve', [ '', 'Y' ] ) ; return $error if $error; @@ -758,7 +761,7 @@ sub process { map { my $f = $svcdb.'__'.$_; - if ( $param->{ $f.'_flag' } =~ /^[MA]$/ ) { + if ( $param->{ $f.'_flag' } =~ /^[MAH]$/ ) { $param->{ $f } = delete( $param->{ $f.'_classnum' } ); } if ( $param->{ $f.'_flag' } =~ /^S$/ ) { diff --git a/FS/FS/part_svc_column.pm b/FS/FS/part_svc_column.pm index f5b39c049..d467516ed 100644 --- a/FS/FS/part_svc_column.pm +++ b/FS/FS/part_svc_column.pm @@ -43,7 +43,7 @@ fields are currently supported: =item columnvalue - default or fixed value for the column -=item columnflag - null or empty (no default), `D' for default, `F' for fixed (unchangeable), `S' for selectable choice, `M' for manual selection from inventory, or `A' for automatic selection from inventory. For virtual fields, can also be 'X' for excluded. +=item columnflag - null or empty (no default), `D' for default, `F' for fixed (unchangeable), `S' for selectable choice, `M' for manual selection from inventory, `A' for automatic selection from inventory, or `H' for selection from a hardware class. For virtual fields, can also be 'X' for excluded. =back @@ -94,15 +94,19 @@ sub check { ; return $error if $error; - $self->columnflag =~ /^([DFSMAX]?)$/ + $self->columnflag =~ /^([DFSMAHX]?)$/ or return "illegal columnflag ". $self->columnflag; $self->columnflag(uc($1)); if ( $self->columnflag =~ /^[MA]$/ ) { $error = $self->ut_foreign_key( 'columnvalue', 'inventory_class', 'classnum' ); - return $error if $error; } + if ( $self->columnflag eq 'H' ) { + $error = + $self->ut_foreign_key( 'columnvalue', 'hardware_class', 'classnum' ); + } + return $error if $error; $self->SUPER::check; } diff --git a/FS/FS/svc_dish.pm b/FS/FS/svc_dish.pm new file mode 100644 index 000000000..5dac4f4d5 --- /dev/null +++ b/FS/FS/svc_dish.pm @@ -0,0 +1,131 @@ +package FS::svc_dish; + +use strict; +use base qw( FS::svc_Common ); +use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::svc_dish - Object methods for svc_dish records + +=head1 SYNOPSIS + + use FS::svc_dish; + + $record = new FS::svc_dish \%hash; + $record = new FS::svc_dish { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::svc_dish object represents a Dish Network service. FS::svc_dish +inherits from FS::svc_Common. + +The following fields are currently supported: + +=over 4 + +=item svcnum - Primary key + +=item acctnum - DISH account number + +=item note - Installation notes: location on property, physical access, etc. + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new svc_dish object. + +=cut + +sub table { 'svc_dish'; } + +sub table_info { + my %opts = ( 'type' => 'text', + 'disable_select' => 1, + 'disable_inventory' => 1, + ); + { + 'name' => 'Dish service', + 'display_weight' => 58, + 'cancel_weight' => 85, + 'fields' => { + 'svcnum' => { label => 'Service' }, + 'acctnum' => { label => 'DISH account#', %opts }, + 'note' => { label => 'Installation notes', %opts }, + } + } +} + +sub label { + my $self = shift; + $self->acctnum; +} + +sub search_sql { + my($class, $string) = @_; + $class->search_sql_field('acctnum', $string); +} + +=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. + +# the replace method can be inherited from FS::Record + +=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 $x = $self->setfixed; + return $x unless ref $x; + + my $error = + $self->ut_numbern('svcnum') + || $self->ut_text('acctnum') + || $self->ut_textn('note') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 SEE ALSO + +L<FS::Record>, L<FS::svc_Common>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/svc_hardware.pm b/FS/FS/svc_hardware.pm new file mode 100644 index 000000000..5b81a9c2b --- /dev/null +++ b/FS/FS/svc_hardware.pm @@ -0,0 +1,211 @@ +package FS::svc_hardware; + +use strict; +use base qw( FS::svc_Common ); +use FS::Record qw( qsearch qsearchs ); +use FS::hardware_type; +use FS::hardware_status; + +=head1 NAME + +FS::svc_hardware - Object methods for svc_hardware records + +=head1 SYNOPSIS + + use FS::svc_hardware; + + $record = new FS::svc_hardware \%hash; + $record = new FS::svc_hardware { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::svc_hardware object represents an equipment installation, such as +a wireless broadband receiver, satellite antenna, or DVR. FS::svc_hardware +inherits from FS::svc_Common. + +The following fields are currently supported: + +=over 4 + +=item svcnum - Primary key + +=item typenum - Device type number (see L<FS::hardware_type>) + +=item ip_addr - IP address + +=item hw_addr - Hardware address + +=item serial - Serial number + +=item statusnum - Service status (see L<FS::hardware_status>) + +=item note - Installation notes: location on property, physical access, etc. + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new svc_hardware object. + +=cut + +sub table { 'svc_hardware'; } + +sub table_info { + my %opts = ( 'type' => 'text', 'disable_select' => 1 ); + { + 'name' => 'Hardware', #? + 'name_plural' => 'Hardware', + 'display_weight' => 59, + 'cancel_weight' => 86, + 'fields' => { + 'svcnum' => { label => 'Service' }, + 'typenum' => { label => 'Device type', + type => 'select-hardware', + disable_select => 1, + disable_fixed => 1, + disable_default => 1, + disable_inventory => 1, + }, + 'serial' => { label => 'Serial number', %opts }, + 'hw_addr' => { label => 'Hardware address', %opts }, + 'ip_addr' => { label => 'IP address', %opts }, + 'statusnum' => { label => 'Service status', + type => 'select', + select_table => 'hardware_status', + select_key => 'statusnum', + select_label => 'label', + disable_inventory => 1, + }, + 'note' => { label => 'Installation notes', %opts }, + } + } +} + +sub search_sql { + my ($class, $string) = @_; + my @where = (); + + my $ip = NetAddr::IP->new($string); + if ( $ip ) { + push @where, $class->search_sql_field('ip_addr', $ip->addr); + } + + if ( $string =~ /^(\w+)$/ ) { + push @where, 'LOWER(svc_hardware.serial) LIKE \'%'.lc($string).'%\''; + } + + if ( $string =~ /^([0-9A-Fa-f]|\W)+$/ ) { + my $hex = uc($string); + $hex =~ s/\W//g; + push @where, 'svc_hardware.hw_addr LIKE \'%'.$hex.'%\''; + } + '(' . join(' OR ', @where) . ')'; +} + +sub label { + my $self = shift; + $self->serial || $self->hw_addr; +} + +=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. + +# the replace method can be inherited from FS::Record + +=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 $x = $self->setfixed; + return $x unless ref $x; + + my $hw_addr = $self->getfield('hw_addr'); + $hw_addr = join('', split(/\W/, $hw_addr)); + $self->setfield('hw_addr', $hw_addr); + + my $error = + $self->ut_numbern('svcnum') + || $self->ut_foreign_key('typenum', 'hardware_type', 'typenum') + || $self->ut_ip46n('ip_addr') + || $self->ut_hexn('hw_addr') + || $self->ut_alphan('serial') + || $self->ut_foreign_keyn('statusnum', 'hardware_status', 'statusnum') + || $self->ut_textn('note') + ; + return $error if $error; + + if ( !length($self->getfield('hw_addr')) + and !length($self->getfield('serial')) ) { + return 'Serial number or hardware address required'; + } + + $self->SUPER::check; +} + +=item hardware_type + +Returns the L<FS::hardware_type> object associated with this installation. + +=cut + +sub hardware_type { + my $self = shift; + return qsearchs('hardware_type', { 'typenum' => $self->typenum }); +} + +=item status_label + +Returns the 'label' field of the L<FS::hardware_status> object associated +with this installation. + +=cut + +sub status_label { + my $self = shift; + my $status = qsearchs('hardware_status', { 'statusnum' => $self->statusnum }) + or return ''; + $status->label; +} + + +=back + +=head1 SEE ALSO + +L<FS::Record>, L<FS::svc_Common>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/MANIFEST b/FS/MANIFEST index fce790346..a293451a1 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -578,3 +578,13 @@ FS/areacode.pm t/areacode.t FS/areacode.pm t/areacode.t +FS/svc_dish.pm +t/svc_dish.t +FS/svc_hardware.pm +t/svc_hardware.t +FS/hardware_class.pm +t/hardware_class.t +FS/hardware_type.pm +t/hardware_type.t +FS/hardware_status.pm +t/hardware_status.t diff --git a/FS/t/hardware_class.t b/FS/t/hardware_class.t new file mode 100644 index 000000000..8c98234ab --- /dev/null +++ b/FS/t/hardware_class.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::hardware_class; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/hardware_status.t b/FS/t/hardware_status.t new file mode 100644 index 000000000..71b3077d5 --- /dev/null +++ b/FS/t/hardware_status.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::hardware_status; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/hardware_type.t b/FS/t/hardware_type.t new file mode 100644 index 000000000..072ed7ccd --- /dev/null +++ b/FS/t/hardware_type.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::hardware_type; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/svc_dish.t b/FS/t/svc_dish.t new file mode 100644 index 000000000..684837bc3 --- /dev/null +++ b/FS/t/svc_dish.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::svc_dish; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/svc_hardware.t b/FS/t/svc_hardware.t new file mode 100644 index 000000000..83ca81622 --- /dev/null +++ b/FS/t/svc_hardware.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::svc_hardware; +$loaded=1; +print "ok 1\n"; |