diff options
-rw-r--r-- | FS/FS/cust_bill.pm | 310 | ||||
-rw-r--r-- | conf/invoice_latex | 75 | ||||
-rw-r--r-- | conf/invoice_latex.diff | 138 |
3 files changed, 389 insertions, 134 deletions
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 10b4928cb..4c37e68b2 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -4,7 +4,7 @@ use strict; use vars qw( @ISA $conf $money_char ); use vars qw( $invoice_lines @buf ); #yuck use Date::Format; -use Text::Template; +use Text::Template 1.20; use File::Temp 0.14; use String::ShellQuote; use FS::UID qw( datasrc ); @@ -418,16 +418,17 @@ sub send { my @print_text = $self->print_text('', $template); my @invoicing_list = $self->cust_main->invoicing_list; - if ( grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list or !@invoicing_list ) { #email + if ( grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list or !@invoicing_list ) { + #email #better to notify this person than silence @invoicing_list = ($invoice_from) unless @invoicing_list; my $error = send_email( $self->generate_email( - 'from' => $invoice_from, - 'to' => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ], - 'print_text' => [ @print_text ], + 'from' => $invoice_from, + 'to' => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ], + 'print_text' => [ @print_text ], ) ); die "can't email invoice: $error\n" if $error; @@ -454,9 +455,8 @@ sub send { } if ( grep { $_ eq 'FAX' } @invoicing_list ) { #fax - unless ($conf->exists('invoice_latex')) { - die 'FAX invoice destination not supported with plain text invoices.' - } + die 'FAX invoice destination not supported with plain text invoices.' + unless $conf->exists('invoice_latex'); my $dialstring = $self->cust_main->getfield('fax'); #Check $dialstring? my $error = send_fax(docdata => $lpr_data, dialstring => $dialstring); @@ -1102,9 +1102,27 @@ sub print_latex { my $templatefile = 'invoice_latex'; my $suffix = length($template) ? "_$template" : ''; $templatefile .= $suffix; - my @invoice_template = $conf->config($templatefile) + my @invoice_template = map "$_\n", $conf->config($templatefile) or die "cannot load config file $templatefile"; + my($format, $text_template); + if ( grep { /^%%Detail/ } @invoice_template ) { + #change this to a die when the old code is removed + warn "old-style invoice template $templatefile; ". + "patch with conf/invoice_latex.diff\n"; + $format = 'old'; + } else { + $format = 'Text::Template'; + $text_template = new Text::Template( + TYPE => 'ARRAY', + SOURCE => \@invoice_template, + DELIMITERS => [ '[@--', '--@]' ], + ); + + $text_template->compile() + or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR; + } + my %invoice_data = ( 'invnum' => $self->invnum, 'date' => time2str('%b %o, %Y', $self->_date), @@ -1143,110 +1161,198 @@ sub print_latex { ? _latex_escape("Purchase Order #". $cust_main->payinfo) : '~'; - my @line_item = (); - my @total_item = (); my @filled_in = (); - while ( @invoice_template ) { - my $line = shift @invoice_template; - - if ( $line =~ /^%%Detail\s*$/ ) { - - while ( ( my $line_item_line = shift @invoice_template ) - !~ /^%%EndDetail\s*$/ ) { - push @line_item, $line_item_line; - } - foreach my $line_item ( $self->_items ) { - #foreach my $line_item ( $self->_items_pkg ) { - $invoice_data{'ref'} = $line_item->{'pkgnum'}; - $invoice_data{'description'} = _latex_escape($line_item->{'description'}); - if ( exists $line_item->{'ext_description'} ) { - $invoice_data{'description'} .= - "\\tabularnewline\n~~". - join("\\tabularnewline\n~~", map { _latex_escape($_) } @{$line_item->{'ext_description'}} ); + if ( $format eq 'old' ) { + + my @line_item = (); + my @total_item = (); + while ( @invoice_template ) { + my $line = shift @invoice_template; + + if ( $line =~ /^%%Detail\s*$/ ) { + + while ( ( my $line_item_line = shift @invoice_template ) + !~ /^%%EndDetail\s*$/ ) { + push @line_item, $line_item_line; } - $invoice_data{'amount'} = $line_item->{'amount'}; - $invoice_data{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; - push @filled_in, - map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } @line_item; - } - - } elsif ( $line =~ /^%%TotalDetails\s*$/ ) { - - while ( ( my $total_item_line = shift @invoice_template ) - !~ /^%%EndTotalDetails\s*$/ ) { - push @total_item, $total_item_line; - } - - my @total_fill = (); - - my $taxtotal = 0; - foreach my $tax ( $self->_items_tax ) { - $invoice_data{'total_item'} = _latex_escape($tax->{'description'}); - $taxtotal += ( $invoice_data{'total_amount'} = $tax->{'amount'} ); + foreach my $line_item ( $self->_items ) { + #foreach my $line_item ( $self->_items_pkg ) { + $invoice_data{'ref'} = $line_item->{'pkgnum'}; + $invoice_data{'description'} = + _latex_escape($line_item->{'description'}); + if ( exists $line_item->{'ext_description'} ) { + $invoice_data{'description'} .= + "\\tabularnewline\n~~". + join( "\\tabularnewline\n~~", + map _latex_escape($_), @{$line_item->{'ext_description'}} + ); + } + $invoice_data{'amount'} = $line_item->{'amount'}; + $invoice_data{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; + push @filled_in, + map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } @line_item; + } + + } elsif ( $line =~ /^%%TotalDetails\s*$/ ) { + + while ( ( my $total_item_line = shift @invoice_template ) + !~ /^%%EndTotalDetails\s*$/ ) { + push @total_item, $total_item_line; + } + + my @total_fill = (); + + my $taxtotal = 0; + foreach my $tax ( $self->_items_tax ) { + $invoice_data{'total_item'} = _latex_escape($tax->{'description'}); + $taxtotal += ( $invoice_data{'total_amount'} = $tax->{'amount'} ); + push @total_fill, + map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } + @total_item; + } + + if ( $taxtotal ) { + $invoice_data{'total_item'} = 'Sub-total'; + $invoice_data{'total_amount'} = + '\dollar '. sprintf('%.2f', $self->charged - $taxtotal ); + unshift @total_fill, + map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } + @total_item; + } + + $invoice_data{'total_item'} = '\textbf{Total}'; + $invoice_data{'total_amount'} = + '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}'; push @total_fill, map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } @total_item; - } - - if ( $taxtotal ) { - $invoice_data{'total_item'} = 'Sub-total'; + + #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments + + # credits + foreach my $credit ( $self->_items_credits ) { + $invoice_data{'total_item'} = _latex_escape($credit->{'description'}); + #$credittotal + $invoice_data{'total_amount'} = '-\dollar '. $credit->{'amount'}; + push @total_fill, + map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } + @total_item; + } + + # payments + foreach my $payment ( $self->_items_payments ) { + $invoice_data{'total_item'} = _latex_escape($payment->{'description'}); + #$paymenttotal + $invoice_data{'total_amount'} = '-\dollar '. $payment->{'amount'}; + push @total_fill, + map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } + @total_item; + } + + $invoice_data{'total_item'} = '\textbf{'. $self->balance_due_msg. '}'; $invoice_data{'total_amount'} = - '\dollar '. sprintf('%.2f', $self->charged - $taxtotal ); - unshift @total_fill, + '\textbf{\dollar '. sprintf('%.2f', $self->owed + $pr_total ). '}'; + push @total_fill, map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } @total_item; + + push @filled_in, @total_fill; + + } else { + #$line =~ s/\$(\w+)/$invoice_data{$1}/eg; + $line =~ s/\$(\w+)/exists($invoice_data{$1}) ? $invoice_data{$1} : nounder($1)/eg; + push @filled_in, $line; } + + } - $invoice_data{'total_item'} = '\textbf{Total}'; - $invoice_data{'total_amount'} = - '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}'; - push @total_fill, - map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } - @total_item; - - #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments - - # credits - foreach my $credit ( $self->_items_credits ) { - $invoice_data{'total_item'} = _latex_escape($credit->{'description'}); - #$credittotal - $invoice_data{'total_amount'} = '-\dollar '. $credit->{'amount'}; - push @total_fill, - map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } - @total_item; - } + sub nounder { + my $var = $1; + $var =~ s/_/\-/g; + $var; + } - # payments - foreach my $payment ( $self->_items_payments ) { - $invoice_data{'total_item'} = _latex_escape($payment->{'description'}); - #$paymenttotal - $invoice_data{'total_amount'} = '-\dollar '. $payment->{'amount'}; - push @total_fill, - map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } - @total_item; + } elsif ( $format eq 'Text::Template' ) { + + my @detail_items = (); + my @total_items = (); + + $invoice_data{'detail_items'} = \@detail_items; + $invoice_data{'total_items'} = \@total_items; + + foreach my $line_item ( $self->_items ) { + my $detail = { + ext_description => [], + }; + $detail->{'ref'} = $line_item->{'pkgnum'}; + $detail->{'quantity'} = 1; + $detail->{'description'} = _latex_escape($line_item->{'description'}); + if ( exists $line_item->{'ext_description'} ) { + @{$detail->{'ext_description'}} = map { + _latex_escape($_); + } @{$line_item->{'ext_description'}}; } - - $invoice_data{'total_item'} = '\textbf{'. $self->balance_due_msg. '}'; - $invoice_data{'total_amount'} = + $detail->{'amount'} = $line_item->{'amount'}; + $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; + + push @detail_items, $detail; + } + + + my $taxtotal = 0; + foreach my $tax ( $self->_items_tax ) { + my $total = {}; + $total->{'total_item'} = _latex_escape($tax->{'description'}); + $taxtotal += ( $invoice_data{'total_amount'} = $tax->{'amount'} ); + push @total_items, $total; + } + + if ( $taxtotal ) { + my $total = {}; + $total->{'total_item'} = 'Sub-total'; + $total->{'total_amount'} = + '\dollar '. sprintf('%.2f', $self->charged - $taxtotal ); + unshift @total_items, $total; + } + + { + my $total = {}; + $total->{'total_item'} = '\textbf{Total}'; + $total->{'total_amount'} = + '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}'; + push @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'} = _latex_escape($credit->{'description'}); + #$credittotal + $total->{'total_amount'} = '-\dollar '. $credit->{'amount'}; + push @total_items, $total; + } + + # payments + foreach my $payment ( $self->_items_payments ) { + my $total = {}; + $total->{'total_item'} = _latex_escape($payment->{'description'}); + #$paymenttotal + $total->{'total_amount'} = '-\dollar '. $payment->{'amount'}; + push @total_items, $total; + } + + { + my $total; + $total->{'total_item'} = '\textbf{'. $self->balance_due_msg. '}'; + $total->{'total_amount'} = '\textbf{\dollar '. sprintf('%.2f', $self->owed + $pr_total ). '}'; - push @total_fill, - map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } - @total_item; - - push @filled_in, @total_fill; - - } else { - #$line =~ s/\$(\w+)/$invoice_data{$1}/eg; - $line =~ s/\$(\w+)/exists($invoice_data{$1}) ? $invoice_data{$1} : nounder($1)/eg; - push @filled_in, $line; + push @total_items, $total; } - } - - sub nounder { - my $var = $1; - $var =~ s/_/\-/g; - $var; + } else { + die "guru meditation #54"; } my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc; @@ -1255,7 +1361,13 @@ sub print_latex { SUFFIX => '.tex', UNLINK => 0, ) or die "can't open temp file: $!\n"; - print $fh join("\n", @filled_in ), "\n"; + if ( $format eq 'old' ) { + print $fh join('', @filled_in ); + } elsif ( $format eq 'Text::Template' ) { + $text_template->fill_in(OUTPUT => $fh, HASH => \%invoice_data); + } else { + die "guru meditation #32"; + } close $fh; $fh->filename =~ /^(.*).tex$/ or die "unparsable filename: ". $fh->filename; diff --git a/conf/invoice_latex b/conf/invoice_latex index 195f8fbb2..e7f6d08d6 100644 --- a/conf/invoice_latex +++ b/conf/invoice_latex @@ -5,7 +5,7 @@ %% Asplen Management Ltd
%% www.asplen.co.uk
%%
-%% Modified for Freeside by Ivan Kohler
+%% Modified for Freeside by Ivan Kohler and Kristian Hoffman
%%
%% Changes
%% 0.1 4/12/00 Created
@@ -61,7 +61,7 @@ %% Headers and footers defined for the first page
\fancyfoot[CO,CE]{\small{
\begin{tabular}{c}
-$footer
+[@-- $footer --@]
\end{tabular}}}
%
%% The LH Heading comprising logo
@@ -76,7 +76,7 @@ $footer \begin{tabular}{rcl}
Invoice date & & Invoice number \\
\vspace{0.2cm}
-\textbf{$date} & & \textbf{$invnum} \\\hline
+\textbf{[@-- $date --@]} & & \textbf{[@-- $invnum --@]} \\\hline
\rule{0pt}{5ex} &~~ \huge{\textsc{Invoice}}& \\
\vspace{-0.2cm}
& & \\\hline
@@ -85,71 +85,76 @@ Invoice date & & Invoice number \\ %% Header & footer changes for subsequent pages
%
\afterpage{ \fancyfoot[RO,RE]{\small{\thepage\ of \pageref{LastPage}}} }
-\afterpage{ \fancyfoot[CO,CE]{\small{$smallfooter}} }
+\afterpage{ \fancyfoot[CO,CE]{\small{[@-- $smallfooter --@]}} }
\afterpage{ \fancyhead[LO,LE]{\small{}} }
\afterpage{ \fancyhead[RO,RE]{\small{
\begin{tabular}{ll}
Invoice date & Invoice number\\
-\textbf{$date} & \textbf{$invnum}\\
+\textbf{[@-- $date --@]} & \textbf{[@-- $invnum --@]}\\
\end{tabular}}} }
%
%
\makebox{
\begin{minipage}[t]{2.9in}
\vspace{0.20in}
-\textbf{$payname}\\
-\addressline{$company}
-\addressline{$address1}
-\addressline{$address2}
-\addressline{$city, $state $zip}
-\addressline{$country}
+\textbf{[@-- $payname --@]}\\
+\addressline{[@-- $company --@]}
+\addressline{[@-- $address1 --@]}
+\addressline{[@-- $address2 --@]}
+\addressline{[@-- $city --@], [@-- $state --@] [@-- $zip --@]}
+\addressline{[@-- $country --@]}
\end{minipage}}
\hfill
\makebox{
\begin{minipage}[t]{2.5in}
\begin{flushright}
-Terms: $terms\\
-$po_line\\
+Terms: [@-- $terms --@]\\
+[@-- $po_line --@]\\
\end{flushright}
\end{minipage}}
\vspace{0.5cm}
%
\section*{\textsc{Charges}}
-\begin{longtable}{|c|l|c|r|r|}
+\begin{longtable}{|c|l|r|}
\hline
\rule{0pt}{2.5ex}
\makebox[1.4cm]{\textbf{Ref}} &
-\makebox[7.9cm][l]{\textbf{Description}} &
-\makebox[1.3cm][c]{\textbf{Quantity}} &
-\makebox[2.5cm][r]{\textbf{Unit Price}} &
-\makebox[2.5cm][r]{\textbf{Amount}} \\
+\makebox[13cm][l]{\textbf{Description}} &
+\makebox[2cm][r]{\textbf{Amount}} \\
\hline
\endfirsthead
-\multicolumn{5}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\
+\multicolumn{3}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\
\hline
\rule{0pt}{2.5ex}
\makebox[1.4cm]{\textbf{Ref}} &
-\makebox[7.9cm][l]{\textbf{Description}} &
-\makebox[1.3cm][c]{\textbf{Quantity}} &
-\makebox[2.5cm][r]{\textbf{Unit Price}} &
-\makebox[2.5cm][r]{\textbf{Amount}} \\
+\makebox[13cm][l]{\textbf{Description}} &
+\makebox[2cm][r]{\textbf{Amount}} \\
\hline
\endhead
-\multicolumn{5}{r}{\rule{0pt}{2.5ex}/cont...}\\
+\multicolumn{3}{r}{\rule{0pt}{2.5ex}/cont...}\\
\endfoot
-%%TotalDetails
- & \multicolumn{3}{l}{$total_item} & $total_amount\\
-%%EndTotalDetails
+[@--
+
+ foreach my $line (@total_items) {
+ $OUT .= ' & \multicolumn{1}{l}{' . $line->{'total_item'} . '} & ' .
+ $line->{'total_amount'} . '\\\\' . "\n";
+ }
+
+--@]
\hline
\endlastfoot
-%%Detail
-\rule{0pt}{2.5ex}$ref &
-\begin{tabular}{l}
-$description\tabularnewline
-\end{tabular}
-& $quantity & \dollar $amount & \dollar $amount\\\hline
-%%EndDetail
+[@--
+
+ foreach my $line (@detail_items) {
+ $OUT .= '\rule{0pt}{2.5ex}' . $line->{'ref'} . ' &' . "\n".
+ '\begin{tabular}{l}' . "\n".
+ $line->{'description'} . '\tabularnewline' . "\n".
+ '\end{tabular}' . "\n".
+ '& \dollar ' . $line->{'amount'} . '\\\\\\hline' . "\n";
+ }
+
+--@]
\end{longtable}
\vfill
-$notes
+[@-- $notes --@]
\end{document}
diff --git a/conf/invoice_latex.diff b/conf/invoice_latex.diff new file mode 100644 index 000000000..b66a522f0 --- /dev/null +++ b/conf/invoice_latex.diff @@ -0,0 +1,138 @@ +--- invoice_latex.old 2005-04-14 01:52:02.000000000 -0700 ++++ invoice_latex 2005-04-14 02:33:26.000000000 -0700 +@@ -5,7 +5,7 @@ + %% Asplen Management Ltd
+ %% www.asplen.co.uk
+ %%
+-%% Modified for Freeside by Ivan Kohler
++%% Modified for Freeside by Ivan Kohler and Kristian Hoffman
+ %%
+ %% Changes
+ %% 0.1 4/12/00 Created
+@@ -61,7 +61,7 @@ + %% Headers and footers defined for the first page
+ \fancyfoot[CO,CE]{\small{
+ \begin{tabular}{c}
+-$footer
++[@-- $footer --@]
+ \end{tabular}}}
+ %
+ %% The LH Heading comprising logo
+@@ -76,7 +76,7 @@ + \begin{tabular}{rcl}
+ Invoice date & & Invoice number \\
+ \vspace{0.2cm}
+-\textbf{$date} & & \textbf{$invnum} \\\hline
++\textbf{[@-- $date --@]} & & \textbf{[@-- $invnum --@]} \\\hline
+ \rule{0pt}{5ex} &~~ \huge{\textsc{Invoice}}& \\
+ \vspace{-0.2cm}
+ & & \\\hline
+@@ -85,71 +85,76 @@ + %% Header & footer changes for subsequent pages
+ %
+ \afterpage{ \fancyfoot[RO,RE]{\small{\thepage\ of \pageref{LastPage}}} }
+-\afterpage{ \fancyfoot[CO,CE]{\small{$smallfooter}} }
++\afterpage{ \fancyfoot[CO,CE]{\small{[@-- $smallfooter --@]}} }
+ \afterpage{ \fancyhead[LO,LE]{\small{}} }
+ \afterpage{ \fancyhead[RO,RE]{\small{
+ \begin{tabular}{ll}
+ Invoice date & Invoice number\\
+-\textbf{$date} & \textbf{$invnum}\\
++\textbf{[@-- $date --@]} & \textbf{[@-- $invnum --@]}\\
+ \end{tabular}}} }
+ %
+ %
+ \makebox{
+ \begin{minipage}[t]{2.9in}
+ \vspace{0.20in}
+-\textbf{$payname}\\
+-\addressline{$company}
+-\addressline{$address1}
+-\addressline{$address2}
+-\addressline{$city, $state $zip}
+-\addressline{$country}
++\textbf{[@-- $payname --@]}\\
++\addressline{[@-- $company --@]}
++\addressline{[@-- $address1 --@]}
++\addressline{[@-- $address2 --@]}
++\addressline{[@-- $city --@], [@-- $state --@] [@-- $zip --@]}
++\addressline{[@-- $country --@]}
+ \end{minipage}}
+ \hfill
+ \makebox{
+ \begin{minipage}[t]{2.5in}
+ \begin{flushright}
+-Terms: $terms\\
+-$po_line\\
++Terms: [@-- $terms --@]\\
++[@-- $po_line --@]\\
+ \end{flushright}
+ \end{minipage}}
+ \vspace{0.5cm}
+ %
+ \section*{\textsc{Charges}}
+-\begin{longtable}{|c|l|c|r|r|}
++\begin{longtable}{|c|l|r|}
+ \hline
+ \rule{0pt}{2.5ex}
+ \makebox[1.4cm]{\textbf{Ref}} &
+-\makebox[7.9cm][l]{\textbf{Description}} &
+-\makebox[1.3cm][c]{\textbf{Quantity}} &
+-\makebox[2.5cm][r]{\textbf{Unit Price}} &
+-\makebox[2.5cm][r]{\textbf{Amount}} \\
++\makebox[13cm][l]{\textbf{Description}} &
++\makebox[2cm][r]{\textbf{Amount}} \\
+ \hline
+ \endfirsthead
+-\multicolumn{5}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\
++\multicolumn{3}{r}{\rule{0pt}{2.5ex}Continued from previous page}\\
+ \hline
+ \rule{0pt}{2.5ex}
+ \makebox[1.4cm]{\textbf{Ref}} &
+-\makebox[7.9cm][l]{\textbf{Description}} &
+-\makebox[1.3cm][c]{\textbf{Quantity}} &
+-\makebox[2.5cm][r]{\textbf{Unit Price}} &
+-\makebox[2.5cm][r]{\textbf{Amount}} \\
++\makebox[13cm][l]{\textbf{Description}} &
++\makebox[2cm][r]{\textbf{Amount}} \\
+ \hline
+ \endhead
+-\multicolumn{5}{r}{\rule{0pt}{2.5ex}/cont...}\\
++\multicolumn{3}{r}{\rule{0pt}{2.5ex}/cont...}\\
+ \endfoot
+-%%TotalDetails
+- & \multicolumn{3}{l}{$total_item} & $total_amount\\
+-%%EndTotalDetails
++[@--
++
++ foreach my $line (@total_items) {
++ $OUT .= ' & \multicolumn{1}{l}{' . $line->{'total_item'} . '} & ' .
++ $line->{'total_amount'} . '\\\\' . "\n";
++ }
++
++--@]
+ \hline
+ \endlastfoot
+-%%Detail
+-\rule{0pt}{2.5ex}$ref &
+-\begin{tabular}{l}
+-$description\tabularnewline
+-\end{tabular}
+-& $quantity & \dollar $amount & \dollar $amount\\\hline
+-%%EndDetail
++[@--
++
++ foreach my $line (@detail_items) {
++ $OUT .= '\rule{0pt}{2.5ex}' . $line->{'ref'} . ' &' . "\n".
++ '\begin{tabular}{l}' . "\n".
++ $line->{'description'} . '\tabularnewline' . "\n".
++ '\end{tabular}' . "\n".
++ '& \dollar ' . $line->{'amount'} . '\\\\\\hline' . "\n";
++ }
++
++--@]
+ \end{longtable}
+ \vfill
+-$notes
++[@-- $notes --@]
+ \end{document}
|