+=item print_html [ TIME [ , TEMPLATE ] ]
+
+Returns an HTML invoice, as a scalar.
+
+TIME an optional value used to control the printing of overdue messages. The
+default is now. It isn't the date of the invoice; that's the `_date' field.
+It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=cut
+
+#sub print_html {
+# my $self = shift;
+#
+# my $file = $self->print_latex(@_);
+#
+# my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+# chdir($dir);
+#
+# my $sfile = shell_quote $file;
+#
+# system("htlatex $sfile.tex") == 0
+# or die "hlatex $file.tex failed; is hlatex installed, or see $file.log for details?\n";
+# #system("ltoh $sfile.tex") == 0
+# # or die "ltoh $file.tex failed; is hlatex installed, or see $file.log for details?\n";
+#
+# open(HTML, "<$file.html")
+# or die "can't open $file.html: $! (error in LaTeX template?)\n";
+#
+# #unlink("$file.dvi", "$file.log", "$file.aux", "$file.html", "$file.tex");
+#
+# my $html = '';
+# while (<HTML>) {
+#
+# s/<link\s+rel="stylesheet"\s+type="text\/css"\s+href="invoice\.(\d+)\.(\w+)\.css">/<link rel="stylesheet" type="text\/css" href="cust_bill.html?$1.$2.css">/;
+## s/<link\s+//;
+# $html .= $_;
+# }
+#
+# close HTML;
+#
+# return $html;
+#
+#}
+#
+##inefficient proof-of-concept for now
+#sub print_html_css {
+# my $self = shift;
+#
+# my $file = $self->print_latex(@_);
+#
+# my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+# chdir($dir);
+#
+# my $sfile = shell_quote $file;
+#
+# system("htlatex $sfile.tex") == 0
+# or die "hlatex $file.tex failed; is hlatex installed, or see $file.log for details?\n";
+# #system("ltoh $sfile.tex") == 0
+# # or die "ltoh $file.tex failed; is hlatex installed, or see $file.log for details?\n";
+#
+# open(CSS, "<$file.css")
+# or die "can't open $file.html: $! (error in LaTeX template?)\n";
+#
+# unlink("$file.dvi", "$file.log", "$file.aux", "$file.html", "$file.tex");
+#
+# my $css = '';
+# while (<CSS>) {
+# $css .= $_;
+# }
+#
+# close CSS;
+#
+# return $css;
+#
+#}
+
+sub print_html {
+ my( $self, $today, $template ) = @_;
+ $today ||= time;
+
+ my $cust_main = $self->cust_main;
+ $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
+ unless $cust_main->payname && $cust_main->payby !~ /^(CHEK|DCHK)$/;
+
+ $template ||= $self->_agent_template;
+ my $templatefile = 'invoice_html';
+ my $suffix = length($template) ? "_$template" : '';
+ $templatefile .= $suffix;
+ my @html_template = map "$_\n", $conf->config($templatefile)
+ or die "cannot load config file $templatefile";
+
+ my $html_template = new Text::Template(
+ TYPE => 'ARRAY',
+ SOURCE => \@html_template,
+ DELIMITERS => [ '<%=', '%>' ],
+ );
+
+ $html_template->compile()
+ or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR;
+
+ my $returnaddress = $conf->exists('invoice_htmlreturnaddress')
+ ? join("\n", $conf->config('invoice_htmlreturnaddress') )
+ : join("\n", map { s/~/ /g; s/\\\\\*?\s*$/<BR>/; }
+ $conf->config('invoice_latexreturnaddress')
+ );
+ warn $conf->config('invoice_latexreturnaddress');
+ warn $returnaddress;
+
+ my %invoice_data = (
+ 'invnum' => $self->invnum,
+ 'date' => time2str('%b %o, %Y', $self->_date),
+ 'agent' => encode_entities($cust_main->agent->agent),
+ 'payname' => encode_entities($cust_main->payname),
+ 'company' => encode_entities($cust_main->company),
+ 'address1' => encode_entities($cust_main->address1),
+ 'address2' => encode_entities($cust_main->address2),
+ 'city' => encode_entities($cust_main->city),
+ 'state' => encode_entities($cust_main->state),
+ 'zip' => encode_entities($cust_main->zip),
+ 'country' => encode_entities($cust_main->country),
+# 'footer' => join("\n", $conf->config('invoice_latexfooter') ),
+# 'smallfooter' => join("\n", $conf->config('invoice_latexsmallfooter') ),
+ 'returnaddress' => $returnaddress,
+ 'terms' => $conf->config('invoice_default_terms')
+ || 'Payable upon receipt',
+ #'notes' => join("\n", $conf->config('invoice_latexnotes') ),
+# 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
+ );
+
+ my $countrydefault = $conf->config('countrydefault') || 'US';
+ $invoice_data{'country'} = '' if $invoice_data{'country'} eq $countrydefault;
+
+# #do variable substitutions in notes
+# $invoice_data{'notes'} =
+# join("\n",
+# map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+# $conf->config_orbase('invoice_latexnotes', $suffix)
+# );
+#
+# $invoice_data{'footer'} =~ s/\n+$//;
+# $invoice_data{'smallfooter'} =~ s/\n+$//;
+# $invoice_data{'notes'} =~ s/\n+$//;
+#
+ $invoice_data{'po_line'} =
+ ( $cust_main->payby eq 'BILL' && $cust_main->payinfo )
+ ? encode_entities("Purchase Order #". $cust_main->payinfo)
+ : '';
+
+ my $money_char = $conf->config('money_char') || '$';
+
+ foreach my $line_item ( $self->_items ) {
+ my $detail = {
+ ext_description => [],
+ };
+ $detail->{'ref'} = $line_item->{'pkgnum'};
+ $detail->{'description'} = encode_entities($line_item->{'description'});
+ if ( exists $line_item->{'ext_description'} ) {
+ @{$detail->{'ext_description'}} = map {
+ encode_entities($_);
+ } @{$line_item->{'ext_description'}};
+ }
+ $detail->{'amount'} = $money_char. $line_item->{'amount'};
+ $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
+
+ push @{$invoice_data{'detail_items'}}, $detail;
+ }
+
+
+ my $taxtotal = 0;
+ foreach my $tax ( $self->_items_tax ) {
+ my $total = {};
+ $total->{'total_item'} = encode_entities($tax->{'description'});
+ $taxtotal += $tax->{'amount'};
+ $total->{'total_amount'} = $money_char. $tax->{'amount'};
+ push @{$invoice_data{'total_items'}}, $total;
+ }
+
+ if ( $taxtotal ) {
+ my $total = {};
+ $total->{'total_item'} = 'Sub-total';
+ $total->{'total_amount'} =
+ $money_char. sprintf('%.2f', $self->charged - $taxtotal );
+ unshift @{$invoice_data{'total_items'}}, $total;
+ }
+
+ my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance
+ {
+ my $total = {};
+ $total->{'total_item'} = '<b>Total</b>';
+ $total->{'total_amount'} =
+ "<b>$money_char". sprintf('%.2f', $self->charged + $pr_total ). '</b>';
+ push @{$invoice_data{'total_items'}}, $total;
+ }
+
+ #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments
+
+ # credits
+ foreach my $credit ( $self->_items_credits ) {
+ my $total;
+ $total->{'total_item'} = encode_entities($credit->{'description'});
+ #$credittotal
+ $total->{'total_amount'} = "-$money_char". $credit->{'amount'};
+ push @{$invoice_data{'total_items'}}, $total;
+ }
+
+ # payments
+ foreach my $payment ( $self->_items_payments ) {
+ my $total = {};
+ $total->{'total_item'} = encode_entities($payment->{'description'});
+ #$paymenttotal
+ $total->{'total_amount'} = "-$money_char". $payment->{'amount'};
+ push @{$invoice_data{'total_items'}}, $total;
+ }
+
+ {
+ my $total;
+ $total->{'total_item'} = '<b>'. $self->balance_due_msg. '</b>';
+ $total->{'total_amount'} =
+ "<b>$money_char". sprintf('%.2f', $self->owed + $pr_total ). '</b>';
+ push @{$invoice_data{'total_items'}}, $total;
+ }
+
+ $html_template->fill_in( HASH => \%invoice_data);
+}
+