From: jeff Date: Thu, 19 Jun 2008 03:18:19 +0000 (+0000) Subject: package categories (meta package classes) and grouping invoices by them X-Git-Tag: root_of_webpay_support~550 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=f13afe5e228a220311557e1ca6dacbf847c26baf package categories (meta package classes) and grouping invoices by them --- diff --git a/FS/FS.pm b/FS/FS.pm index 26f8c18d3..b3a6dcd79 100644 --- a/FS/FS.pm +++ b/FS/FS.pm @@ -161,6 +161,8 @@ L - External provisioning export class L - Export option class +L - Package category class + L - Package class class L - Package definition class diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index ec046cb38..22a731784 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1778,11 +1778,23 @@ sub tables_hashref { 'index' => [], }, + 'pkg_category' => { + 'columns' => [ + 'categorynum', 'serial', '', '', '', '', + 'categoryname', 'varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'categorynum', + 'unique' => [], + 'index' => [ ['disabled'] ], + }, + 'pkg_class' => { 'columns' => [ - 'classnum', 'serial', '', '', '', '', - 'classname', 'varchar', '', $char_d, '', '', - 'disabled', 'char', 'NULL', 1, '', '', + 'classnum', 'serial', '', '', '', '', + 'classname', 'varchar', '', $char_d, '', '', + 'categorynum', 'int', 'NULL', '', '', '', + 'disabled', 'char', 'NULL', 1, '', '', ], 'primary_key' => 'classnum', 'unique' => [], diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 06eec57ae..46189586b 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -2506,7 +2506,7 @@ sub _items_sections { if ( $cust_bill_pkg->pkgnum > 0 ) { - my $desc = $cust_bill_pkg->part_pkg->classname; + my $desc = $cust_bill_pkg->part_pkg->categoryname; $s{$desc} += $cust_bill_pkg->setup if ( $cust_bill_pkg->setup != 0 ); @@ -2576,7 +2576,7 @@ sub _items_pkg { my @cust_bill_pkg = grep { $_->pkgnum && ( defined($section) - ? $_->part_pkg->classname eq $section->{'description'} + ? $_->part_pkg->categoryname eq $section->{'description'} : 1 ) } $self->cust_bill_pkg; diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 0d77ed92e..7bb434dbe 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -475,6 +475,21 @@ sub pkg_class { } } +=item categoryname + +Returns the package category name, or the empty string if there is no package +category. + +=cut + +sub categoryname { + my $self = shift; + my $pkg_class = $self->pkg_class; + $pkg_class + ? $pkg_class->categoryname + : ''; +} + =item classname Returns the package class name, or the empty string if there is no package diff --git a/FS/FS/pkg_category.pm b/FS/FS/pkg_category.pm new file mode 100644 index 000000000..69578c9cf --- /dev/null +++ b/FS/FS/pkg_category.pm @@ -0,0 +1,113 @@ +package FS::pkg_category; + +use strict; +use vars qw( @ISA ); +use FS::Record qw( qsearch ); +use FS::part_pkg; + +@ISA = qw( FS::Record ); + +=head1 NAME + +FS::pkg_category - Object methods for pkg_category records + +=head1 SYNOPSIS + + use FS::pkg_category; + + $record = new FS::pkg_category \%hash; + $record = new FS::pkg_category { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::pkg_category object represents an package category. Every package class +(see L) has, optionally, a package category. FS::pkg_category +inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item categorynum - primary key (assigned automatically for new package categoryes) + +=item categoryname - Text name of this package category + +=item disabled - Disabled flag, empty or 'Y' + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new package category. To add the package category to the database, see +L<"insert">. + +=cut + +sub table { 'pkg_category'; } + +=item insert + +Adds this package category to the database. If there is an error, returns the +error, otherwise returns false. + +=item delete + +Deletes this package category from the database. Only package categoryes with no +associated package definitions can be deleted. If there is an error, returns +the error, otherwise returns false. + +=cut + +sub delete { + my $self = shift; + + return "Can't delete an pkg_category with pkg_class records!" + if qsearch( 'pkg_class', { 'categorynum' => $self->categorynum } ); + + $self->SUPER::delete; +} + +=item replace OLD_RECORD + +Replaces 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 package category. If there is an +error, returns the error, otherwise returns false. Called by the insert and +replace methods. + +=cut + +sub check { + my $self = shift; + + $self->ut_numbern('categorynum') + or $self->ut_text('categoryname') + or $self->SUPER::check; + +} + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L, L, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/pkg_class.pm b/FS/FS/pkg_class.pm index bab6e5e56..254282fbf 100644 --- a/FS/FS/pkg_class.pm +++ b/FS/FS/pkg_class.pm @@ -2,8 +2,9 @@ package FS::pkg_class; use strict; use vars qw( @ISA ); -use FS::Record qw( qsearch ); +use FS::Record qw( qsearchs qsearch ); use FS::part_pkg; +use FS::pkg_category; @ISA = qw( FS::Record ); @@ -38,6 +39,8 @@ from FS::Record. The following fields are currently supported: =item classname - Text name of this package class +=item categorynum - Number of associated pkg_category (see L) + =item disabled - Disabled flag, empty or 'Y' =back @@ -95,10 +98,35 @@ sub check { $self->ut_numbern('classnum') or $self->ut_text('classname') + or $self->ut_foreign_keyn('categorynum', 'pkg_category', 'categorynum') or $self->SUPER::check; } +=item pkg_category + +Returns the pkg_category record associated with this class, or false if there +is none. + +=cut + +sub pkg_category { + my $self = shift; + qsearchs('pkg_category', { 'categorynum' => $self->categorynum } ); +} + +=item categoryname + +Returns the category name associated with this class, or false if there +is none. + +=cut + +sub categoryname { + my $pkg_category = shift->pkg_category; + $pkg_category->categoryname if $pkg_category; +} + =back =head1 BUGS diff --git a/FS/MANIFEST b/FS/MANIFEST index 23df38570..74342e9ab 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -409,3 +409,5 @@ FS/part_pkg_taxoverride.pm t/part_pkg_taxoverride.t FS/part_pkg_taxrate.pm t/part_pkg_taxrate.t +FS/pkg_category.pm +t/pkg_category.t diff --git a/FS/t/pkg_category.t b/FS/t/pkg_category.t new file mode 100644 index 000000000..ee256d56f --- /dev/null +++ b/FS/t/pkg_category.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::pkg_category; +$loaded=1; +print "ok 1\n"; diff --git a/htetc/handler.pl b/htetc/handler.pl index be6f2f758..4361a78a2 100644 --- a/htetc/handler.pl +++ b/htetc/handler.pl @@ -205,6 +205,7 @@ sub handler use FS::cdr; use FS::inventory_class; use FS::inventory_item; + use FS::pkg_category; use FS::pkg_class; use FS::access_user; use FS::access_user_pref; diff --git a/httemplate/browse/pkg_category.html b/httemplate/browse/pkg_category.html new file mode 100644 index 000000000..20bf1a8df --- /dev/null +++ b/httemplate/browse/pkg_category.html @@ -0,0 +1,33 @@ +<% include( 'elements/browse.html', + 'title' => 'Package categories', + 'html_init' => $html_init, + 'name' => 'package categories', + 'disableable' => 1, + 'disabled_statuspos' => 2, + 'query' => { 'table' => 'pkg_category', + 'hashref' => {}, + 'extra_sql' => 'ORDER BY categorynum', + }, + 'count_query' => $count_query, + 'header' => [ '#', 'Category' ], + 'fields' => [ 'categorynum', 'categoryname' ], + 'links' => [ $link, $link ], + ) +%> + +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $html_init = + qq!Package classes

!. + 'Package categories define groups of package classes, for reporting and '. + 'convenience purposes.

'. + qq!Add a package category

!; + +my $count_query = 'SELECT COUNT(*) FROM pkg_category'; + +my $link = [ $p.'edit/pkg_category.html?', 'categorynum' ]; + + diff --git a/httemplate/browse/pkg_class.html b/httemplate/browse/pkg_class.html index 4f02ca22d..75969dbe8 100644 --- a/httemplate/browse/pkg_class.html +++ b/httemplate/browse/pkg_class.html @@ -9,9 +9,9 @@ 'extra_sql' => 'ORDER BY classnum', }, 'count_query' => $count_query, - 'header' => [ '#', 'Class', ], - 'fields' => [ 'classnum', 'classname' ], - 'links' => [ $link, $link ], + 'header' => $header, + 'fields' => $fields, + 'links' => $links, ) %> <%init> @@ -28,4 +28,19 @@ my $count_query = 'SELECT COUNT(*) FROM pkg_class'; my $link = [ $p.'edit/pkg_class.html?', 'classnum' ]; +my $header = [ '#', 'Class' ]; +my $fields = [ 'classnum', 'classname' ]; +my $links = [ $link, $link ]; + +my $cat_query = 'SELECT COUNT(*) FROM pkg_class where categorynum IS NOT NULL'; +my $sth = dbh->prepare($cat_query) + or die "Error preparing $cat_query: ". dbh->errstr; +$sth->execute + or die "Error executing $cat_query: ". $sth->errstr; +if ($sth->fetchrow_arrayref->[0]) { + push @$header, 'Category'; + push @$fields, 'categoryname'; + push @$links, $link; +} + diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 04ca81c72..86eb2b3c7 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -106,7 +106,7 @@ Example: 'new_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; }, #run before display to return a different value - 'value_callback' => sub { my( $columname, $value } ) = @_; }, + 'value_callback' => sub { my( $columname, $value ) = @_; }, #XXX describe 'field_callback' => sub { }, @@ -212,6 +212,7 @@ Example: % #select(-*) % 'options' => $f->{'options'}, % 'labels' => $f->{'labels'}, +% 'empty_label' => $f->{'empty_label'}, % 'multiple' => $f->{'multiple'}, % 'disable_empty' => $f->{'disable_empty'}, % #select-reason diff --git a/httemplate/edit/pkg_category.html b/httemplate/edit/pkg_category.html new file mode 100644 index 000000000..fdc8da638 --- /dev/null +++ b/httemplate/edit/pkg_category.html @@ -0,0 +1,22 @@ +<% include( 'elements/edit.html', + 'name' => 'Package Category', + 'table' => 'pkg_category', + 'fields' => [ + 'categoryname', + { field=>'disabled', type=>'checkbox', value=>'Y', }, + ], + 'labels' => { + 'categorynum' => 'Category number', + 'categoryname' => 'Category name', + 'disabled' => 'Disable category', + }, + 'viewall_dir' => 'browse', + ) + +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + + diff --git a/httemplate/edit/pkg_class.html b/httemplate/edit/pkg_class.html index eddbfc16e..2e4e9d1cd 100644 --- a/httemplate/edit/pkg_class.html +++ b/httemplate/edit/pkg_class.html @@ -3,6 +3,10 @@ 'table' => 'pkg_class', 'fields' => [ 'classname', + (scalar(@category) + ? { field=>'categorynum', type=>'select-table', 'empty_label'=>'(none)', 'table'=>'pkg_category', 'name_col'=>'categoryname' } + : { field=>'categorynum', type=>'hidden' } + ), { field=>'disabled', type=>'checkbox', value=>'Y', }, ], 'labels' => { @@ -19,4 +23,5 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); +my @category = qsearch('pkg_category', { 'disabled' => '' }); diff --git a/httemplate/edit/process/pkg_category.html b/httemplate/edit/process/pkg_category.html new file mode 100644 index 000000000..50cd5cb29 --- /dev/null +++ b/httemplate/edit/process/pkg_category.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'pkg_category', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + + diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index fcca775d8..9ace19ea3 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -262,6 +262,7 @@ $config_export_svc_pkg{'View/Edit package definitions'} = [ $fsurl.'browse/part_ if $curuser->access_right('Edit package definitions') || $curuser->access_right('Edit global package definitions'); if ( $curuser->access_right('Configuration') ) { + $config_export_svc_pkg{'View/Edit package categories'} = [ $fsurl.'browse/pkg_category.html', 'Package categories define groups of package classes, for reporting and convenience purposes.' ]; $config_export_svc_pkg{'View/Edit package classes'} = [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ]; $config_export_svc_pkg{'View/Edit cancel reason types'} = [ $fsurl.'browse/reason_type.html?class=C', 'Cancel reason types define groups of reasons, for reporting and convenience purposes.' ]; $config_export_svc_pkg{'View/Edit cancel reasons'} = [ $fsurl.'browse/reason.html?class=C', 'Cancel reasons explain why a service was cancelled.' ];