use Mail::Internet 1.44;
use Mail::Header;
use Text::Template;
+use File::Temp 0.14;
+use String::ShellQuote;
use FS::UID qw( datasrc );
use FS::Record qw( qsearch qsearchs );
use FS::cust_main;
$balance;
}
-=item send
+=item send [ TEMPLATENAME [ , AGENTNUM ] ]
Sends this invoice to the destinations configured for this customer: send
emails or print. See L<FS::cust_main_invoice>.
+TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
+
+AGENTNUM, if specified, means that this invoice will only be sent for customers
+of the specified agent.
+
=cut
sub send {
- my($self,$template) = @_;
+ my $self = shift;
+ my $template = scalar(@_) ? shift : '';
+ return '' if scalar(@_) && $_[0] && $self->cust_main->agentnum ne shift;
+
my @print_text = $self->print_text('', $template);
my @invoicing_list = $self->cust_main->invoicing_list;
$!=0;
$message->smtpsend( Host => $smtpmachine )
or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or return "(customer # ". $self->custnum. ") can't send invoice email".
- " to ". join(', ', grep { $_ ne 'POST' } @invoicing_list ).
- " via server $smtpmachine with SMTP: $!";
+ or die "(customer # ". $self->custnum. ") can't send invoice email".
+ " to ". join(', ', grep { $_ ne 'POST' } @invoicing_list ).
+ " via server $smtpmachine with SMTP: $!\n";
}
if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal
open(LPR, "|$lpr")
- or return "Can't open pipe to $lpr: $!";
+ or die "Can't open pipe to $lpr: $!\n";
print LPR @print_text;
close LPR
- or return $! ? "Error closing $lpr: $!"
- : "Exit status $? from $lpr";
+ or die $! ? "Error closing $lpr: $!\n"
+ : "Exit status $? from $lpr\n";
}
'';
} );
my $error = $cust_pay->insert;
if ( $error ) {
- # gah, even with transactions.
- my $e = 'WARNING: Card/ACH debited but database not updated - '.
- 'error applying payment, invnum #' . $self->invnum.
- " ($processor): $error";
- warn $e;
- return $e;
- } else {
- return '';
+ $cust_pay->invnum(''); #try again with no specific invnum
+ my $error2 = $cust_pay->insert;
+ if ( $error2 ) {
+ # gah, even with transactions.
+ my $e = 'WARNING: Card/ACH debited but database not updated - '.
+ "error inserting payment ($processor): $error2".
+ ' (previously tried insert with invnum #' . $self->invnum.
+ ": $error )";
+ warn $e;
+ return $e;
+ }
}
+ return ''; #no error
+
#} elsif ( $options{'report_badcard'} ) {
} else {
'';
}
+sub _agent_template {
+ my $self = shift;
+
+ my $cust_bill_event = qsearchs( 'part_bill_event',
+ {
+ 'payby' => $self->cust_main->payby,
+ 'plan' => 'send_agent',
+ 'eventcode' => { 'op' => 'LIKE',
+ 'value' => '_%, '. $self->cust_main->agentnum. ');' },
+ },
+ '',
+ 'ORDER BY seconds LIMIT 1'
+ );
+
+ return '' unless $cust_bill_event;
+
+ if ( $cust_bill_event->eventcode =~ /\(\s*'(.*)'\s*,\s*(\d+)\s*\)\;$/ ) {
+ return $1;
+ } else {
+ warn "can't parse eventcode for agent-specific invoice template";
+ return '';
+ }
+
+}
+
=item print_text [ TIME [ , TEMPLATE ] ]
Returns an text invoice, as a list of lines.
sprintf("%10.2f", $balance_due ) ];
#create the template
+ $template ||= $self->_agent_template;
my $templatefile = 'invoice_template';
- $templatefile .= "_$template" if $template;
+ $templatefile .= "_$template" if length($template);
my @invoice_template = $conf->config($templatefile)
- or die "cannot load config file $templatefile";
+ or die "cannot load config file $templatefile";
$invoice_lines = 0;
my $wasfunc = 0;
foreach ( grep /invoice_lines\(\d*\)/, @invoice_template ) { #kludgy
@buf = ();
#create the template
+ $template ||= $self->_agent_template;
my $templatefile = 'invoice_latex';
- $templatefile .= "_$template" if $template;
+ my $suffix = length($template) ? "_$template" : '';
+ $templatefile .= $suffix;
my @invoice_template = $conf->config($templatefile)
or die "cannot load config file $templatefile";
$invoice_data{'notes'} =
join("\n",
map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
- $conf->config('invoice_latexnotes')
+ $conf->config_orbase('invoice_latexnotes', $suffix)
);
$invoice_data{'footer'} =~ s/\n+$//;
$var;
}
- my $dir = '/tmp'; #! /usr/local/etc/freeside/invoices.datasrc/
- my $unique = int(rand(2**31)); #UGH... use File::Temp or something
-
- chdir($dir);
- my $file = $self->invnum. ".$unique";
-
- open(TEX,">$file.tex") or die "can't open $file.tex: $!\n";
- print TEX join("\n", @filled_in ), "\n";
- close TEX;
+ my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+ my $fh = new File::Temp( TEMPLATE => 'invoice.'. $self->invnum. '.XXXXXXXX',
+ DIR => $dir,
+ SUFFIX => '.tex',
+ UNLINK => 0,
+ ) or die "can't open temp file: $!\n";
+ print $fh join("\n", @filled_in ), "\n";
+ close $fh;
- return $file;
+ $fh->filename =~ /^(.*).tex$/ or die "unparsable filename: ". $fh->filename;
+ return $1;
}
my $file = $self->print_latex(@_);
- #error checking!!
- system('pslatex', "$file.tex");
- system('pslatex', "$file.tex");
- system('dvips', '-q', '-t', 'letter', "$file.dvi", '-o', "$file.ps" );
+ my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+ chdir($dir);
+
+ system("pslatex $file.tex >/dev/null 2>&1") == 0
+ or die "pslatex $file.tex failed: $!";
+ system("pslatex $file.tex >/dev/null 2>&1") == 0
+ or die "pslatex $file.tex failed: $!";
+
+ system('dvips', '-q', '-t', 'letter', "$file.dvi", '-o', "$file.ps" ) == 0
+ or die "dvips failed: $!";
open(POSTSCRIPT, "<$file.ps")
- or die "can't open $file.ps (probable error in LaTeX template): $!\n";
+ or die "can't open $file.ps: $! (error in LaTeX template?)\n";
unlink("$file.dvi", "$file.log", "$file.aux", "$file.ps", "$file.tex");
my $file = $self->print_latex(@_);
+ my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
+ chdir($dir);
+
#system('pdflatex', "$file.tex");
#system('pdflatex', "$file.tex");
#! LaTeX Error: Unknown graphics extension: .eps.
- #error checking!!
- system('pslatex', "$file.tex");
- system('pslatex', "$file.tex");
+ system("pslatex $file.tex >/dev/null 2>&1") == 0
+ or die "pslatex $file.tex failed: $!";
+ system("pslatex $file.tex >/dev/null 2>&1") == 0
+ or die "pslatex $file.tex failed: $!";
#system('dvipdf', "$file.dvi", "$file.pdf" );
- system("dvips -q -t letter -f $file.dvi | gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$file.pdf -c save pop -");
+ my $sfile = shell_quote $file;
+ system(
+ "dvips -q -t letter -f $sfile.dvi ".
+ "| gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$sfile.pdf ".
+ " -c save pop -"
+ ) == 0
+ or die "dvips | gs failed: $!";
open(PDF, "<$file.pdf")
- or die "can't open $file.pdf (probably error in LaTeX tempalte: $!\n";
+ or die "can't open $file.pdf: $! (error in LaTeX template?)\n";
unlink("$file.dvi", "$file.log", "$file.aux", "$file.pdf", "$file.tex");
#'description' => 'Credit ref\#'. $_->crednum.
# " (". time2str("%x",$_->cust_credit->_date) .")".
# $reason,
- 'description' => 'Credit applied'.
+ 'description' => 'Credit applied '.
time2str("%x",$_->cust_credit->_date). $reason,
'amount' => sprintf("%10.2f",$_->amount),
};
print_text formatting (and some logic :/) is in source, but needs to be
slurped in from a file. Also number of lines ($=).
-missing print_ps for a nice postscript copy (maybe HylaFAX-cover-page-style
-or something similar so the look can be completely customized?)
-
=head1 SEE ALSO
L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill_pay>, L<FS::cust_pay>,