[freeside-commits] branch master updated. 10d114817c3d17c778444cc96a799d9d2b042224

Mark Wells mark at 420.am
Sat Jun 9 20:26:10 PDT 2012


The branch, master has been updated
       via  10d114817c3d17c778444cc96a799d9d2b042224 (commit)
      from  a1eb54c2661dad29992603e78682d9be2d372625 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 10d114817c3d17c778444cc96a799d9d2b042224
Author: Mark Wells <mark at freeside.biz>
Date:   Sat Jun 9 20:26:01 2012 -0700

    further changes to unearned income report, #13289

diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index e866a3f..4220d3c 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -1058,42 +1058,49 @@ sub _X_show_zero {
 
 =over 4
 
-=item owed_sql [ BEFORE, AFTER, OPTIONS ]
+=item usage_sql
 
-Returns an SQL expression for the amount owed.  BEFORE and AFTER specify
-a date window.  OPTIONS may include 'no_usage' (excludes usage charges)
-and 'setuprecur' (set to "setup" or "recur" to limit to one or the other).
+Returns an SQL expression for the total usage charges in details on
+an item.
 
 =cut
 
-sub owed_sql {
+my $usage_sql =
+  '(SELECT COALESCE(SUM(cust_bill_pkg_detail.amount),0) 
+    FROM cust_bill_pkg_detail 
+    WHERE cust_bill_pkg_detail.billpkgnum = cust_bill_pkg.billpkgnum)';
+
+sub usage_sql { $usage_sql }
+
+# this makes owed_sql, etc. much more concise
+sub charged_sql {
   my ($class, $start, $end, %opt) = @_;
   my $charged = 
     $opt{setuprecur} =~ /^s/ ? 'cust_bill_pkg.setup' :
     $opt{setuprecur} =~ /^r/ ? 'cust_bill_pkg.recur' :
     'cust_bill_pkg.setup + cust_bill_pkg.recur';
 
-  if ( $opt{no_usage} ) {
-    $charged .= ' - ' . $class->usage_sql;
+  if ($opt{no_usage} and $charged =~ /recur/) { 
+    $charged = "$charged - $usage_sql"
   }
 
-  '(' . $charged . 
-  ' - ' . $class->paid_sql($start, $end, %opt) .
-  ' - ' . $class->credited_sql($start, $end, %opt) . ')'
+  $charged;
 }
 
-=item usage_sql
 
-Returns an SQL expression for the total usage charges in details on
-an item.
+=item owed_sql [ BEFORE, AFTER, OPTIONS ]
+
+Returns an SQL expression for the amount owed.  BEFORE and AFTER specify
+a date window.  OPTIONS may include 'no_usage' (excludes usage charges)
+and 'setuprecur' (set to "setup" or "recur" to limit to one or the other).
 
 =cut
 
-sub usage_sql {
+sub owed_sql {
   my $class = shift;
-  "(SELECT COALESCE(SUM(cust_bill_pkg_detail.amount),0) 
-    FROM cust_bill_pkg_detail 
-    WHERE cust_bill_pkg_detail.billpkgnum = cust_bill_pkg.billpkgnum)"
+  '(' . $class->charged_sql(@_) . 
+  ' - ' . $class->paid_sql(@_) .
+  ' - ' . $class->credited_sql(@_) . ')'
 }
 
 =item paid_sql [ BEFORE, AFTER, OPTIONS ]
@@ -1104,32 +1111,55 @@ Returns an SQL expression for the sum of payments applied to this item.
 
 sub paid_sql {
   my ($class, $start, $end, %opt) = @_;
-  $start = $start ? "AND cust_bill_pay._date <= $start" : '';
-  $end   = $end   ? "AND cust_bill_pay._date >  $end"   : '';
+  my $s = $start ? "AND cust_bill_pay._date <= $start" : '';
+  my $e = $end   ? "AND cust_bill_pay._date >  $end"   : '';
   my $setuprecur = 
     $opt{setuprecur} =~ /^s/ ? 'setup' :
     $opt{setuprecur} =~ /^r/ ? 'recur' :
     '';
   $setuprecur &&= "AND setuprecur = '$setuprecur'";
-  "( SELECT COALESCE(SUM(cust_bill_pay_pkg.amount),0)
+
+  my $paid = "( SELECT COALESCE(SUM(cust_bill_pay_pkg.amount),0)
      FROM cust_bill_pay_pkg JOIN cust_bill_pay USING (billpaynum)
      WHERE cust_bill_pay_pkg.billpkgnum = cust_bill_pkg.billpkgnum
-           $start $end $setuprecur )";
+           $s $e$setuprecur )";
+
+  if ( $opt{no_usage} ) {
+    # cap the amount paid at the sum of non-usage charges, 
+    # minus the amount credited against non-usage charges
+    "LEAST($paid, ". 
+      $class->charged_sql($start, $end, %opt) . ' - ' .
+      $class->credited_sql($start, $end, %opt).')';
+  }
+  else {
+    $paid;
+  }
+
 }
 
 sub credited_sql {
   my ($class, $start, $end, %opt) = @_;
-  $start = $start ? "AND cust_credit_bill._date <= $start" : '';
-  $end   = $end   ? "AND cust_credit_bill._date >  $end"   : '';
+  my $s = $start ? "AND cust_credit_bill._date <= $start" : '';
+  my $e = $end   ? "AND cust_credit_bill._date >  $end"   : '';
   my $setuprecur = 
     $opt{setuprecur} =~ /^s/ ? 'setup' :
     $opt{setuprecur} =~ /^r/ ? 'recur' :
     '';
   $setuprecur &&= "AND setuprecur = '$setuprecur'";
-  "( SELECT COALESCE(SUM(cust_credit_bill_pkg.amount),0)
+
+  my $credited = "( SELECT COALESCE(SUM(cust_credit_bill_pkg.amount),0)
      FROM cust_credit_bill_pkg JOIN cust_credit_bill USING (creditbillnum)
      WHERE cust_credit_bill_pkg.billpkgnum = cust_bill_pkg.billpkgnum
-           $start $end $setuprecur )";
+           $s $e $setuprecur )";
+
+  if ( $opt{no_usage} ) {
+    # cap the amount credited at the sum of non-usage charges
+    "LEAST($credited, ". $class->charged_sql($start, $end, %opt).')';
+  }
+  else {
+    $credited;
+  }
+
 }
 
 =back
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index a84f981..f9dd4a2 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -367,28 +367,44 @@ if ( $cgi->param('unearned_now') =~ /^(\d+)$/ ) {
 
   my $usage_sql = FS::cust_bill_pkg->usage_sql;
   push @select, "($usage_sql) AS usage"; # we need this
-  my $owed_sql = FS::cust_bill_pkg->owed_sql($unearned, '', 
-    setuprecur => 'recur', no_usage => 1);
-  push @select, "($owed_sql) AS owed"; # also this
+  my $paid_sql = 'GREATEST(' .
+    FS::cust_bill_pkg->paid_sql($unearned, '', setuprecur => 'recur') .
+    " - $usage_sql, 0)";
+
+  push @select, "$paid_sql AS paid_no_usage"; # need this either way
+
+  if ( $unearned_mode eq 'paid' ) {
+    # then use the amount paid, minus usage charges
+    $unearned_base = $paid_sql;
+  }
+  else {
+    # use the amount billed, minus usage charges and credits
+    $unearned_base = "GREATEST( cust_bill_pkg.recur - ".
+      FS::cust_bill_pkg->credited_sql($unearned, '', setuprecur => 'recur') .
+      " - $usage_sql, 0)";
+      # include only rows that have some non-usage, non-credited portion
+  }
+  # whatever we're using as the base, only show rows where it's positive
+  push @where, "$unearned_base > 0";
 
-  $unearned_base = "(cust_bill_pkg.recur - $usage_sql)";
   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)";
 
