<% include( 'elements/browse.html',
'title' => 'Package Definitions',
+ 'menubar' => \@menubar,
'html_init' => $html_init,
'html_form' => $html_form,
'html_posttotal' => $html_posttotal,
'agent_virt' => 1,
'agent_null_right' => [ $edit, $edit_global ],
'agent_null_right_link' => $edit_global,
- 'agent_pos' => 6,
+ 'agent_pos' => 7, #5?
'query' => { 'select' => $select,
'table' => 'part_pkg',
'hashref' => \%hash,
}
$cgi->delete('classnum');
+if ( $cgi->param('pkgpartbatch') =~ /^([\w\/\-\:\. ]+)$/ ) {
+ push @where, "pkgpartbatch = '$1' ";
+}
+
if ( $cgi->param('missing_recur_fee') ) {
- push @where, "0 = ( SELECT COUNT(*) FROM part_pkg_option
- WHERE optionname = 'recur_fee'
- AND part_pkg_option.pkgpart = part_pkg.pkgpart
- AND CAST( optionvalue AS NUMERIC ) > 0
- )";
+ push @where, "NOT EXISTS ( SELECT 1 FROM part_pkg_option
+ WHERE optionname = 'recur_fee'
+ AND part_pkg_option.pkgpart = part_pkg.pkgpart
+ AND CAST( optionvalue AS NUMERIC ) > 0
+ )";
+}
+
+if ( $cgi->param('ratenum') =~ /^(\d+)$/ ) {
+ push @where, "EXISTS( SELECT 1 FROM part_pkg_option
+ WHERE optionname LIKE '%ratenum'
+ AND optionvalue = '$1'
+ AND part_pkg_option.pkgpart = part_pkg.pkgpart
+ )";
}
if ( $cgi->param('family') =~ /^(\d+)$/ ) {
WHERE cust_pkg.pkgpart = part_pkg.pkgpart
AND $agentnums_sql
";
+my $count_cust_pkg_cancel = "
+ SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )
+ LEFT JOIN cust_pkg AS cust_pkg_next
+ ON (cust_pkg.pkgnum = cust_pkg_next.change_pkgnum)
+ WHERE cust_pkg.pkgpart = part_pkg.pkgpart
+ AND $agentnums_sql
+ AND cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0
+";
$select = "
( $count_cust_pkg
AND ( cancel IS NULL OR cancel = 0 )
AND susp IS NOT NULL AND susp != 0
+ AND setup IS NOT NULL AND setup != 0
) AS num_suspended,
( $count_cust_pkg
- AND cancel IS NOT NULL AND cancel != 0
+ AND ( cancel IS NULL OR cancel = 0 )
+ AND susp IS NOT NULL AND susp != 0
+ AND ( setup IS NULL OR setup = 0 )
+ ) AS num_on_hold,
+
+ ( $count_cust_pkg_cancel
+ AND (cust_pkg_next.pkgnum IS NULL
+ OR cust_pkg_next.pkgpart != cust_pkg.pkgpart)
) AS num_cancelled
";
+# About the num_cancelled expression: packages that were changed, but
+# kept the same pkgpart, are considered "moved", not "canceled" (because
+# this is the part_pkg UI). We could show the count of those but it's
+# probably not interesting.
my $html_init = qq!
One or more service definitions are grouped together into a package
],
[
{ data =>$money_char.
- sprintf('%.2f', $part_pkg->option('setup_fee') ),
+ sprintf('%.2f ', $part_pkg->option('setup_fee') ),
align=>'right'
},
- { data => ( ( $is_recur ? ' setup' : ' one-time' ).
+ { data => ( ( $is_recur ? ' setup' : ' one-time' ).
( $part_pkg->option('recur_fee') == 0
&& $part_pkg->setup_show_zero
? ' (printed on invoices)'
[
{ data=>(
$is_recur
- ? $money_char. sprintf('%.2f ', $part_pkg->option('recur_fee'))
+ ? $money_char. sprintf('%.2f', $part_pkg->option('recur_fee'))
: $part_pkg->freq_pretty
),
align=> ( $is_recur ? 'right' : 'center' ),
},
( $is_recur
? { data => ( $is_recur
- ? $part_pkg->freq_pretty.
+ ? ' '. $part_pkg->freq_pretty.
( $part_pkg->option('recur_fee') == 0
&& $part_pkg->recur_show_zero
? ' (printed on invoices)'
# $part_pkg->freq_pretty; #.'<BR>'
};
+push @header, 'Cost tracking';
+$align .= 'r'; #?
+push @fields, sub {
+ my $part_pkg = shift;
+ #(my $plan = $plan_labels{$part_pkg->plan} ) =~ s/ / /g;
+ my $is_recur = ( $part_pkg->freq ne '0' );
+
+ [
+ [
+ { data => ' ', # $plan,
+ align=>'center',
+ colspan=>2,
+ },
+ ],
+ [
+ { data =>$money_char.
+ sprintf('%.2f ', $part_pkg->setup_cost ),
+ align=>'right'
+ },
+ { data => ( $is_recur ? ' setup' : ' one-time' ),
+ align=>'left',
+ },
+ ],
+ [
+ { data=>(
+ $is_recur
+ ? $money_char. sprintf('%.2f', $part_pkg->recur_cost)
+ : '(no recurring)' #$part_pkg->freq_pretty
+ ),
+ align=> ( $is_recur ? 'right' : 'center' ),
+ colspan=> ( $is_recur ? 1 : 2 ),
+ },
+ ( $is_recur
+ ? { data => ( $is_recur
+ ? ' '. $part_pkg->freq_pretty
+ : ''
+ ),
+ align=>'left',
+ }
+ : ()
+ ),
+ ],
+ ];
+};
+
###
# Agent goes here if displayed
###
#agent type
if ( $acl_edit_global ) {
#really we just want a count, but this is fine unless someone has tons
- my @all_agent_types = map {$_->typenum} qsearch('agent_type',{});
+ my @all_agent_types = map {$_->typenum}
+ qsearch('agent_type', { 'disabled'=>'' });
if ( scalar(@all_agent_types) > 1 ) {
push @header, 'Agent types';
my $typelink = $p. 'edit/agent_type.cgi?';
#if ( $cgi->param('active') ) {
push @header, 'Customer<BR>packages';
- my %col = (
- 'not yet billed' => '009999', #teal? cyan?
- 'active' => '00CC00',
- 'suspended' => 'FF9900',
- 'cancelled' => 'FF0000',
- #'one-time charge' => '000000',
- 'charge' => '000000',
- );
+ my %col = %{ FS::cust_pkg->statuscolors };
my $cust_pkg_link = $p. 'search/cust_pkg.cgi?pkgpart=';
push @fields, sub { my $part_pkg = shift;
[
my $label = $_;
if ( $magic eq 'active' && $part_pkg->freq == 0 ) {
$magic = 'inactive';
- #$label = 'one-time charge',
- $label = 'charge',
+ #$label = 'one-time charge';
+ $label = 'charge';
}
$label= 'not yet billed' if $magic eq 'not_yet_billed';
+ $label= 'on hold' if $magic eq 'on_hold';
[
{
),
},
],
- } (qw( not_yet_billed active suspended cancelled ))
+ } (qw( on_hold not_yet_billed active suspended cancelled ))
),
($acl_config ?
[ {},
},
];
}
+ sort
grep { $options{$_} =~ /\S/ }
grep { $_ !~ /^(setup|recur)_fee$/
and $_ !~ /^report_option_\d+$/ }
sub {
my $part_pkg = shift;
+ my @part_pkg_usage = sort { $a->priority <=> $b->priority }
+ $part_pkg->part_pkg_usage;
[
(map {
]
}
$part_pkg->svc_part_pkg_link
- )
+ ),
+ ( scalar(@part_pkg_usage) ?
+ [ { data => 'Usage minutes',
+ align => 'center',
+ colspan => 2,
+ data_style => 'b',
+ link => $p.'browse/part_pkg_usage.html#pkgpart'.
+ $part_pkg->pkgpart
+ } ]
+ : ()
+ ),
+ ( map {
+ [ { data => $_->minutes,
+ align => 'right'
+ },
+ { data => $_->description,
+ align => 'left'
+ },
+ ]
+ } @part_pkg_usage
+ ),
];
};
) . '</FORM>';
}
+my @menubar;
+# show this if there are any voip_cdr packages defined
+if ( FS::part_pkg->count("plan = 'voip_cdr'") ) {
+ push @menubar, 'Per-package usage minutes' => $p.'browse/part_pkg_usage.html';
+}
</%init>