From: Ivan Kohler Date: Fri, 24 Jan 2014 08:39:40 +0000 (-0800) Subject: svc_pbx devices, for RT#24968 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=f3ac48703be75c0e2aec161487057eafeb8fc74f svc_pbx devices, for RT#24968 --- diff --git a/FS/FS.pm b/FS/FS.pm index 11d8b6e0f..c19d2a923 100644 --- a/FS/FS.pm +++ b/FS/FS.pm @@ -206,6 +206,8 @@ L - PBX service class L - PBX extension class +L - PBX device class + L - Certificate service class L - Dish network service class diff --git a/FS/FS/MAC_Mixin.pm b/FS/FS/MAC_Mixin.pm new file mode 100644 index 000000000..8715995c1 --- /dev/null +++ b/FS/FS/MAC_Mixin.pm @@ -0,0 +1,65 @@ +package FS::MAC_Mixin; + +use strict; +#use FS::Record qw(qsearch); +#use FS::Conf; +# careful about importing anything here--it will end up in a LOT of +# namespaces + +#use vars qw(@subclasses $DEBUG $conf); + +#$DEBUG = 0; + +# any subclass that can have MAC addresses needs to be added here +#@subclasses = (qw(FS::svc_broadband FS::svc_cable)); + +#sub conf { +# $conf ||= FS::Conf->new; +#} + +=head1 NAME + +FS::MAC_Mixin - Mixin class for objects that have MAC addresses assigned. + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +=head1 METHODS + +=head1 METHODS + +=over 4 + +=item mac_addr_pretty + +=cut + +sub mac_addr_pretty { + my $self = shift; + $self->mac_addr_formatted('U',':'); +} + +=item mac_addr_formatted CASE DELIMITER + +Format the MAC address (for use by exports). If CASE starts with "l" +(for "lowercase"), it's returned in lowercase. DELIMITER is inserted +between octets. + +=cut + +sub mac_addr_formatted { + my $self = shift; + my ($case, $delim) = @_; + my $addr = $self->mac_addr; + $addr = lc($addr) if $case =~ /^l/i; + join( $delim || '', $addr =~ /../g ); +} + +=back + +=head1 BUGS + +=cut + +1; diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 7d783769e..a4eac45aa 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -369,6 +369,8 @@ if ( -e $addl_handler_use_file ) { use FS::part_pkg_usageprice; use FS::cust_pkg_usageprice; use FS::pbx_extension; + use FS::pbx_device; + use FS::extension_device; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 2300c07fc..0447892d2 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -5676,6 +5676,45 @@ sub tables_hashref { ], }, + 'pbx_device' => { + 'columns' => [ + 'devicenum', 'serial', '', '', '', '', + 'devicepart', 'int', '', '', '', '', + 'svcnum', 'int', '', '', '', '', + 'mac_addr', 'varchar', 'NULL', 12, '', '', + ], + 'primary_key' => 'devicenum', + 'unique' => [ [ 'mac_addr' ], ], + 'index' => [ [ 'devicepart' ], [ 'svcnum' ], ], + 'foreign_keys' => [ + { columns => [ 'devicepart' ], + table => 'part_device', + }, + { columns => [ 'svcnum' ], + table => 'svc_pbx', + }, + ], + }, + + 'extension_device' => { + 'columns' => [ + 'extensiondevicenum', 'serial', '', '', '', '', + 'extensionnum', 'int', '', '', '', '', + 'devicenum', 'int', '', '', '', '', + ], + 'primary_key' => 'extensiondevicenum', + 'unique' => [ [ 'extensionnum', 'devicenum' ] ], + 'index' => [],#both? which way do we need to query? + 'foreign_keys' => [ + { columns => [ 'extensionnum' ], + table => 'pbx_extension', + }, + { columns => [ 'devicenum' ], + table => 'pbx_device', + }, + ], + }, + 'svc_mailinglist' => { #svc_group? 'columns' => [ 'svcnum', 'int', '', '', '', '', diff --git a/FS/FS/dsl_device.pm b/FS/FS/dsl_device.pm index 39e8c3468..1e86d44f5 100644 --- a/FS/FS/dsl_device.pm +++ b/FS/FS/dsl_device.pm @@ -1,5 +1,5 @@ package FS::dsl_device; -use base qw( FS::Record ); +use base qw( FS::MAC_Mixin FS::Record ); use strict; diff --git a/FS/FS/extension_device.pm b/FS/FS/extension_device.pm new file mode 100644 index 000000000..23d881e64 --- /dev/null +++ b/FS/FS/extension_device.pm @@ -0,0 +1,110 @@ +package FS::extension_device; +use base qw( FS::Record ); + +use strict; +#use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::extension_device - Object methods for extension_device records + +=head1 SYNOPSIS + + use FS::extension_device; + + $record = new FS::extension_device \%hash; + $record = new FS::extension_device { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::extension_device object represents a PBX extension association with a +specific PBX device (SIP phone or ATA). FS::extension_device inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item extensiondevicenum + +primary key + +=item extensionnum + +extensionnum + +=item devicenum + +devicenum + + +=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 method. + +=cut + +sub table { 'extension_device'; } + +=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 record. 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('extensiondevicenum') + || $self->ut_foreign_keyn('extensionnum', 'pbx_extension', 'extensionnum') + || $self->ut_foreign_keyn('devicenum', 'pbx_device', 'devicenum') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L + +=cut + +1; + diff --git a/FS/FS/pbx_device.pm b/FS/FS/pbx_device.pm new file mode 100644 index 000000000..ec1c3b90e --- /dev/null +++ b/FS/FS/pbx_device.pm @@ -0,0 +1,114 @@ +package FS::pbx_device; +use base qw( FS::MAC_Mixin FS::Record ); + +use strict; +#use FS::Record qw( qsearch qsearchs ); + +=head1 NAME + +FS::pbx_device - Object methods for pbx_device records + +=head1 SYNOPSIS + + use FS::pbx_device; + + $record = new FS::pbx_device \%hash; + $record = new FS::pbx_device { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::pbx_device object represents a specific customer phone device, such +as a SIP phone or ATA. FS::pbx_device inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item devicenum + +primary key + +=item devicepart + +devicepart + +=item svcnum + +svcnum + +=item mac_addr + +mac_addr + + +=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 method. + +=cut + +sub table { 'pbx_device'; } + +=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 record. 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('devicenum') + || $self->ut_foreign_key('devicepart', 'part_device', 'devicepart') + || $self->ut_foreign_key('svcnum', 'svc_pbx', 'svcnum') + || $self->ut_mac_addr('mac_addr') + ; + return $error if $error; + + $self->SUPER::check; +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L + +=cut + +1; + diff --git a/FS/FS/phone_device.pm b/FS/FS/phone_device.pm index d5f80a2c5..b891bb294 100644 --- a/FS/FS/phone_device.pm +++ b/FS/FS/phone_device.pm @@ -1,5 +1,5 @@ package FS::phone_device; -use base qw( FS::Record ); +use base qw( FS::MAC_Mixin FS::Record ); use strict; use Scalar::Util qw( blessed ); diff --git a/FS/FS/svc_External_Common.pm b/FS/FS/svc_External_Common.pm index a5805aafd..32fe7f3db 100644 --- a/FS/FS/svc_External_Common.pm +++ b/FS/FS/svc_External_Common.pm @@ -8,28 +8,12 @@ use FS::svc_Common; =head1 NAME -FS::svc_external - Object methods for svc_external records +FS::svc_External_Common - Base class for svc_X classes which track external databases =head1 SYNOPSIS - use FS::svc_external; - - $record = new FS::svc_external \%hash; - $record = new FS::svc_external { 'column' => 'value' }; - - $error = $record->insert; - - $error = $new_record->replace($old_record); - - $error = $record->delete; - - $error = $record->check; - - $error = $record->suspend; - - $error = $record->unsuspend; - - $error = $record->cancel; + package FS::svc_newservice; + use base qw( FS::svc_External_Common ); =head1 DESCRIPTION diff --git a/FS/FS/svc_MAC_Mixin.pm b/FS/FS/svc_MAC_Mixin.pm deleted file mode 100644 index 737a8e83f..000000000 --- a/FS/FS/svc_MAC_Mixin.pm +++ /dev/null @@ -1,65 +0,0 @@ -package FS::svc_MAC_Mixin; - -use strict; -#use FS::Record qw(qsearch); -#use FS::Conf; -# careful about importing anything here--it will end up in a LOT of -# namespaces - -#use vars qw(@subclasses $DEBUG $conf); - -#$DEBUG = 0; - -# any subclass that can have MAC addresses needs to be added here -#@subclasses = (qw(FS::svc_broadband FS::svc_cable)); - -#sub conf { -# $conf ||= FS::Conf->new; -#} - -=head1 NAME - -FS::MAC_Mixin - Mixin class for objects that have MAC addresses assigned. - -=head1 SYNOPSIS - -=head1 DESCRIPTION - -=head1 METHODS - -=head1 METHODS - -=over 4 - -=item mac_addr_pretty - -=cut - -sub mac_addr_pretty { - my $self = shift; - $self->mac_addr_formatted('U',':'); -} - -=item mac_addr_formatted CASE DELIMITER - -Format the MAC address (for use by exports). If CASE starts with "l" -(for "lowercase"), it's returned in lowercase. DELIMITER is inserted -between octets. - -=cut - -sub mac_addr_formatted { - my $self = shift; - my ($case, $delim) = @_; - my $addr = $self->mac_addr; - $addr = lc($addr) if $case =~ /^l/i; - join( $delim || '', $addr =~ /../g ); -} - -=back - -=head1 BUGS - -=cut - -1; diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm index b9c89cef7..ce50a0c3b 100755 --- a/FS/FS/svc_broadband.pm +++ b/FS/FS/svc_broadband.pm @@ -3,7 +3,7 @@ use base qw( FS::svc_Radius_Mixin FS::svc_Tower_Mixin FS::svc_IP_Mixin - FS::svc_MAC_Mixin + FS::MAC_Mixin FS::svc_Common ); diff --git a/FS/FS/svc_cable.pm b/FS/FS/svc_cable.pm index 3a1dc5ae9..12a1dbba5 100644 --- a/FS/FS/svc_cable.pm +++ b/FS/FS/svc_cable.pm @@ -1,5 +1,5 @@ package FS::svc_cable; -use base qw( FS::svc_MAC_Mixin +use base qw( FS::MAC_Mixin FS::svc_Common ); #FS::device_Common diff --git a/FS/FS/svc_pbx.pm b/FS/FS/svc_pbx.pm index 7899621b2..d35b3a22c 100644 --- a/FS/FS/svc_pbx.pm +++ b/FS/FS/svc_pbx.pm @@ -1,5 +1,5 @@ package FS::svc_pbx; -use base qw( FS::o2m_Common FS::svc_External_Common ); +use base qw( FS::o2m_Common FS::device_Common FS::svc_External_Common ); use strict; use Tie::IxHash; diff --git a/FS/FS/svc_video.pm b/FS/FS/svc_video.pm index a6ff13628..999b87c66 100644 --- a/FS/FS/svc_video.pm +++ b/FS/FS/svc_video.pm @@ -1,5 +1,5 @@ package FS::svc_video; -use base qw( FS::svc_MAC_Mixin FS::svc_Common ); +use base qw( FS::MAC_Mixin FS::svc_Common ); use strict; use Tie::IxHash; diff --git a/FS/MANIFEST b/FS/MANIFEST index f2f1e3984..bedc26cf2 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -751,3 +751,7 @@ FS/cust_pkg_usageprice.pm t/cust_pkg_usageprice.t FS/pbx_extension.pm t/pbx_extension.t +FS/pbx_device.pm +t/pbx_device.t +FS/extension_device.pm +t/extension_device.t diff --git a/FS/t/extension_device.t b/FS/t/extension_device.t new file mode 100644 index 000000000..5927a17bf --- /dev/null +++ b/FS/t/extension_device.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::extension_device; +$loaded=1; +print "ok 1\n"; diff --git a/FS/t/pbx_device.t b/FS/t/pbx_device.t new file mode 100644 index 000000000..9cd549942 --- /dev/null +++ b/FS/t/pbx_device.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::pbx_device; +$loaded=1; +print "ok 1\n"; diff --git a/httemplate/edit/elements/device_Common.html b/httemplate/edit/elements/device_Common.html new file mode 100644 index 000000000..ab8135784 --- /dev/null +++ b/httemplate/edit/elements/device_Common.html @@ -0,0 +1,110 @@ +<& edit.html, + 'labels' => { + 'devicenum' => 'Device', + 'devicepart' => 'Device type', + 'mac_addr' => 'MAC address', + }, + 'fields' => [ { 'field' => 'devicepart', + 'type' => 'select-table', + 'table' => 'part_device', + 'name_col' => 'devicename', + 'onchange' => 'devicepart_changed', + 'empty_label' =>'Select device type', + #'hashref' =>{ disabled => '' }, + }, + { field => 'mac_addr', + type => 'select-mac', + }, + { 'field' => 'svcnum', + 'type' => 'hidden', + }, + ], + 'menubar' => [], #disable viewall + #'viewall_dir' => 'browse', + 'new_callback' => sub { + my( $cgi, $object ) = @_; + $object->svcnum( $cgi->param('svcnum') ); + }, + 'html_foot' => $html_foot, + %opt, +&> +<%init> + +my %opt = @_; + +my @deviceparts_with_inventory = + map $_->devicepart, + qsearch({ 'table' => 'part_device', + 'extra_sql' => 'WHERE inventory_classnum IS NOT NULL', + }); + +my $html_foot = sub { + my $js = " +"; + + $js; +}; + +# :/ needs agent-virt so you can't futz with arbitrary devices + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + + + diff --git a/httemplate/edit/pbx_device.html b/httemplate/edit/pbx_device.html new file mode 100644 index 000000000..457ec7121 --- /dev/null +++ b/httemplate/edit/pbx_device.html @@ -0,0 +1,4 @@ +<& elements/device_Common.html, + 'name' => 'PBX device', + 'table' => 'pbx_device', +&> diff --git a/httemplate/edit/process/elements/device_Common.html b/httemplate/edit/process/elements/device_Common.html new file mode 100644 index 000000000..7b6f2cd78 --- /dev/null +++ b/httemplate/edit/process/elements/device_Common.html @@ -0,0 +1,27 @@ +<& process.html, + 'redirect' => sub { + my( $cgi, $X_device ) = @_; + popurl(3)."view/$svc_table.cgi?". + 'svcnum='. $X_device->svcnum. + ';devicenum='; + }, + %opt, +&> +<%init> + +my %opt = @_; + +warn my $table = $opt{table}; +( my $svc_table = $table ) =~ s/_device//; +$svc_table = "svc_$svc_table"; + +if($cgi->param('sel_mac_addr') && !$cgi->param('mac_addr')) { + $cgi->param('mac_addr',$cgi->param('sel_mac_addr')); +} + +# :/ needs agent-virt so you can't futz with arbitrary devices + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + + diff --git a/httemplate/edit/process/pbx_device.html b/httemplate/edit/process/pbx_device.html new file mode 100644 index 000000000..664a9e715 --- /dev/null +++ b/httemplate/edit/process/pbx_device.html @@ -0,0 +1,3 @@ +<& elements/device_Common.html, + 'table' => 'pbx_device', +&> diff --git a/httemplate/misc/delete-pbx_device.html b/httemplate/misc/delete-pbx_device.html new file mode 100755 index 000000000..7540d2f9f --- /dev/null +++ b/httemplate/misc/delete-pbx_device.html @@ -0,0 +1,23 @@ +% if ( $error ) { +% errorpage($error); +% } else { +<% $cgi->redirect($p. "view/svc_pbx.cgi?". $svcnum) %> +% } +<%init> + +# :/ needs agent-virt so you can't futz with arbitrary devices + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +#untaint devicenum +my($query) = $cgi->keywords; +$query =~ /^(\d+)$/ || die "Illegal devicenum"; +my $devicenum = $1; + +my $pbx_device = qsearchs('pbx_device', { 'devicenum' => $devicenum } ); +my $svcnum = $pbx_device->svcnum; + +my $error = $pbx_device->delete; + + diff --git a/httemplate/view/elements/svc_devices.html b/httemplate/view/elements/svc_devices.html index 9458c922c..c9f5eda78 100644 --- a/httemplate/view/elements/svc_devices.html +++ b/httemplate/view/elements/svc_devices.html @@ -15,7 +15,7 @@ %if ( @devices || $num_part_device || $table eq 'dsl_device' ) { % my $svcnum = $svc_x->svcnum; - Devices + Devices (Add device)
@@ -30,7 +30,7 @@ <& /elements/table-grid.html &> -% if ( $table eq 'phone_device' || $table eq 'cable_device' ) { +% if ( $table ne 'dsl_device' ) { # ( $table eq 'phone_device' || $table eq 'cable_device' || $table eq 'pbx_device' ) { Type % } MAC Addr @@ -62,7 +62,7 @@ % if ( $table eq 'phone_device' || $svc_x->isa('FS::device_Common') ) { <% $td %><% $device->part_device->devicename |h %> % } - <% $td %><% $device->mac_addr %> + <% $td %><% $device->mac_addr_pretty %> <% $td %><% $export_links %> <% $td %>( % unless ( $opt{'no_edit'} ) { @@ -85,7 +85,7 @@ my $table = $opt{'table'}; #part_device, dsl_device my $svc_x = $opt{'svc_x'}; my $num_part_device = 0; -if ( $table eq 'phone_device' || $table eq 'cable_device' ) { +if ( $table ne 'dsl_device' ) { # ( $table eq 'phone_device' || $table eq 'cable_device' || $table eq 'pbx_device' ) { my $sth = dbh->prepare("SELECT COUNT(*) FROM part_device") #WHERE disabled = '' OR disabled IS NULL;"); or die dbh->errstr;