<& elements/search.html,
- 'title' => emt("Unearned revenue - ".ucfirst($unearned_mode)),
+ 'title' => emt("Unearned revenue - ".ucfirst($unearned_mode)) . ' (' .
+ time2str('%b %d %Y', $unearned) . ')',
'name' => emt('line items'),
'query' => $query,
'count_query' => $count_query,
date_sub('last_credit'),
#Charge start
date_sub('sdate'),
- #Charge end
- date_sub('edate'),
+ #Charge end, minus most of a day
+ date_sub('before_edate'),
#Invoice
'invnum',
#Invoice date
push @where, "cust_bill._date >= $beginning",
"cust_bill._date <= $ending";
-if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
- push @where, "cust_main.agentnum = $1";
+# cust_classnum (false laziness w/ elements/cust_main_dayranges.html, elements/cust_pay_or_refund.html, prepaid_income.html, cust_bill_pay.html, cust_bill_pkg.html, cust_bill_pkg_referral.html, cust_credit.html, cust_credit_refund.html, cust_main::Search::search_sql)
+if ( grep { $_ eq 'cust_classnum' } $cgi->param ) {
+ my @classnums = grep /^\d*$/, $cgi->param('cust_classnum');
+ push @where, 'COALESCE( cust_main.classnum, 0) IN ( '.
+ join(',', map { $_ || '0' } @classnums ).
+ ' )'
+ if @classnums;
}
# no pkgclass, no taxclass, no tax location...
# whatever we're using as the base, only show rows where it's positive
push @where, "$unearned_base > 0";
-my $period = "CAST(cust_bill_pkg.edate - cust_bill_pkg.sdate AS REAL)";
-my $elapsed = "GREATEST( $unearned - cust_bill_pkg.sdate, 0 )";
-my $remaining = "(1 - $elapsed/$period)";
+my $edate_zero = midnight_sql('edate');
+my $sdate_zero = midnight_sql('sdate');
+# $unearned is one second before midnight on the date requested for the report.
-$unearned_sql = "CAST( $unearned_base * $remaining AS DECIMAL(10,2) )";
+# suppress partial days for more accounting-like behavior
+my $period = "CAST( ($edate_zero - $sdate_zero) / 86400.0 AS DECIMAL(10,0) )";
+
+my $remaining = "GREATEST(
+ CAST( ($edate_zero - $unearned) / 86400.0 AS DECIMAL(10,0) ),
+ 0)";
+my $fraction = "$remaining / $period";
+
+$unearned_sql = "CAST( $unearned_base * $fraction AS DECIMAL(10,2) )";
push @select, "$unearned_sql AS unearned_revenue";
# last payment/credit date
push @select, "($last_date_sql) AS last_$x";
}
+push @select, '(edate - 82799) AS before_edate';
+
#no itemdesc
#no tax report group kludge
#no tax exemption
#usage always excluded
# always 'nottax', not 'istax'
-$join_cust = ' JOIN cust_bill USING ( invnum )
- LEFT JOIN cust_main USING ( custnum ) ';
+$join_cust = ' JOIN cust_bill USING ( invnum ) '.
+ FS::UI::Web::join_cust_main('cust_pkg', 'cust_pkg');
$join_pkg .= ' LEFT JOIN cust_pkg USING ( pkgnum )
LEFT JOIN part_pkg USING ( pkgpart )
my $count_query = "SELECT COUNT(DISTINCT billpkgnum),
SUM( $unearned_base ), SUM( $unearned_sql )
- FROM cust_bill_pkg $join_cust $join_pkg $where";
+ FROM cust_bill_pkg $join_pkg $join_cust $where";
push @select, 'part_pkg.pkg',
'part_pkg.freq',
my $query = {
'table' => 'cust_bill_pkg',
- 'addl_from' => "$join_cust $join_pkg",
+ 'addl_from' => "$join_pkg $join_cust",
'hashref' => {},
'select' => join(",\n", @select ),
'extra_sql' => $where,
my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ];
my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ];
-my $money_char;
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
sub money_sub {
$conf ||= new FS::Conf;