+=item print_html [ TIME [ , TEMPLATE [ , CID ] ] ]
+
+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.
+
+CID is a MIME Content-ID used to create a "cid:" URL for the logo image, used
+when emailing the invoice as part of a multipart/related MIME email.
+
+=cut
+
+#some falze laziness w/print_text and print_latex (and send_csv)
+sub print_html {
+ my( $self, $today, $template, $cid ) = @_;
+ $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 %invoice_data = (
+ 'custnum' => $self->custnum,
+ 'invnum' => $self->invnum,
+ 'date' => time2str('%b %o, %Y', $self->_date),
+ 'today' => time2str('%b %o, %Y', $today),
+ '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),
+ 'terms' => $self->terms,
+ 'cid' => $cid,
+ 'template' => $template,
+# 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
+ );
+
+ if (
+ defined( $conf->config_orbase('invoice_htmlreturnaddress', $template) )
+ && length( $conf->config_orbase('invoice_htmlreturnaddress', $template) )
+ ) {
+ $invoice_data{'returnaddress'} =
+ join("\n", $conf->config('invoice_htmlreturnaddress', $template) );
+ } else {
+ $invoice_data{'returnaddress'} =
+ join("\n", map {
+ s/~/ /g;
+ s/\\\\\*?\s*$/<BR>/;
+ s/\\hyphenation\{[\w\s\-]+\}//;
+ $_;
+ }
+ $conf->config_orbase( 'invoice_latexreturnaddress',
+ $template
+ )
+ );
+ }
+
+ my $countrydefault = $conf->config('countrydefault') || 'US';
+ if ( $cust_main->country eq $countrydefault ) {
+ $invoice_data{'country'} = '';
+ } else {
+ $invoice_data{'country'} =
+ encode_entities(code2country($cust_main->country));
+ }
+
+ if (
+ defined( $conf->config_orbase('invoice_htmlnotes', $template) )
+ && length( $conf->config_orbase('invoice_htmlnotes', $template) )
+ ) {
+ $invoice_data{'notes'} =
+ join("\n", $conf->config_orbase('invoice_htmlnotes', $template) );
+ } else {
+ $invoice_data{'notes'} =
+ join("\n", map {
+ s/%%(.*)$/<!-- $1 -->/;
+ s/\\section\*\{\\textsc\{(.)(.*)\}\}/<p><b><font size="+1">$1<\/font>\U$2<\/b>/;
+ s/\\begin\{enumerate\}/<ol>/;
+ s/\\item / <li>/;
+ s/\\end\{enumerate\}/<\/ol>/;
+ s/\\textbf\{(.*)\}/<b>$1<\/b>/;
+ s/\\\\\*/ /;
+ $_;
+ }
+ $conf->config_orbase('invoice_latexnotes', $template)
+ );
+ }
+
+# #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)
+# );
+
+ if (
+ defined( $conf->config_orbase('invoice_htmlfooter', $template) )
+ && length( $conf->config_orbase('invoice_htmlfooter', $template) )
+ ) {
+ $invoice_data{'footer'} =
+ join("\n", $conf->config_orbase('invoice_htmlfooter', $template) );
+ } else {
+ $invoice_data{'footer'} =
+ join("\n", map { s/~/ /g; s/\\\\\*?\s*$/<BR>/; $_; }
+ $conf->config_orbase('invoice_latexfooter', $template)
+ );
+ }
+
+ $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);
+}
+