[freeside-commits] branch master updated. db72d963d3acd790df17fee77830b3742c75c3e7

Mark Wells mark at 420.am
Tue Jan 6 13:08:02 PST 2015


The branch, master has been updated
       via  db72d963d3acd790df17fee77830b3742c75c3e7 (commit)
      from  18a1b36c6f9d66385ecfd96154b923bd544843c2 (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 db72d963d3acd790df17fee77830b3742c75c3e7
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Jan 6 13:03:18 2015 -0800

    tax report fix for monthly exemptions + credits, #27698

diff --git a/FS/FS/Report/Tax.pm b/FS/FS/Report/Tax.pm
index 76012fb..f3f441d 100644
--- a/FS/FS/Report/Tax.pm
+++ b/FS/FS/Report/Tax.pm
@@ -88,16 +88,19 @@ sub report_internal {
     "FROM cust_bill_pkg_tax_location JOIN cust_bill_pkg USING (billpkgnum) ".
     "GROUP BY taxable_billpkgnum, taxnum";
 
-  # This one links a tax-exempted line item (billpkgnum) to a tax rate (taxnum),
-  # and gives the amount of the tax exemption.  EXEMPT_WHERE should be replaced 
-  # with a real WHERE clause to further limit the tax exemptions that will be
-  # included.
+  # This one links a tax-exempted line item (billpkgnum) to a tax rate
+  # (taxnum), and gives the amount of the tax exemption.  EXEMPT_WHERE must 
+  # be replaced with an expression to further limit the tax exemptions
+  # that will be included, or "TRUE" to not limit them.
+  #
+  # Note that tax exemptions with non-null creditbillpkgnum are always
+  # excluded. Those are "negative exemptions" created by crediting a sale 
+  # that had received an exemption.
   my $pkg_tax_exempt = "SELECT SUM(amount) AS exempt_charged, billpkgnum, taxnum ".
-    "FROM cust_tax_exempt_pkg EXEMPT_WHERE GROUP BY billpkgnum, taxnum";
-
-  # This just calculates the sum of credit applications to a line item.
-  my $pkg_credited = "SELECT SUM(amount) AS credited, billpkgnum ".
-    "FROM cust_credit_bill_pkg GROUP BY billpkgnum";
+    "FROM cust_tax_exempt_pkg WHERE
+      ( EXEMPT_WHERE )
+      AND cust_tax_exempt_pkg.creditbillpkgnum IS NULL
+     GROUP BY billpkgnum, taxnum";
 
   my $where = "WHERE cust_bill._date >= $beginning AND cust_bill._date <= $ending ".
               "AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' ".
@@ -165,102 +168,78 @@ sub report_internal {
 
   # sales to tax-exempt customers
   $sql{exempt_cust} = $exempt;
-  $sql{exempt_cust} =~ s/EXEMPT_WHERE/WHERE exempt_cust = 'Y' OR exempt_cust_taxname = 'Y'/;
+  $sql{exempt_cust} =~ s/EXEMPT_WHERE/exempt_cust = 'Y' OR exempt_cust_taxname = 'Y'/;
   $all_sql{exempt_cust} = $all_exempt;
-  $all_sql{exempt_cust} =~ s/EXEMPT_WHERE/WHERE exempt_cust = 'Y' OR exempt_cust_taxname = 'Y'/;
+  $all_sql{exempt_cust} =~ s/EXEMPT_WHERE/exempt_cust = 'Y' OR exempt_cust_taxname = 'Y'/;
 
   # sales of tax-exempt packages
   $sql{exempt_pkg} = $exempt;
-  $sql{exempt_pkg} =~ s/EXEMPT_WHERE/WHERE exempt_setup = 'Y' OR exempt_recur = 'Y'/;
+  $sql{exempt_pkg} =~ s/EXEMPT_WHERE/exempt_setup = 'Y' OR exempt_recur = 'Y'/;
   $all_sql{exempt_pkg} = $all_exempt;
-  $all_sql{exempt_pkg} =~ s/EXEMPT_WHERE/WHERE exempt_setup = 'Y' OR exempt_recur = 'Y'/;
+  $all_sql{exempt_pkg} =~ s/EXEMPT_WHERE/exempt_setup = 'Y' OR exempt_recur = 'Y'/;
 
   # monthly per-customer exemptions
   $sql{exempt_monthly} = $exempt;
-  $sql{exempt_monthly} =~ s/EXEMPT_WHERE/WHERE exempt_monthly = 'Y'/;
+  $sql{exempt_monthly} =~ s/EXEMPT_WHERE/exempt_monthly = 'Y'/;
   $all_sql{exempt_monthly} = $all_exempt;
-  $all_sql{exempt_monthly} =~ s/EXEMPT_WHERE/WHERE exempt_monthly = 'Y'/;
+  $all_sql{exempt_monthly} =~ s/EXEMPT_WHERE/exempt_monthly = 'Y'/;
 
   # taxable sales
-  # (sale - exemptions - credits, except not negative)
   $sql{taxable} = "$select
-    SUM(
-      cust_bill_pkg.setup + cust_bill_pkg.recur
-        - COALESCE(exempt_charged, 0)
-        - COALESCE(credited, 0)
-      )
-    FROM cust_bill_pkg
-    LEFT JOIN ($pkg_tax) AS pkg_tax
-      ON (cust_bill_pkg.billpkgnum = pkg_tax.billpkgnum)
+    SUM(cust_bill_pkg.setup + cust_bill_pkg.recur - COALESCE(exempt_charged, 0))
+    FROM cust_main_county
+    JOIN ($pkg_tax) AS pkg_tax USING (taxnum)
+    JOIN cust_bill_pkg USING (billpkgnum)
     LEFT JOIN ($pkg_tax_exempt) AS pkg_tax_exempt
-      ON (cust_bill_pkg.billpkgnum = pkg_tax_exempt.billpkgnum)
-    LEFT JOIN ($pkg_credited) AS pkg_credited
-      ON (cust_bill_pkg.billpkgnum = pkg_credited.billpkgnum)
-    LEFT JOIN cust_main_county
-      ON (COALESCE(pkg_tax.taxnum, pkg_tax_exempt.taxnum) = cust_main_county.taxnum)
+      ON (pkg_tax_exempt.billpkgnum = cust_bill_pkg.billpkgnum 
+          AND pkg_tax_exempt.taxnum = cust_main_county.taxnum)
     $join_cust_pkg $where AND $nottax 
     $group";
 
   $all_sql{taxable} = "$select_all
-    SUM(
-      cust_bill_pkg.setup + cust_bill_pkg.recur
-        - COALESCE(exempt_charged, 0)
-        - COALESCE(credited, 0)
-      )
-    FROM cust_bill_pkg
-    LEFT JOIN ($pkg_tax) AS pkg_tax
-      ON (cust_bill_pkg.billpkgnum = pkg_tax.billpkgnum)
+    SUM(cust_bill_pkg.setup + cust_bill_pkg.recur - COALESCE(exempt_charged, 0))
+    FROM cust_main_county
+    JOIN ($pkg_tax) AS pkg_tax USING (taxnum)
+    JOIN cust_bill_pkg USING (billpkgnum)
     LEFT JOIN ($pkg_tax_exempt) AS pkg_tax_exempt
-      ON (cust_bill_pkg.billpkgnum = pkg_tax_exempt.billpkgnum)
-    LEFT JOIN ($pkg_credited) AS pkg_credited
-      ON (cust_bill_pkg.billpkgnum = pkg_credited.billpkgnum)
-    LEFT JOIN cust_main_county
-      ON (COALESCE(pkg_tax.taxnum, pkg_tax_exempt.taxnum) = cust_main_county.taxnum)
+      ON (pkg_tax_exempt.billpkgnum = cust_bill_pkg.billpkgnum 
+          AND pkg_tax_exempt.taxnum = cust_main_county.taxnum)
     $join_cust_pkg $where AND $nottax 
     $group_all";
 
-  $sql{taxable} =~ s/EXEMPT_WHERE//; # unrestricted
-  $all_sql{taxable} =~ s/EXEMPT_WHERE//;
+  $sql{taxable} =~ s/EXEMPT_WHERE/TRUE/; # unrestricted
+  $all_sql{taxable} =~ s/EXEMPT_WHERE/TRUE/;
 
   # estimated tax (taxable * rate)
   $sql{estimated} = "$select
     SUM(cust_main_county.tax / 100 * 
-      ( cust_bill_pkg.setup + cust_bill_pkg.recur
-        - COALESCE(exempt_charged, 0)
-        - COALESCE(credited, 0)
-      )
+      (cust_bill_pkg.setup + cust_bill_pkg.recur - COALESCE(exempt_charged, 0))
     )
-    FROM cust_bill_pkg
-    LEFT JOIN ($pkg_tax) AS pkg_tax
-      ON (cust_bill_pkg.billpkgnum = pkg_tax.billpkgnum)
+    FROM cust_main_county
+    JOIN ($pkg_tax) AS pkg_tax USING (taxnum)
+    JOIN cust_bill_pkg USING (billpkgnum)
     LEFT JOIN ($pkg_tax_exempt) AS pkg_tax_exempt
-      ON (cust_bill_pkg.billpkgnum = pkg_tax_exempt.billpkgnum)
-    LEFT JOIN ($pkg_credited) AS pkg_credited
-      ON (cust_bill_pkg.billpkgnum = pkg_credited.billpkgnum)
-    LEFT JOIN cust_main_county
-      ON (COALESCE(pkg_tax.taxnum, pkg_tax_exempt.taxnum) = cust_main_county.taxnum)
+      ON (pkg_tax_exempt.billpkgnum = cust_bill_pkg.billpkgnum 
+          AND pkg_tax_exempt.taxnum = cust_main_county.taxnum)
     $join_cust_pkg $where AND $nottax 
     $group";
 
   $all_sql{estimated} = "$select_all
     SUM(cust_main_county.tax / 100 * 
-      ( cust_bill_pkg.setup + cust_bill_pkg.recur
-        - COALESCE(exempt_charged, 0)
-        - COALESCE(credited, 0)
-      )
+      (cust_bill_pkg.setup + cust_bill_pkg.recur - COALESCE(exempt_charged, 0))
     )
-    FROM cust_bill_pkg
-    LEFT JOIN ($pkg_tax) AS pkg_tax
-      ON (cust_bill_pkg.billpkgnum = pkg_tax.billpkgnum)
+    FROM cust_main_county
+    JOIN ($pkg_tax) AS pkg_tax USING (taxnum)
+    JOIN cust_bill_pkg USING (billpkgnum)
     LEFT JOIN ($pkg_tax_exempt) AS pkg_tax_exempt
-      ON (cust_bill_pkg.billpkgnum = pkg_tax_exempt.billpkgnum)
-    LEFT JOIN ($pkg_credited) AS pkg_credited
-      ON (cust_bill_pkg.billpkgnum = pkg_credited.billpkgnum)
-    LEFT JOIN cust_main_county
-      ON (COALESCE(pkg_tax.taxnum, pkg_tax_exempt.taxnum) = cust_main_county.taxnum)
+      ON (pkg_tax_exempt.billpkgnum = cust_bill_pkg.billpkgnum 
+          AND pkg_tax_exempt.taxnum = cust_main_county.taxnum)
     $join_cust_pkg $where AND $nottax 
     $group_all";
 
+  $sql{estimated} =~ s/EXEMPT_WHERE/TRUE/; # unrestricted
+  $all_sql{estimated} =~ s/EXEMPT_WHERE/TRUE/;
+
   # there isn't one for 'sales', because we calculate sales by adding up 
   # the taxable and exempt columns.
   
@@ -392,6 +371,7 @@ sub report_internal {
         JOIN cust_main_county USING (taxnum)
         WHERE cust_tax_exempt_pkg.billpkgnum = cust_bill_pkg.billpkgnum
           AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname'
+          AND cust_tax_exempt_pkg.creditbillpkgnum IS NULL
     )
     AND NOT EXISTS(
       SELECT 1 FROM cust_bill_pkg_tax_location
diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi
index 2d64466..fa6dabc 100644
--- a/httemplate/search/cust_bill_pkg.cgi
+++ b/httemplate/search/cust_bill_pkg.cgi
@@ -422,6 +422,8 @@ if ( $cgi->param('nottax') ) {
   # If we're showing 'out' (items that aren't region/class taxable),
   # then we need the set of all items minus the union of those.
 
+  # Always exclude cust_tax_exempt_pkg records with non-NULL creditbillpkgnum.
+
   if ( $cgi->param('out') ) {
     # separate from the rest, in that we're not going to join cust_main_county
     # in the outer query
@@ -446,19 +448,22 @@ if ( $cgi->param('nottax') ) {
   } else {
     # everything that returns things joined to a tax definition
 
-    my $exempt_sub;
+    if ( @exempt_where or @tax_where or $cgi->param('taxable') ) {
+
+      push @exempt_where, "cust_tax_exempt_pkg.creditbillpkgnum IS NULL";
 
-    # process exemption restrictions, including @tax_where
-    my $exempt_sub = 'SELECT SUM(amount) as exempt_amount, billpkgnum 
-    FROM cust_tax_exempt_pkg JOIN cust_main_county USING (taxnum)';
+      # process exemption restrictions, including @tax_where
+      my $exempt_sub = 'SELECT SUM(amount) as exempt_amount, billpkgnum 
+      FROM cust_tax_exempt_pkg JOIN cust_main_county USING (taxnum)';
 
-    $exempt_sub .= ' WHERE '.join(' AND ', @tax_where, @exempt_where)
-      if (@tax_where or @exempt_where);
+      $exempt_sub .= ' WHERE '.join(' AND ', @tax_where, @exempt_where);
 
-    $exempt_sub .= ' GROUP BY billpkgnum';
+      $exempt_sub .= ' GROUP BY billpkgnum';
 
-    $join_pkg .= " LEFT JOIN ($exempt_sub) AS item_exempt
-    ON (cust_bill_pkg.billpkgnum = item_exempt.billpkgnum)";
+      $join_pkg .= " LEFT JOIN ($exempt_sub) AS item_exempt
+      ON (cust_bill_pkg.billpkgnum = item_exempt.billpkgnum)";
+
+    }
 
     my $credit_sub = 'SELECT SUM(amount) AS credit_amount, billpkgnum
     FROM cust_credit_bill_pkg GROUP BY billpkgnum';
@@ -471,18 +476,30 @@ if ( $cgi->param('nottax') ) {
       unshift @tax_where,
         'cust_main_county.tax > 0';
 
-      my $tax_sub = "SELECT taxable_billpkgnum AS billpkgnum
+      my $tax_sub = "SELECT taxable_billpkgnum
       FROM cust_bill_pkg_tax_location
       JOIN cust_main_county USING (taxnum)
       WHERE ". join(' AND ', @tax_where).
       " GROUP BY taxable_billpkgnum";
 
       $join_pkg .= " LEFT JOIN ($tax_sub) AS item_tax
-      ON (cust_bill_pkg.billpkgnum = item_tax.billpkgnum)"
+      ON (cust_bill_pkg.billpkgnum = item_tax.taxable_billpkgnum)"
     }
 
     # now do something with that
-    if ( @exempt_where ) {
+    if ( $cgi->param('taxable') ) {
+      # taxable query: needs sale amount - exempt amount
+      my $taxable = 'cust_bill_pkg.setup + cust_bill_pkg.recur '.
+                    '- COALESCE(item_exempt.exempt_amount, 0)';
+
+      push @where, "item_tax.taxable_billpkgnum IS NOT NULL";
+      push @select,   "($taxable) AS taxable_amount";
+      push @peritem,  'taxable_amount';
+      push @peritem_desc, 'Taxable';
+      push @total,    "SUM($taxable)";
+      push @total_desc, "$money_char%.2f taxable";
+
+    } elsif ( $cgi->param('exempt_cust') or $cgi->param('exempt_pkg') ) {
 
       push @where,    'item_exempt.billpkgnum IS NOT NULL';
       push @select,   'item_exempt.exempt_amount';
@@ -491,28 +508,11 @@ if ( $cgi->param('nottax') ) {
       push @total,    'SUM(exempt_amount)';
       push @total_desc, "$money_char%.2f tax-exempt";
 
-    } elsif ( @tax_where or $cgi->param('taxable') ) {
-
-      my $taxable = 'cust_bill_pkg.setup + cust_bill_pkg.recur '.
-                    '- COALESCE(item_exempt.exempt_amount, 0) '.
-                    '- COALESCE(item_credit.credit_amount, 0)';
-
-      push @where,    "(item_tax.billpkgnum IS NOT NULL OR item_exempt.billpkgnum IS NOT NULL)";
-      push @select,   "($taxable) AS taxable_amount";
-      push @peritem,  'taxable_amount';
-      push @peritem_desc, 'Taxable';
-
-      if ( $cgi->param('taxable') ) {
-        push @where, "($taxable) > 0";
-      } else {
-        push @total, 'SUM('.
-                        'cust_bill_pkg.setup + cust_bill_pkg.recur '.
-                        '- COALESCE(item_credit.credit_amount, 0) )';
-        push @total_desc, "$money_char%.2f net sales";
-      }
+    } elsif ( @tax_where ) {
+      # union of taxable + all exempt_ cases
+      push @where,
+        '(item_tax.taxable_billpkgnum IS NOT NULL OR item_exempt.billpkgnum IS NOT NULL)';
 
-      push @total,    "SUM($taxable)";
-      push @total_desc, "$money_char%.2f taxable";
     }
 
   } # handle all joins to cust_main_county
@@ -617,6 +617,18 @@ if ( $cgi->param('nottax') ) {
 
   } #end of "normal case"
 
+  # classnum (of underlying package)
+  # not specified: all classes
+  # 0: empty class
+  # N: classnum
+  if ( grep { $_ eq 'classnum' } $cgi->param ) {
+    my @classnums = grep /^\d+$/, $cgi->param('classnum');
+    push @where, "COALESCE(part_fee.classnum, $part_pkg.classnum, 0) IN ( ".
+                     join(',', @classnums ).
+                 ' )'
+      if @classnums;
+  }
+
 } # nottax / istax
 
 
diff --git a/httemplate/search/cust_tax_exempt_pkg.cgi b/httemplate/search/cust_tax_exempt_pkg.cgi
index 382dbc4..ba3f275 100644
--- a/httemplate/search/cust_tax_exempt_pkg.cgi
+++ b/httemplate/search/cust_tax_exempt_pkg.cgi
@@ -144,6 +144,10 @@ if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
   push @where, "COALESCE(part_pkg.classnum,0) = $1";
 }
 
+# no reason ever to show the negative exemptions created by credits.
+# they'll just confuse people.
+push @where, "creditbillpkgnum IS NULL";
+
 my $where = scalar(@where) ? 'WHERE '.join(' AND ', @where) : '';
 
 my $count_query = "SELECT COUNT(*), SUM(amount)".

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

Summary of changes:
 FS/FS/Report/Tax.pm                       |  116 ++++++++++++-----------------
 httemplate/search/cust_bill_pkg.cgi       |   78 +++++++++++--------
 httemplate/search/cust_tax_exempt_pkg.cgi |    4 +
 3 files changed, 97 insertions(+), 101 deletions(-)




More information about the freeside-commits mailing list