-  $unearned_sql = "CAST(
-  GREATEST( ( $unearned_base * $remaining ) - $owed_sql, 0 )
-    AS DECIMAL(10,2)
-  )";
+  $unearned_sql = "CAST( $unearned_base * $remaining AS DECIMAL(10,2) )";
   push @select, "$unearned_sql AS unearned_revenue";
 
-  if ( $unearned_mode eq 'billed' ) {
-    # include only rows that have some unearned portion
-    push @where, "$unearned_base > 0";
-  }
-  elsif ( $unearned_mode eq 'paid' ) {
-    # include only those that have some _paid_ unearned portion
-    push @where, "$unearned_sql > 0";
+  # last payment/credit date
+  my %t = (pay => 'cust_bill_pay', credit => 'cust_credit_bill');
+  foreach my $x (qw(pay credit)) {
+    my $table = $t{$x};
+    my $link = $table.'_pkg';
+    my $pkey = dbdef->table($table)->primary_key;
+    my $last_date_sql = "SELECT MAX(_date) 
+    FROM $table JOIN $link USING ($pkey)
+    WHERE $link.billpkgnum = cust_bill_pkg.billpkgnum 
+    AND $table._date <= $unearned";
+    push @select, "($last_date_sql) AS last_$x";
   }
 
 }
