sales tax report: detail link and better accuracy for "out of taxable" calculation...
[freeside.git] / httemplate / search / report_tax.cgi
1 <& /elements/header.html, $report->title &>
2 <TD ALIGN="right">
3 Download full results<BR>
4 as <A HREF="<% $p.'search/report_tax-xls.cgi?'.$cgi->query_string%>">Excel spreadsheet</A>
5 </TD>
6
7 <STYLE type="text/css">
8 TD.sectionhead {
9   background-color: #777777;
10   color: #ffffff;
11   font-weight: bold;
12   text-align: left;
13 }
14 .grid TH { background-color: #cccccc; padding: 0px 3px 2px }
15 .row0 TD { background-color: #eeeeee; padding: 0px 3px 2px; text-align: right}
16 .row1 TD { background-color: #ffffff; padding: 0px 3px 2px; text-align: right}
17 TD.rowhead { font-weight: bold; text-align: left; padding: 0px 3px }
18 .bigmath { font-size: large; font-weight: bold; font: sans-serif; text-align: center }
19 .total { font-style: italic }
20 </STYLE>
21 <& /elements/table-grid.html &>
22   <THEAD>
23   <TR>
24     <TH ROWSPAN=3></TH>
25     <TH COLSPAN=5>Sales</TH>
26     <TH ROWSPAN=3></TH>
27     <TH ROWSPAN=3>Rate</TH>
28     <TH ROWSPAN=3></TH>
29     <TH ROWSPAN=3>Estimated tax</TH>
30     <TH ROWSPAN=3>Tax invoiced</TH>
31     <TH ROWSPAN=3></TH>
32     <TH ROWSPAN=3>Tax credited</TH>
33     <TH ROWSPAN=3></TH>
34     <TH ROWSPAN=3>Net tax due</TH>
35   </TR>
36
37   <TR>
38     <TH ROWSPAN=2>Total</TH>
39     <TH ROWSPAN=1>Non-taxable</TH>
40     <TH ROWSPAN=1>Non-taxable</TH>
41     <TH ROWSPAN=1>Non-taxable</TH>
42     <TH ROWSPAN=2>Taxable</TH>
43   </TR>
44
45   <TR STYLE="font-size:small">
46     <TH>(tax-exempt customer)</TH>
47     <TH>(tax-exempt package)</TH>
48     <TH>(monthly exemption)</TH>
49   </TR>
50   </THEAD>
51
52 % my $rownum = 0;
53 % my $prev_row = { pkgclass => 'DUMMY PKGCLASS' };
54
55   <TBODY>
56 % foreach my $row (@rows) {
57 %   # before anything else: if this row's pkgclass is not the same as the 
58 %   # previous row's, then:
59 %   if ( $row->{pkgclass} ne $prev_row->{pkgclass} ) {
60 %     if ( $rownum > 0 ) { # start a new section
61 %       $rownum = 0;
62   </TBODY><TBODY>
63 %     }
64 %     if ( $params{breakdown}->{pkgclass} ) { # and caption the new section
65   <TR>
66     <TD COLSPAN=19 CLASS="sectionhead">
67       <% $pkgclass_name{$row->{pkgclass}} %>
68     </TD>
69   </TR>
70 %     }
71 %   } # if $row->{pkgclass} ne ...
72
73 %   # construct base links that limit to the tax rates described by this row
74 %   my $rowlink = ';taxnum=' . $row->{taxnums};
75 %   # and also the package class, if we're limiting package class
76 %   $rowlink .= ';pkgclass='.$row->{pkgclass}
77 %     if $params{breakdown}->{pkgclass};
78 %
79 %   if ( $row->{total} ) {
80   </TBODY><TBODY CLASS="total">
81 %   }
82   <TR CLASS="row<% $rownum % 2 %>">
83 %   # Row label
84     <TD CLASS="rowhead"><% $row->{label} |h %></TD>
85     <TD>
86 %   # Total sales
87       <A HREF="<% $saleslink . $rowlink %>">
88         <% $money_sprintf->( $row->{sales} ) %>
89       </A>
90     </TD>
91 %   # Exemptions: customer
92     <TD>
93       <A HREF="<% $saleslink . $rowlink . ';exempt_cust=Y' %>">
94         <% $money_sprintf->( $row->{exempt_cust} ) %>
95       </A>
96     </TD>
97 %   # package
98     <TD>
99       <A HREF="<% $saleslink . $rowlink . ';exempt_pkg=Y' %>">
100         <% $money_sprintf->( $row->{exempt_pkg} ) %>
101       </A>
102     </TD>
103 %   # monthly (note this uses $exemptlink; it's a completely separate report)
104     <TD>
105       <A HREF="<% $exemptlink . $rowlink %>">
106         <% $money_sprintf->( $row->{exempt_monthly} ) %>
107       </A>
108     </TD>
109 %   # taxable sales
110     <TD>
111       <A HREF="<% $saleslink . $rowlink . ";taxable=1" %>">
112         <% $money_sprintf->( $row->{taxable} ) %>
113       </A>
114     </TD>
115     <TD CLASS="bigmath"> &times; </TD>
116     <TD><% $row->{rate} %></TD>
117 %   # estimated tax
118     <TD CLASS="bigmath"> = </TD>
119     <TD>
120 %   if ( $row->{estimated} ) {
121       <% $money_sprintf->( $row->{estimated} ) %>
122 %   }
123     </TD>
124 %   # invoiced tax
125     <TD>
126       <A HREF="<% $taxlink . $rowlink %>">
127         <% $money_sprintf->( $row->{tax} ) %>
128       </A>
129     </TD>
130 %   # credited tax
131     <TD CLASS="bigmath"> &minus; </TD>
132     <TD>
133       <A HREF="<% $creditlink . $rowlink %>">
134         <% $money_sprintf->( $row->{credit} ) %>
135       </A>
136     </TD>
137 %   # net tax due
138     <TD CLASS="bigmath"> = </TD>
139     <TD><% $money_sprintf->( $row->{tax} - $row->{credit} ) %></TD>
140   </TR>
141 %   $rownum++;
142 %   $prev_row = $row;
143 % } # foreach my $row
144 % # at the end of everything
145   </TBODY>
146 % if ( $report->{outside} > 0 ) {
147   <TBODY CLASS="total" STYLE="background-color: #cccccc; line-height: 3">
148     <TR>
149       <TD CLASS="rowhead">
150         <% emt('Out of taxable region') %>
151       </TD>
152       <TD STYLE="text-align: right">
153         <A HREF="<% $saleslink %>;out=1;taxname=<% $params{taxname} %>">
154           <% $money_sprintf->( $report->{outside } ) %>
155         </A>
156       </TD>
157       <TD COLSPAN=0></TD>
158     </TR>
159   </TBODY>
160 % }
161 </TABLE>
162
163 <& /elements/footer.html &>
164 <%init>
165
166 die "access denied"
167   unless $FS::CurrentUser::CurrentUser->access_right('Financial reports');
168
169 my $DEBUG = $cgi->param('debug') || 0;
170
171 my $conf = new FS::Conf;
172
173 my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi);
174
175 my %params = (
176   beginning => $beginning,
177   ending    => $ending,
178 );
179 $params{country} = $cgi->param('country');
180 $params{debug}   = $DEBUG;
181 $params{breakdown} = { map { $_ => 1 } $cgi->param('breakdown') };
182
183 my $agentname;
184 if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
185   my $agent = FS::agent->by_key($1) or die "unknown agentnum $1";
186   $params{agentnum} = $1;
187   $agentname = $agent->agentname;
188 }
189
190 if ( $cgi->param('taxname') =~ /^([\w ]+)$/ ) {
191   $params{taxname} = $1;
192 } else {
193   die "taxname required";
194 }
195
196 if ( $cgi->param('credit_date') eq 'cust_credit_bill' ) {
197   $params{credit_date} = 'cust_credit_bill';
198 } else {
199   $params{credit_date} = 'cust_bill';
200 }
201
202 warn "PARAMS:\n".Dumper(\%params)."\n\n" if $DEBUG;
203
204 my $report = FS::Report::Tax->report_internal(%params);
205 my @rows = $report->table; # array of hashrefs
206
207 my $money_char = $conf->config('money_char') || '$';
208 my $money_sprintf = sub {
209   $money_char. sprintf('%.2f', shift);
210 };
211
212 my $dateagentlink = "begin=$beginning;end=$ending";
213 $dateagentlink .= $params{agentnum} if $params{agentnum};
214 my $saleslink  = $p. "search/cust_bill_pkg.cgi?$dateagentlink;nottax=1";
215 my $taxlink    = $p. "search/cust_bill_pkg.cgi?$dateagentlink;istax=1";
216 my $exemptlink = $p. "search/cust_tax_exempt_pkg.cgi?$dateagentlink";
217 my $creditlink = $p. "search/cust_bill_pkg.cgi?$dateagentlink;credit=1;istax=1";
218
219 if ( $params{'credit_date'} eq 'cust_credit_bill' ) {
220   $creditlink =~ s/begin/credit_begin/;
221   $creditlink =~ s/end/credit_end/;
222 }
223
224 my %pkgclass_name = map { $_->classnum, $_->classname } qsearch('pkg_class');
225 $pkgclass_name{''} = 'Unclassified';
226
227 </%init>