From e3c3d86b7091d806af42e40475a28ea8afb5865c Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 28 Mar 2009 22:59:36 +0000 Subject: [PATCH] package selector, split by package class, RT#5077 --- FS/FS/Conf.pm | 7 ++ FS/FS/part_pkg.pm | 26 ++++- httemplate/elements/select-cust-part_pkg.html | 12 +-- httemplate/elements/select-cust-pkg_class.html | 12 +++ httemplate/elements/select-part_pkg.html | 14 ++- httemplate/elements/select-table.html | 2 +- httemplate/elements/tr-select-cust-part_pkg.html | 107 +++++++++++++++++++++ .../elements/tr-selectmultiple-part_pkg.html | 9 +- httemplate/misc/change_pkg.cgi | 22 ++--- httemplate/misc/cust-part_pkg.cgi | 29 ++++++ httemplate/misc/order_pkg.html | 18 ++-- 11 files changed, 218 insertions(+), 40 deletions(-) create mode 100644 httemplate/elements/select-cust-pkg_class.html create mode 100644 httemplate/elements/tr-select-cust-part_pkg.html create mode 100644 httemplate/misc/cust-part_pkg.cgi diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index f765fc721..b6fea5413 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -2712,6 +2712,13 @@ worry that config_items is freeside-specific and icky. 'type' => 'checkbox', }, + { + 'key' => 'disable-cust-pkg_class', + 'section' => 'UI', + 'description' => 'Disable the two-step dropdown for selecting package class and package, and return to the classic single dropdown.', + 'type' => 'checkbox', + }, + ); 1; diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 81696fcfa..8cf7d0ca1 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -1236,9 +1236,31 @@ L). =cut sub curuser_pkgs_sql { - #my($class) = shift; + my $class = shift; + + $class->_pkgs_sql( $FS::CurrentUser::CurrentUser->agentnums ); + +} + +=item agent_pkgs_sql AGENT | AGENTNUM, ... + +Returns an SQL fragment for searching for packages the provided agent or agents +can use, either via part_pkg.agentnum directly, or via agent type (see +L). + +=cut + +sub agent_pkgs_sql { + my $class = shift; #i'm a class method, not a sub (the question is... why??) + my @agentnums = map { ref($_) ? $_->agentnum : $_ } @_; + + $class->_pkgs_sql(@agentnums); #is this why + +} - my $agentnums = join(',', $FS::CurrentUser::CurrentUser->agentnums); +sub _pkgs_sql { + my( $class, @agentnums ) = @_; + my $agentnums = join(',', @agentnums); " ( diff --git a/httemplate/elements/select-cust-part_pkg.html b/httemplate/elements/select-cust-part_pkg.html index 292662921..7f91e8141 100644 --- a/httemplate/elements/select-cust-part_pkg.html +++ b/httemplate/elements/select-cust-part_pkg.html @@ -31,11 +31,11 @@ my( %opt ) = @_; my $cust_main = $opt{'cust_main'} or die "cust_main not specified"; -$opt{'extra_sql'} .= - ' AND ( agentnum IS NOT NULL '. - ' OR 0 < ( SELECT COUNT(*) FROM type_pkgs '. - ' WHERE typenum = '. $cust_main->agent->typenum. - ' AND type_pkgs.pkgpart = part_pkg.pkgpart )'. - ' )'; +$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent ); +# ' AND ( agentnum IS NOT NULL '. +# ' OR 0 < ( SELECT COUNT(*) FROM type_pkgs '. +# ' WHERE typenum = '. $cust_main->agent->typenum. +# ' AND type_pkgs.pkgpart = part_pkg.pkgpart )'. +# ' )'; diff --git a/httemplate/elements/select-cust-pkg_class.html b/httemplate/elements/select-cust-pkg_class.html new file mode 100644 index 000000000..5c19efa6d --- /dev/null +++ b/httemplate/elements/select-cust-pkg_class.html @@ -0,0 +1,12 @@ +<% include( '/elements/select-pkg_class.html', + 'pre_options' => [ '-1' => 'all' ], #XXX a config ? + #'pre_options' => [ '-2' => 'Select package class' ], + 'disable_empty' => 1, + %opt, + ) +%> +<%init> + +my %opt = @_; + + diff --git a/httemplate/elements/select-part_pkg.html b/httemplate/elements/select-part_pkg.html index 52b1ccaf1..6b697abdf 100644 --- a/httemplate/elements/select-part_pkg.html +++ b/httemplate/elements/select-part_pkg.html @@ -22,17 +22,27 @@ Example: 'name_col' => 'pkg', 'empty_label' => 'Select package', #should this be the default? 'label_callback' => sub { shift->pkg_comment }, - 'hashref' => { 'disabled' => '' }, + 'hashref' => \%hash, %opt, ) %> <%init> - + my( %opt ) = @_; $opt{'records'} = delete $opt{'part_pkg'} if $opt{'part_pkg'}; +my %hash = ( 'disabled' => '' ); + +if ( exists($opt{'classnum'}) && defined($opt{'classnum'}) ) { + if ( $opt{'classnum'} > 0 ) { + $hash{'classnum'} = $opt{'classnum'}; + } elsif ( $opt{'classnum'} eq '' || $opt{'classnum'} == 0 ) { + $hash{'classnum'} = ''; + } #else -1 or not specified, all classes, so don't set classnum +} + $opt{'extra_sql'} .= ' AND '. FS::part_pkg->curuser_pkgs_sql; diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index 4efbcbaf3..e7baaf53b 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -139,7 +139,7 @@ if ( $opt{'records'} ) { }); } -unless ( ! $value +unless ( $value < 1 # !$value #ignore negatives too or ref($value) or ! exists( $opt{hashref}->{disabled} ) #?? or grep { $value == $_->$key() } @records diff --git a/httemplate/elements/tr-select-cust-part_pkg.html b/httemplate/elements/tr-select-cust-part_pkg.html new file mode 100644 index 000000000..75f1f6f0a --- /dev/null +++ b/httemplate/elements/tr-select-cust-part_pkg.html @@ -0,0 +1,107 @@ +%if ( scalar(@pkg_class) > 1 && ! $conf->exists('disable-cust-pkg_class') ) { + + <% include('/elements/xmlhttp.html', + 'url' => $p.'misc/cust-part_pkg.cgi', + 'subs' => [ 'get_part_pkg' ], + ) + %> + + + + + Package Class + + <% include('/elements/select-cust-pkg_class.html', + 'curr_value' => $opt{'classnum'}, + 'pkg_class' => \@pkg_class, + 'onchange' => 'classnum_changed', + ) + %> + + + +%} + + + Package + + <% include('/elements/select-cust-part_pkg.html', + 'curr_value' => $opt{'curr_value'}, #$pkgpart + 'classnum' => $opt{'classnum'}, + 'cust_main' => $opt{'cust_main'}, #$cust_main + 'onchange' => 'enable_order_pkg', + ) + %> + + + +<%init> + +my $conf = new FS::Conf; + +my %opt = @_; + +my $pre_label = $opt{'pre_label'} || ''; +$pre_label .= ' ' if length($pre_label) && $pre_label =~ /\S$/; + +my $cust_main = $opt{'cust_main'} + or die "cust_main not specified"; + +#my @pkg_class = sort { $a->classname cmp $b->classname } +# qsearch( 'pkg_class', { 'disabled' => '' } ); + +#"normal" part_pkg agent virtualization (agentnum or type) +my @part_pkg = qsearch({ + 'select' => 'DISTINCT classnum', + 'table' => 'part_pkg', + 'hashref' => { 'disabled' => '' }, + 'extra_sql' => + ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ). + ' AND '. FS::part_pkg->agent_pkgs_sql( $opt{'cust_main'}->agent ), +}); + +my @pkg_class = + sort { $a->classname cmp $b->classname } #should get a sort order in config + map { $_->pkg_class || new FS::pkg_class { 'classnum' => '', + 'classname' => '(none)' } + } + @part_pkg; + + diff --git a/httemplate/elements/tr-selectmultiple-part_pkg.html b/httemplate/elements/tr-selectmultiple-part_pkg.html index 455038da9..d959a5bae 100644 --- a/httemplate/elements/tr-selectmultiple-part_pkg.html +++ b/httemplate/elements/tr-selectmultiple-part_pkg.html @@ -2,11 +2,10 @@ <% $opt{'label'} || 'Packages' %> <% include( '/elements/select-table.html', - 'table' => 'part_pkg', - 'name_col' => 'pkg', - 'value' => '', - 'empty_label' => '(none)', - 'element_etc' => 'multiple', + 'table' => 'part_pkg', + 'name_col' => 'pkg', + 'disable_empty' => 1, + 'element_etc' => 'multiple', %opt, ) %> diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi index c4dfca200..16b707121 100755 --- a/httemplate/misc/change_pkg.cgi +++ b/httemplate/misc/change_pkg.cgi @@ -13,19 +13,15 @@ <% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><% $part_pkg->pkg |h %> - <% $part_pkg->comment |h %> - - - New package - - <% include('/elements/select-cust-part_pkg.html', - 'cust_main' => $cust_main, - 'element_name' => 'pkgpart', - #'extra_sql' => ' AND pkgpart != '. $cust_pkg->pkgpart, - 'curr_value' => scalar($cgi->param('pkgpart')), - ) - %> - - + + <% include('/elements/tr-select-cust-part_pkg.html', + 'pre_label' => 'New', + 'curr_value' => scalar($cgi->param('pkgpart')), + 'classnum' => $part_pkg->classnum, + 'cust_main' => $cust_main, + #'extra_sql' => ' AND pkgpart != '. $cust_pkg->pkgpart, + ) + %> <% include('/elements/tr-select-cust_location.html', 'cgi' => $cgi, diff --git a/httemplate/misc/cust-part_pkg.cgi b/httemplate/misc/cust-part_pkg.cgi new file mode 100644 index 000000000..a249f033f --- /dev/null +++ b/httemplate/misc/cust-part_pkg.cgi @@ -0,0 +1,29 @@ +<% objToJson( \@return ) %> +<%init> + +my( $custnum, $classnum ) = $cgi->param('arg'); + +#XXX i guess i should be agent-virtualized. cause "packages a customer can +#order" is such a huge deal +my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); + +my %hash = ( 'disabled' => '' ); +if ( $classnum > 0 ) { + $hash{'classnum'} = $classnum; +} elsif ( $classnum eq '' || $classnum == 0 ) { + $hash{'classnum'} = ''; +} #else -1, all classes, so don't set classnum + +my @part_pkg = qsearch({ + 'table' => 'part_pkg', + 'hashref' => \%hash, + 'extra_sql' => + ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ). + ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent ), +}); + +my @return = map { $_->pkgpart => $_->pkg_comment } + sort { $a->pkg_comment cmp $b->pkg_comment } + @part_pkg; + + diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html index 2c8335154..9caa57a69 100644 --- a/httemplate/misc/order_pkg.html +++ b/httemplate/misc/order_pkg.html @@ -19,17 +19,13 @@ <% ntable("#cccccc", 2) %> - - Package - - <% include('/elements/select-cust-part_pkg.html', - 'curr_value' => $pkgpart, - 'cust_main' => $cust_main, - 'onchange' => 'enable_order_pkg', - ) - %> - - +<% include('/elements/tr-select-cust-part_pkg.html', + 'curr_value' => $pkgpart, + 'classnum' => -1, + 'cust_main' => $cust_main, + 'onchange' => 'enable_order_pkg', + ) +%> % if ( $conf->exists('pkg_referral') ) { <% include('/elements/tr-select-part_referral.html', -- 2.11.0