+ my $old_latex = '';
+ if ( $format eq 'latex' && 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 or use new conf/invoice_latex*\n";
+ $old_latex = 'true';
+ @invoice_template = _translate_old_latex_format(@invoice_template);
+ }
+
+ my $text_template = new Text::Template(
+ TYPE => 'ARRAY',
+ SOURCE => \@invoice_template,
+ DELIMITERS => $delimiters{$format},
+ );
+
+ $text_template->compile()
+ or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR;
+
+
+ # additional substitution could possibly cause breakage in existing templates
+ my %convert_maps = (
+ 'latex' => {
+ 'notes' => sub { map "$_", @_ },
+ 'footer' => sub { map "$_", @_ },
+ 'smallfooter' => sub { map "$_", @_ },
+ 'returnaddress' => sub { map "$_", @_ },
+ },
+ 'html' => {
+ 'notes' =>
+ sub {
+ map {
+ s/%%(.*)$/<!-- $1 -->/g;
+ s/\\section\*\{\\textsc\{(.)(.*)\}\}/<p><b><font size="+1">$1<\/font>\U$2<\/b>/g;
+ s/\\begin\{enumerate\}/<ol>/g;
+ s/\\item / <li>/g;
+ s/\\end\{enumerate\}/<\/ol>/g;
+ s/\\textbf\{(.*)\}/<b>$1<\/b>/g;
+ s/\\\\\*/ /;
+ s/\\dollar ?/\$/g;
+ $_;
+ } @_
+ },
+ 'footer' =>
+ sub { map { s/~/ /g; s/\\\\\*?\s*$/<BR>/; $_; } @_ },
+ 'smallfooter' =>
+ sub { map { s/~/ /g; s/\\\\\*?\s*$/<BR>/; $_; } @_ },
+ 'returnaddress' =>
+ sub {
+ map {
+ s/~/ /g;
+ s/\\\\\*?\s*$/<BR>/;
+ s/\\hyphenation\{[\w\s\-]+}//;
+ $_;
+ } @_
+ },
+ },
+ 'template' => {
+ 'notes' =>
+ sub {
+ map {
+ s/%%.*$//g;
+ s/\\section\*\{\\textsc\{(.*)\}\}/\U$1/g;
+ s/\\begin\{enumerate\}//g;
+ s/\\item / * /g;
+ s/\\end\{enumerate\}//g;
+ s/\\textbf\{(.*)\}/$1/g;
+ s/\\\\\*/ /;
+ s/\\dollar ?/\$/g;
+ $_;
+ } @_
+ },
+ 'footer' =>
+ sub { map { s/~/ /g; s/\\\\\*?\s*$/\n/; $_; } @_ },
+ 'smallfooter' =>
+ sub { map { s/~/ /g; s/\\\\\*?\s*$/\n/; $_; } @_ },
+ 'returnaddress' =>
+ sub {
+ map {
+ s/~/ /g;
+ s/\\\\\*?\s*$/\n/; # dubious
+ s/\\hyphenation\{[\w\s\-]+}//;
+ $_;
+ } @_
+ },
+ },
+ );
+
+
+ # hashes for differing output formats
+ my %nbsps = ( 'latex' => '~',
+ 'html' => '', # '&nbps;' would be nice
+ 'template' => '', # not used
+ );
+ my $nbsp = $nbsps{$format};
+
+ my %escape_functions = ( 'latex' => \&_latex_escape,
+ 'html' => \&encode_entities,
+ 'template' => sub { shift },
+ );
+ my $escape_function = $escape_functions{$format};
+
+ my %date_formats = ( 'latex' => '%b, %o, %Y',
+ 'html' => '%b %o, %Y',
+ 'template' => '%s',
+ );
+ my $date_format = $date_formats{$format};
+
+ my %embolden_functions = ( 'latex' => sub { return '\textbf{'. shift(). '}'
+ },
+ 'html' => sub { return '<b>'. shift(). '</b>'
+ },
+ 'template' => sub { shift },
+ );
+ my $embolden_function = $embolden_functions{$format};
+
+
+ # generate template variables
+ my $returnaddress;
+ if (
+ defined( $conf->config_orbase( "invoice_${format}returnaddress",
+ $template
+ )
+ )
+ && length( $conf->config_orbase( "invoice_${format}returnaddress",
+ $template
+ )
+ )
+ ) {
+
+ $returnaddress = join("\n",
+ $conf->config_orbase("invoice_${format}returnaddress", $template)
+ );
+
+ } elsif ( grep /\S/,
+ $conf->config_orbase('invoice_latexreturnaddress', $template) ) {
+
+ my $convert_map = $convert_maps{$format}{'returnaddress'};
+ $returnaddress =
+ join( "\n",
+ &$convert_map( $conf->config_orbase( "invoice_latexreturnaddress",
+ $template
+ )
+ )
+ );
+ } elsif ( grep /\S/, $conf->config('company_address') ) {
+
+ $returnaddress = join( "\n", $conf->config('company_address') );
+
+ $returnaddress =
+ join( '\\*'."\n", map s/( {2,})/'~' x length($1)/eg,
+ $conf->config('company_address')
+ )
+ if $format eq 'latex';
+
+ } else {
+
+ my $warning = "Couldn't find a return address; ".
+ "do you need to set the company_address configuration value?";
+ warn "$warning\n";
+ $returnaddress = $nbsp;
+ #$returnaddress = $warning;
+
+ }
+
+ my %invoice_data = (
+ 'company_name' => scalar( $conf->config('company_name') ),
+ 'company_address' => join("\n", $conf->config('company_address') ). "\n",
+ 'custnum' => $self->custnum,
+ 'invnum' => $self->invnum,
+ 'date' => time2str($date_format, $self->_date),
+ 'today' => time2str('%b %o, %Y', $today),
+ 'agent' => &$escape_function($cust_main->agent->agent),
+ 'payname' => &$escape_function($cust_main->payname),
+ 'company' => &$escape_function($cust_main->company),
+ 'address1' => &$escape_function($cust_main->address1),
+ 'address2' => &$escape_function($cust_main->address2),
+ 'city' => &$escape_function($cust_main->city),
+ 'state' => &$escape_function($cust_main->state),
+ 'zip' => &$escape_function($cust_main->zip),
+ 'returnaddress' => $returnaddress,
+ 'quantity' => 1,
+ 'terms' => $self->terms,
+ 'template' => $params{'template'},
+ #'notes' => join("\n", $conf->config('invoice_latexnotes') ),
+ # better hang on to conf_dir for a while
+ 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
+ 'page' => 1,
+ 'total_pages' => 1,
+ );
+
+ $invoice_data{'cid'} = $params{'cid'}
+ if $params{'cid'};
+
+ my $countrydefault = $conf->config('countrydefault') || 'US';
+ if ( $cust_main->country eq $countrydefault ) {
+ $invoice_data{'country'} = '';
+ } else {
+ $invoice_data{'country'} = &$escape_function(code2country($cust_main->country));
+ }
+
+ my @address = ();
+ $invoice_data{'address'} = \@address;
+ push @address,
+ $cust_main->payname.
+ ( ( $cust_main->payby eq 'BILL' ) && $cust_main->payinfo
+ ? " (P.O. #". $cust_main->payinfo. ")"
+ : ''
+ )
+ ;
+ push @address, $cust_main->company
+ if $cust_main->company;
+ push @address, $cust_main->address1;
+ push @address, $cust_main->address2
+ if $cust_main->address2;
+ push @address,
+ $cust_main->city. ", ". $cust_main->state. " ". $cust_main->zip;
+ push @address, $invoice_data{'country'}
+ if $invoice_data{'country'};
+ push @address, ''
+ while (scalar(@address) < 5);
+
+ #do variable substitution in notes, footer, smallfooter
+ foreach my $include (qw( notes footer smallfooter )) {
+
+ my @inc_src = $conf->config_orbase("invoice_latex$include", $template );
+ my $convert_map = $convert_maps{$format}{$include};
+
+ if (
+ defined( $conf->config_orbase("invoice_${format}$include", $template) )
+ && length( $conf->config_orbase('invoice_${format}$include', $template) )
+ ) {
+ @inc_src = $conf->config_orbase("invoice_${format}$include", $template );
+ } else {
+ @inc_src =
+ map { s/\[@--/$delimiters{$format}[0]/g;
+ s/--@]/$delimiters{$format}[1]/g;
+ $_;
+ }
+ &$convert_map(
+ $conf->config_orbase("invoice_latex$include", $template )
+ );
+ }
+
+ my $inc_tt = new Text::Template (
+ TYPE => 'ARRAY',
+ SOURCE => [ map "$_\n", @inc_src ],
+ DELIMITERS => $delimiters{$format},
+ ) or die "can't create new Text::Template object: $Text::Template::ERROR";