summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2012-05-13 22:16:37 -0700
committerIvan Kohler <ivan@freeside.biz>2012-05-13 22:16:37 -0700
commit8d7cd4b2bd99cc1a711d81b55a1652d31eda4df5 (patch)
treef742c8f30a6724b4cf429a3247a2c9e075b668f2
parent6a66ab1163bfcd6f46df00aa474d013530a1e13c (diff)
service def classes, to support corecom portal, RT#17617
-rw-r--r--FS/FS.pm2
-rw-r--r--FS/FS/Schema.pm12
-rw-r--r--FS/FS/part_svc.pm6
-rw-r--r--FS/FS/part_svc_class.pm126
-rw-r--r--FS/MANIFEST2
-rw-r--r--FS/t/part_svc_class.t5
-rw-r--r--httemplate/browse/part_svc_class.html34
-rw-r--r--httemplate/docs/part_svc-table.html63
-rwxr-xr-xhttemplate/edit/part_svc.cgi131
-rw-r--r--httemplate/edit/part_svc_class.html6
-rw-r--r--httemplate/edit/process/part_svc_class.html11
-rw-r--r--httemplate/elements/menu.html1
-rw-r--r--httemplate/elements/select-part_svc_class.html22
-rw-r--r--httemplate/elements/tr-select-part_svc_class.html27
14 files changed, 369 insertions, 79 deletions
diff --git a/FS/FS.pm b/FS/FS.pm
index 8c78179..e169166 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -214,6 +214,8 @@ L<FS::inventory_item> - Inventory items
L<FS::part_svc> - Service definition class
+L<FS::part_svc_class> - Service class class
+
L<FS::part_svc_column> - Column constraint class
L<FS::export_svc> - Class linking service definitions (see L<FS::part_svc>)
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 843e210..e3f34a4 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -1850,6 +1850,7 @@ sub tables_hashref {
'disabled', 'char', 'NULL', 1, '', '',
'preserve', 'char', 'NULL', 1, '', '',
'selfservice_access', 'varchar', 'NULL', $char_d, '', '',
+ 'classnum', 'int', 'NULL', '', '', '',
],
'primary_key' => 'svcpart',
'unique' => [],
@@ -1870,6 +1871,17 @@ sub tables_hashref {
'index' => [ [ 'svcpart' ] ],
},
+ 'part_svc_class' => {
+ 'columns' => [
+ 'classnum', 'serial', '', '', '', '',
+ 'classname', 'varchar', '', $char_d, '', '',
+ 'disabled', 'char', 'NULL', 1, '', '',
+ ],
+ 'primary_key' => 'classnum',
+ 'unique' => [],
+ 'index' => [ ['disabled'] ],
+ },
+
#(this should be renamed to part_pop)
'svc_acct_pop' => {
'columns' => [
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 7e592bf..20b80c6 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -9,6 +9,7 @@ use FS::part_svc_column;
use FS::part_export;
use FS::export_svc;
use FS::cust_svc;
+use FS::part_svc_class;
@ISA = qw(FS::Record);
@@ -51,6 +52,8 @@ FS::Record. The following fields are currently supported:
=item svcdb - table used for this service. See L<FS::svc_acct>,
L<FS::svc_domain>, and L<FS::svc_forward>, among others.
+=item classnum - Optional service class (see L<FS::svc_class>)
+
=item disabled - Disabled flag, empty or `Y'
=item preserve - Preserve after cancellation, empty or 'Y'
@@ -387,6 +390,7 @@ sub check {
|| $self->ut_enum('disabled', [ '', 'Y' ] )
|| $self->ut_enum('preserve', [ '', 'Y' ] )
|| $self->ut_enum('selfservice_access', [ '', 'hidden', 'readonly' ] )
+ || $self->ut_foreign_keyn('classnum', 'part_svc_class', 'classnum' )
;
return $error if $error;
@@ -712,7 +716,7 @@ sub process {
my $job = shift;
my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
+ warn Dumper($param);# if $DEBUG;
my $old = qsearchs('part_svc', { 'svcpart' => $param->{'svcpart'} })
if $param->{'svcpart'};
diff --git a/FS/FS/part_svc_class.pm b/FS/FS/part_svc_class.pm
new file mode 100644
index 0000000..d1c9915
--- /dev/null
+++ b/FS/FS/part_svc_class.pm
@@ -0,0 +1,126 @@
+package FS::part_svc_class;
+use base qw( FS::class_Common );
+
+use strict;
+use FS::Record; # qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::part_svc_class - Object methods for part_svc_class records
+
+=head1 SYNOPSIS
+
+ use FS::part_svc_class;
+
+ $record = new FS::part_svc_class \%hash;
+ $record = new FS::part_svc_class { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::part_svc_class object represents a service class. FS::part_svc_class
+inherits from FS::Record. The following fields are currently supported:
+
+=over 4
+
+=item classnum
+
+primary key
+
+=item classname
+
+classname
+
+=item disabled
+
+disabled
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new service class. To add the service class 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 { 'part_svc_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 service 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')
+ || $self->ut_enum('disabled', [ '', 'Y' ] )
+ ;
+ return $error if $error;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 91711d3..8bb4eee 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -638,3 +638,5 @@ FS/sales.pm
t/sales.t
FS/access_groupsales.pm
t/access_groupsales.t
+FS/part_svc_class.pm
+t/part_svc_class.t
diff --git a/FS/t/part_svc_class.t b/FS/t/part_svc_class.t
new file mode 100644
index 0000000..e838c0b
--- /dev/null
+++ b/FS/t/part_svc_class.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_svc_class;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/browse/part_svc_class.html b/httemplate/browse/part_svc_class.html
new file mode 100644
index 0000000..73bd603
--- /dev/null
+++ b/httemplate/browse/part_svc_class.html
@@ -0,0 +1,34 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Service classes',
+ 'html_init' => $html_init,
+ 'name' => 'service classes',
+ 'disableable' => 1,
+ 'disabled_statuspos' => 1,
+ 'query' => { 'table' => 'part_svc_class',
+ 'hashref' => {},
+ 'order_by' => 'ORDER BY classnum',
+ },
+ 'count_query' => $count_query,
+ 'header' => $header,
+ 'fields' => $fields,
+ 'links' => $links,
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my $html_init =
+ 'Service classes are user-defined, informational types for services.<BR><BR>'.
+ qq!<A HREF="${p}edit/part_svc_class.html"><I>Add a service class</I></A><BR><BR>!;
+
+my $count_query = 'SELECT COUNT(*) FROM part_svc_class';
+
+my $link = [ $p.'edit/part_svc_class.html?', 'classnum' ];
+
+my $header = [ '#', 'Class' ];
+my $fields = [ 'classnum', 'classname' ];
+my $links = [ $link, $link ];
+
+</%init>
diff --git a/httemplate/docs/part_svc-table.html b/httemplate/docs/part_svc-table.html
new file mode 100644
index 0000000..48841f5
--- /dev/null
+++ b/httemplate/docs/part_svc-table.html
@@ -0,0 +1,63 @@
+<& /elements/header-popup.html &>
+
+<TABLE>
+ <TR>
+ <TH ALIGN="left">Generic</TH>
+ <TH ALIGN="left">Access</TH>
+ <TH ALIGN="left">Telephony</TH>
+<!-- <TH>Hosting</TH>
+ <TH>Colocation</TH>
+-->
+ </TR>
+ <TR>
+ <TD VALIGN="top">
+ <UL STYLE="margin:0">
+ <LI><B>svc_acct</B>: Accounts - anything with a username (mailbox, shell, RADIUS, etc.)
+ <LI><B>svc_hardware</B>: Equipment supplied to customers
+ <LI><B>svc_external</B>: Externally-tracked service
+ </UL>
+ </TD>
+ <TD VALIGN="top">
+ <UL STYLE="margin:0">
+ <LI><B>svc_dsl</B>: DSL
+ <LI><B>svc_broadband</B>: Wireless broadband
+ <LI><B>svc_dish</B>: DISH Network
+ </UL>
+ </TD>
+ <TD VALIGN="top">
+ <UL STYLE="margin:0">
+ <LI><B>svc_phone</B>: Customer phone number
+ <LI><B>svc_pbx</B>: Customer PBX
+ </UL>
+ </TD>
+ </TR>
+</TABLE>
+<BR>
+<TABLE>
+ <TR>
+ <TH ALIGN="left">Hosting</TH>
+ <TH ALIGN="left">Colocation</TH>
+ </TR>
+ <TD VALIGN="top">
+ <UL STYLE="margin:0">
+ <LI><B>svc_domain</B>: Domain
+ <LI><B>svc_cert</B>: Certificate
+ <LI><B>svc_forward</B>: Mail forwarding
+ <LI><B>svc_mailinglist</B>: Mailing list
+ <LI><B>svc_www</B>: Virtual domain website
+ </UL>
+ </TD>
+ <TD VALIGN="top">
+ <UL STYLE="margin:0">
+ <LI><B>svc_port</B>: Customer router/switch port
+ </UL>
+ </TD>
+ </TR>
+<TABLE>
+<!-- <LI>svc_charge - One-time charges (Partially unimplemented)
+ <LI>svc_wo - Work orders (Partially unimplemented)
+-->
+
+</BODY>
+</HTML>
+
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index fae8961..4bd0837 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -1,17 +1,27 @@
-<% include('/elements/header.html', "$action Service Definition",
+<& /elements/header.html, "$action Service Definition",
menubar('View all service definitions' => "${p}browse/part_svc.cgi"),
#" onLoad=\"visualize()\""
- )
-%>
+&>
+
+<& /elements/init_overlib.html &>
+
+<BR>
<FORM NAME="dummy">
- Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>
-<BR><BR>
-Service <INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"><BR>
+<FONT CLASS="fsinnerbox-title">Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %></FONT>
+<TABLE CLASS="fsinnerbox">
+<TR>
+ <TD ALIGN="right">Service</TD>
+ <TD><INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"></TD>
+<TR>
+
+<& /elements/tr-select-part_svc_class.html, curr_value=>$hashref->{classnum} &>
-Self-service access:
-<SELECT NAME="selfservice_access">
+<TR>
+ <TD ALIGN="right">Self-service access</TD>
+ <TD>
+ <SELECT NAME="selfservice_access">
% tie my %selfservice_access, 'Tie::IxHash', #false laziness w/browse/part_svc
% '' => 'Yes',
% 'hidden' => 'Hidden',
@@ -22,12 +32,22 @@ Self-service access:
<% $_ eq $hashref->{'selfservice_access'} ? 'SELECTED' : '' %>
><% $selfservice_access{$_} %>
% }
-</SELECT><BR>
+ </SELECT>
+ </TD>
+</TR>
-<INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>>&nbsp;Disable new orders<BR>
-<INPUT TYPE="checkbox" NAME="preserve" VALUE="Y"<% $hashref->{'preserve'} eq 'Y' ? ' CHECKED' : '' %>>&nbsp;Preserve this service on package cancellation<BR>
+<TR>
+ <TD ALIGN="right">Disable new orders</TD>
+ <TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Preserve this service on package cancellation</TD>
+ <TD><INPUT TYPE="checkbox" NAME="preserve" VALUE="Y"<% $hashref->{'preserve'} eq 'Y' ? ' CHECKED' : '' %>>&nbsp;</TD>
+</TR>
+
+</TABLE>
<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $hashref->{svcpart} %>">
@@ -76,6 +96,18 @@ Self-service access:
% ? ( $hashref->{svcdb} )
% : FS::part_svc->svc_tables();
%
+% my $help = '';
+% unless ( $hashref->{svcpart} ) {
+% $help = '&nbsp;'.
+% include('/elements/popup_link.html',
+% 'action' => $p.'docs/part_svc-table.html',
+% 'label' => 'help',
+% 'actionlabel' => 'Service table help',
+% 'width' => 763,
+% #'height' => 400,
+% );
+% }
+%
% tie my %svcdb, 'Tie::IxHash', map { $_=>$_ } grep dbdef->table($_), @dbs;
% my $widget = new HTML::Widgets::SelectLayers(
% #'selected_layer' => $p_svcdb,
@@ -84,15 +116,16 @@ Self-service access:
% 'form_name' => 'dummy',
% #'form_action' => 'process/part_svc.cgi',
% 'form_action' => 'part_svc.cgi', #self
-% 'form_text' => [ qw( svc svcpart ) ],
-% 'form_select' => [ 'selfservice_access' ],
-% 'form_checkbox' => [ 'disabled', 'preserve' ],
+% 'form_elements' => [qw( svc svcpart classnum selfservice_access
+% disabled preserve
+% )],
+% 'html_between' => $help,
% 'layer_callback' => sub {
% my $layer = shift;
%
% my $html = qq!<INPUT TYPE="hidden" NAME="svcdb" VALUE="$layer">!;
%
-% $html .= $svcdb_info;
+% #$html .= $svcdb_info;
%
% my $columns = 3;
% my $count = 0;
@@ -267,6 +300,7 @@ Self-service access:
%
% $html .= include('/elements/select-table.html',
% 'element_name' => "${layer}__${field}_classnum",
+% 'id' => "${layer}__${field}_classnum",
% 'element_etc' => ( $is_inv
% ? $disabled
% : $nodisplay
@@ -349,6 +383,7 @@ Self-service access:
% $html .= include('/elements/select-hardware_class.html',
% 'curr_value' => $value,
% 'element_name' => "${layer}__${field}_classnum",
+% 'id' => "${layer}__${field}_classnum",
% 'element_etc' => $flag ne 'H' && $nodisplay,
% 'empty_label' => 'Select hardware class',
% );
@@ -382,7 +417,8 @@ Self-service access:
%
% $html .= include('/elements/progress-init.html',
% $layer, #form name
-% [ qw(svc svcpart selfservice_access disabled preserve
+% [ qw(svc svcpart classnum selfservice_access
+% disabled preserve
% exportnum),
% @fields ],
% 'process/part_svc.cgi',
@@ -401,9 +437,8 @@ Self-service access:
%
% },
% );
-%
-%
+<BR>
Table <% $widget->html %>
<% include('/elements/footer.html') %>
@@ -451,66 +486,6 @@ my %communigate_fields = (
#'svc_cert' => { map { $_=>1 } qw( ) },
);
-my $svcdb_info = '
-<TABLE>
- <TR>
- <TH ALIGN="left">Generic</TH>
- <TH ALIGN="left">Access</TH>
- <TH ALIGN="left">Telephony</TH>
-<!-- <TH>Hosting</TH>
- <TH>Colocation</TH>
--->
- </TR>
- <TR>
- <TD VALIGN="top">
- <UL STYLE="margin:0">
- <LI><B>svc_acct</B>: Accounts - anything with a username (mailbox, shell, RADIUS, etc.)
- <LI><B>svc_hardware</B>: Equipment supplied to customers
- <LI><B>svc_external</B>: Externally-tracked service
- </UL>
- </TD>
- <TD VALIGN="top">
- <UL STYLE="margin:0">
- <LI><B>svc_dsl</B>: DSL
- <LI><B>svc_broadband</B>: Wireless broadband
- <LI><B>svc_dish</B>: DISH Network
- </UL>
- </TD>
- <TD VALIGN="top">
- <UL STYLE="margin:0">
- <LI><B>svc_phone</B>: Customer phone number
- <LI><B>svc_pbx</B>: Customer PBX
- </UL>
- </TD>
- </TR>
-</TABLE>
-<BR>
-<TABLE>
- <TR>
- <TH ALIGN="left">Hosting</TH>
- <TH ALIGN="left">Colocation</TH>
- </TR>
- <TD VALIGN="top">
- <UL STYLE="margin:0">
- <LI><B>svc_domain</B>: Domain
- <LI><B>svc_cert</B>: Certificate
- <LI><B>svc_forward</B>: Mail forwarding
- <LI><B>svc_mailinglist</B>: Mailing list
- <LI><B>svc_www</B>: Virtual domain website
- </UL>
- </TD>
- <TD VALIGN="top">
- <UL STYLE="margin:0">
- <LI><B>svc_port</B>: Customer router/switch port
- </UL>
- </TD>
- </TR>
-<TABLE>
-<!-- <LI>svc_charge - One-time charges (Partially unimplemented)
- <LI>svc_wo - Work orders (Partially unimplemented)
--->
-';
-
my $mod_info = '
For the selected table, you can give fields default or fixed (unchangable)
values, or select an inventory class to manually or automatically fill in
diff --git a/httemplate/edit/part_svc_class.html b/httemplate/edit/part_svc_class.html
new file mode 100644
index 0000000..0d9a007
--- /dev/null
+++ b/httemplate/edit/part_svc_class.html
@@ -0,0 +1,6 @@
+<% include( 'elements/class_Common.html',
+ 'name' => 'Service class',
+ 'table' => 'part_svc_class',
+ 'nocat' => 1,
+ )
+%>
diff --git a/httemplate/edit/process/part_svc_class.html b/httemplate/edit/process/part_svc_class.html
new file mode 100644
index 0000000..16165dd
--- /dev/null
+++ b/httemplate/edit/process/part_svc_class.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'part_svc_class',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index 42feb7b..fcc17ea 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -457,6 +457,7 @@ tie my %config_radius, 'Tie::IxHash',
tie my %config_export_svc, 'Tie::IxHash', ();
if ( $curuser->access_right('Configuration') ) {
$config_export_svc{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ];
+ $config_export_svc{'Service classes'} = [ $fsurl.'browse/part_svc_class.html', 'Services classes are user-defined, informational types for services' ];
$config_export_svc{'Provisioning exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ];
}
$config_export_svc{'Dialup'} = [ \%config_dialup, '' ]
diff --git a/httemplate/elements/select-part_svc_class.html b/httemplate/elements/select-part_svc_class.html
new file mode 100644
index 0000000..280e3e1
--- /dev/null
+++ b/httemplate/elements/select-part_svc_class.html
@@ -0,0 +1,22 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'part_svc_class',
+ 'name_col' => 'classname',
+ 'value' => $classnum,
+ 'empty_label' => '(none)',
+ 'hashref' => \%hash,
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+my %hash = ();
+$hash{'disabled'} = '' unless $opt{'showdisabled'};
+
+
+$opt{'records'} = delete $opt{'part_svc_class'}
+ if $opt{'part_svc_class'};
+
+</%init>
diff --git a/httemplate/elements/tr-select-part_svc_class.html b/httemplate/elements/tr-select-part_svc_class.html
new file mode 100644
index 0000000..2f4b093
--- /dev/null
+++ b/httemplate/elements/tr-select-part_svc_class.html
@@ -0,0 +1,27 @@
+% if ( scalar(@{ $opt{'part_svc_class'} }) == 0 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'classnum' %>" VALUE="">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Service class' %></TD>
+ <TD>
+ <% include( '/elements/select-part_svc_class.html',
+ 'curr_value' => $classnum,
+ %opt
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'part_svc_class'} ||= [ qsearch( 'part_svc_class', { disabled=>'' } ) ];
+
+</%init>