13 use FS::UID qw(adminsuidsetup);
14 use FS::Record qw(qsearch);
16 use FS::cust_bill_pay;
20 &untaint_argv; #what it sounds like (eww)
21 use vars qw($opt_v $opt_p $opt_m $opt_e $opt_t $opt_s $opt_f $report_lines $report_template @buf $header);
22 getopts("vpmef:s:"); #switches
24 #we're at now now (and later).
25 my($_finishdate)= $opt_f ? str2time($main::opt_f) : $^T;
26 my($_startdate)= $opt_s ? str2time($main::opt_s) : $^T;
28 # Get the current month
29 my ($ssec,$smin,$shour,$smday,$smon,$syear) =
30 (localtime($_startdate) )[0,1,2,3,4,5];
34 # Get the current month
35 my ($fsec,$fmin,$fhour,$fmday,$fmon,$fyear) =
36 (localtime($_finishdate) )[0,1,2,3,4,5];
40 # Login to the database
41 my $user = shift or die &usage;
44 # Get the needed configuration files
45 my $conf = new FS::Conf;
46 my $lpr = $conf->config('lpr');
47 my $email = $conf->config('email');
48 my $smtpmachine = $conf->config('smtpmachine');
49 my $mail_sender = $conf->exists('invoice_from') ? $conf->config('invoice_from') :
51 my @report_template = $conf->config('report_template')
52 or die "cannot load config file report_template";
54 foreach ( grep /report_lines\(\d+\)/, @report_template ) { #kludgy :/
55 /report_lines\((\d+)\)/;
58 die "no report_lines() functions in template?" unless $report_lines;
59 $report_template = new Text::Template (
61 SOURCE => [ map "$_\n", @report_template ],
62 ) or die "can't create new Text::Template object: $Text::Template::ERROR";
65 my(@cust_bills)=qsearch('cust_bill',{});
66 if (scalar(@cust_bills) == 0)
71 # Open print and email pipes
72 # $lpr and opt_p for printing
73 # $email and opt_m for email
75 if ($lpr && $main::opt_p)
80 if ($email && $main::opt_m)
82 $ENV{MAILADDRESS} = $mail_sender;
83 $header = new Mail::Header ( [
84 "From: Account Processor",
86 "Sender: $mail_sender",
87 "Reply-To: $mail_sender",
88 "Subject: Sales Taxes Invoiced",
101 # Now I can start looping
102 foreach my $cust_bill (@cust_bills)
104 my $_date = $cust_bill->getfield('_date');
105 my $invnum = $cust_bill->getfield('invnum');
106 my $charged = $cust_bill->getfield('charged');
108 if ($_date >= $_startdate && $_date <= $_finishdate) {
111 # The following lines were used to produce rather verbose reports
112 #my ($sec,$min,$hour,$mday,$mon,$year) =
113 # (localtime($_date) )[0,1,2,3,4,5];
115 #$year -= 100 if $year >= 100;
116 #$year = "0" . $year if $year < 10;
120 my $invoice_comped =0;
121 my(@cust_bill_pkgs)= $cust_bill->cust_bill_pkg;
122 foreach my $cust_bill_pkg (@cust_bill_pkgs) {
124 my $recur = $cust_bill_pkg->getfield('recur');
125 my $setup = $cust_bill_pkg->getfield('setup');
126 my $pkgnum = $cust_bill_pkg->getfield('pkgnum');
129 # The following line was used to produce rather verbose reports
130 # push @buf, ('', sprintf(qq{%10s%15s%14.2f}, "$mon/$mday/$year", "Tax $invnum", $recur+$setup));
131 $invoice_tax += $recur;
132 $invoice_tax += $setup;
134 # The following line was used to produce rather verbose reports
135 # push @buf, ('', sprintf(qq{%10s%15s%14.2f}, "$mon/$mday/$year", "Inv $invnum", $recur+$setup));
136 $invoice_amt += $recur;
137 $invoice_amt += $setup;
142 my(@cust_bill_pays)= $cust_bill->cust_bill_pay;
143 foreach my $cust_bill_pay (@cust_bill_pays) {
144 my $payby = $cust_bill_pay->cust_pay->payby;
145 my $paid = $cust_bill_pay->getfield('amount');
146 if ($payby =~ 'COMP') {
147 $invoice_comped += $paid;
151 if (abs($invoice_comped - ($invoice_amt + $invoice_tax)) < 0.0001){
152 $comped += $invoice_amt;
153 $comped_tax += $invoice_tax;
154 } elsif ($invoice_comped > 0) {
155 push @buf, sprintf(qq{\nInvoice %10d has inexpliciable complimentary payments of %14.9f\n}, $invnum, $invoice_comped);
156 $other += $invoice_amt;
157 $other_tax += $invoice_tax;
158 } elsif ($invoice_tax > 0) {
159 $total_tax += $invoice_tax;
160 $taxed += $invoice_amt;
162 $untaxed += $invoice_amt;
169 push @buf, ('', sprintf(qq{%25s%14.2f}, "Complimentary", $comped));
170 push @buf, sprintf(qq{%25s%14.2f}, "Complimentary Tax", $comped_tax);
171 push @buf, sprintf(qq{%25s%14.2f}, "Other", $other);
172 push @buf, sprintf(qq{%25s%14.2f}, "Other Tax", $other_tax);
173 push @buf, sprintf(qq{%25s%14.2f}, "Untaxed", $untaxed);
174 push @buf, sprintf(qq{%25s%14.2f}, "Taxed", $taxed);
175 push @buf, sprintf(qq{%25s%14.2f}, "Tax", $total_tax);
176 push @buf, ('', sprintf(qq{%39s}, "========="), sprintf(qq{%39.2f}, $total));
178 sub FS::tax_report::_template::report_lines {
181 scalar(@buf) ? shift @buf : '' ;
186 $FS::tax_report::_template::title = qq~SALES TAXES INVOICED for $smon/$smday/$syear through $fmon/$fmday/$fyear~;
187 $FS::tax_report::_template::title = $opt_t if $opt_t;
188 $FS::tax_report::_template::page = 1;
189 $FS::tax_report::_template::date = $^T;
190 $FS::tax_report::_template::date = $^T;
191 $FS::tax_report::_template::fdate = $_finishdate;
192 $FS::tax_report::_template::fdate = $_finishdate;
193 $FS::tax_report::_template::sdate = $_startdate;
194 $FS::tax_report::_template::sdate = $_startdate;
195 $FS::tax_report::_template::total_pages =
196 int( scalar(@buf) / $report_lines);
197 $FS::tax_report::_template::total_pages++ if scalar(@buf) % $report_lines;
201 push @report, split("\n",
202 $report_template->fill_in( PACKAGE => 'FS::tax_report::_template' )
204 $FS::tax_report::_template::page++;
208 print map "$_\n", @report;
212 print LPR map "$_\n", @report;
213 print LPR "\f" if $opt_e;
214 close LPR || die "Could not close printer: $lpr\n";
218 my $message = new Mail::Internet (
220 'Body' => [ (@report) ],
223 $message->smtpsend( Host => "$smtpmachine" )
224 or die "can't send report to $email via $smtpmachine: $!";
230 foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
231 $ARGV[$_] =~ /^([\w\-\/ :\.]*)$/ || die "Illegal argument \"$ARGV[$_]\"";
237 die "Usage:\n\n freeside-tax-report [-v] [-p] [-e] user\n";
242 freeside-tax-report - Prints or emails sales taxes invoiced in a given period.
246 freeside-tax-report [-v] [-p] [-m] [-e] [-t "title"] [-s date] [-f date] user
250 Prints or emails sales taxes invoiced in a given period.
252 -v: Verbose - Prints records to STDOUT.
254 -p: Print to printer lpr as found in the conf directory.
256 -m: Email output to user found in the Conf email file.
258 -e: Print a final form feed to the printer.
260 -t: supply a title for the top of each page.
262 -s: starting date for inclusion
264 -f: final date for inclusion
266 user: From the mapsecrets file - see config.html from the base documentation
270 $Id: freeside-tax-report,v 1.5 2002-09-09 22:57:34 ivan Exp $
274 Yes..... Use at your own risk. No guarantees or warrantees of any
275 kind apply to this program. Parts of this program are hacked from
276 other GNU licensed software created mainly by Ivan Kohler.
278 This is released under the GNU Public License. See www.gnu.org
279 for more information regarding this license.
283 L<FS::cust_main>, config.html from the base documentation
287 Jeff Finucane <jeff@cmh.net>
289 based on print-batch by Joel Griffiths <griff@aver-computer.com>