diff --git a/httemplate/search/prepaid_income.html b/httemplate/search/prepaid_income.html
index deed33a..d02345e 100644
--- a/httemplate/search/prepaid_income.html
+++ b/httemplate/search/prepaid_income.html
@@ -98,7 +98,7 @@ $dt->add(days => 1); # the day after that
 $dt->subtract(seconds => 1); # the last second of the report day
 $now = $dt->epoch;
 
-my $link = "cust_bill_pkg.cgi?nottax=1;unearned_now=$now;mode=$mode";
+my $link = "unearned_detail.html?date=$now;mode=$mode";
 
 if ( $cgi->param('include_monthly') ) {
   $link .= ';include_monthly=1';
@@ -138,17 +138,22 @@ foreach my $agentnum (@agentnums) {
 
   my( $total, $total_legacy ) = ( 0, 0 );
 
-  # false laziness
-  my $usage_sql = FS::cust_bill_pkg->usage_sql;
-  my $owed_sql = FS::cust_bill_pkg->owed_sql($now, '', 
-    setuprecur => 'recur', no_usage => 1);
-  my $unearned_base = "(cust_bill_pkg.recur - $usage_sql)";
+  my @opt = ($now, '', setuprecur => 'recur', no_usage => 1);
+  # balance owed, recurring only, not including usage charges
+  my $unearned_base;
+  if ( $mode eq 'billed' ) {
+    $unearned_base = '( ' . 
+                     FS::cust_bill_pkg->charged_sql(@opt) . ' - ' .
+                     FS::cust_bill_pkg->credited_sql(@opt) . ' )';
+  } elsif ( $mode eq 'paid' ) {
+    $unearned_base = FS::cust_bill_pkg->paid_sql(@opt);
+  }
   my $period = "CAST(cust_bill_pkg.edate - cust_bill_pkg.sdate AS REAL)";
   my $elapsed  = "GREATEST( $now - cust_bill_pkg.sdate, 0 )";
   my $remaining = "(1 - $elapsed/$period)";
 
   my $unearned_sql = "CAST(
-  GREATEST( $unearned_base * $remaining - $owed_sql, 0 )
+  GREATEST( $unearned_base * $remaining, 0 )
     AS DECIMAL(10,2)
   )";
 
@@ -180,6 +185,8 @@ foreach my $agentnum (@agentnums) {
                  AND part_pkg.freq != '0'
                  $where
              ";
+
+             warn $sql;
   my $sth = dbh->prepare($sql) or die dbh->errstr;
   $sth->execute or die $sth->errstr;
   my $total = $sth->fetchrow_arrayref->[0];

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/cust_bill_pkg.pm                |   80 ++++++++++++++++++++++----------
 httemplate/search/cust_bill_pkg.cgi   |   46 +++++++++++++------
 httemplate/search/prepaid_income.html |   21 ++++++---
 3 files changed, 100 insertions(+), 47 deletions(-)




More information about the freeside-commits mailing list