diff options
| -rw-r--r-- | FS/FS/ClientAPI/MyAccount.pm | 2 | ||||
| -rw-r--r-- | FS/FS/Conf.pm | 7 | ||||
| -rw-r--r-- | FS/FS/Misc.pm | 76 | ||||
| -rw-r--r-- | FS/FS/cust_bill.pm | 46 | ||||
| -rw-r--r-- | FS/FS/cust_main.pm | 5 | ||||
| -rw-r--r-- | FS/FS/cust_main_invoice.pm | 6 | ||||
| -rw-r--r-- | FS/FS/cust_pay.pm | 4 | ||||
| -rw-r--r-- | FS/FS/cust_pkg.pm | 2 | ||||
| -rw-r--r-- | FS/FS/part_export/http.pm | 2 | ||||
| -rw-r--r-- | FS/FS/part_export/infostreet.pm | 2 | ||||
| -rw-r--r-- | FS/FS/part_export/shellcommands.pm | 2 | ||||
| -rw-r--r-- | FS/FS/svc_acct.pm | 2 | ||||
| -rw-r--r-- | htetc/handler.pl | 2 | ||||
| -rw-r--r-- | httemplate/docs/install.html | 1 | ||||
| -rwxr-xr-x | httemplate/edit/cust_main.cgi | 7 | ||||
| -rwxr-xr-x | httemplate/edit/process/cust_main.cgi | 1 | ||||
| -rwxr-xr-x | httemplate/misc/fax-invoice.cgi | 25 | ||||
| -rwxr-xr-x | httemplate/view/cust_bill.cgi | 6 | ||||
| -rw-r--r-- | httemplate/view/cust_main/billing.html | 8 | ||||
| -rw-r--r-- | httemplate/view/cust_main/tickets.html | 2 | 
20 files changed, 176 insertions, 32 deletions
| diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index d18a6e4ff..478973396 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -131,7 +131,7 @@ sub customer_info {      }      $return{'invoicing_list'} = -      join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ); +      join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list );      $return{'postal_invoicing'} =        0 < ( grep { $_ eq 'POST' } $cust_main->invoicing_list ); diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index e21e58322..4a9762672 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1433,6 +1433,13 @@ httemplate/docs/config.html      'select_enum' => [ 'Cache::SharedMemoryCache', 'Cache::FileCache', ], # '_Database' ],    }, +  { +    'key'         => 'hylafax', +    'section'     => '', +    'description' => 'Options for a HylaFAX server to enable the FAX invoice destination.  They should be in the form of a space separated list of arguments to the Fax::Hylafax::Client::sendfax subroutine.  You probably shouldn\'t override things like \'docfile\'.  *Note* Only supported when using typeset invoices (see the invoice_latex configuration option).', +    'type'        => [qw( checkbox textarea )], +  }, +  );  1; diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm index 71fe7e712..a7cd47176 100644 --- a/FS/FS/Misc.pm +++ b/FS/FS/Misc.pm @@ -5,7 +5,7 @@ use vars qw ( @ISA @EXPORT_OK );  use Exporter;  @ISA = qw( Exporter ); -@EXPORT_OK = qw( send_email ); +@EXPORT_OK = qw( send_email send_fax );  =head1 NAME @@ -50,6 +50,7 @@ use Date::Format;  use Mail::Header;  use Mail::Internet 1.44;  use MIME::Entity; +use Fax::Hylafax::Client;  use FS::UID;  FS::UID->install_callback( sub { @@ -111,6 +112,77 @@ sub send_email {  } +=item send_fax OPTION => VALUE ... + +Options: + +I<dialstring> - (required) 10-digit phone number w/ area code + +I<docdata> - (required) Array ref containing PostScript or TIFF Class F document + +-or- + +I<docfile> - (required) Filename of PostScript TIFF Class F document + +...any other options will be passed to L<Fax::Hylafax::Client::sendfax> + + +=cut + +sub send_fax { + +  my %options = @_; + +  die 'HylaFAX support has not been configured.' +    unless $conf->exists('hylafax'); + +  my %hylafax_opts = map { split /\s+/ } $conf->config('hylafax'); + +  die 'Called send_fax without a \'dialstring\'.' +    unless exists($options{'dialstring'}); + +  if (exists($options{'docdata'}) and ref($options{'docdata'}) eq 'ARRAY') { +      my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc; +      my $fh = new File::Temp( +        TEMPLATE => 'faxdoc.'. $options{'dialstring'} . '.XXXXXXXX', +        DIR      => $dir, +        UNLINK   => 0, +      ) or die "can't open temp file: $!\n"; + +      $options{docfile} = $fh->filename; + +      print $fh @{$options{'docdata'}}; +      close $fh; + +      delete $options{'docdata'}; +  } + +  die 'Called send_fax without a \'docfile\' or \'docdata\'.' +    unless exists($options{'docfile'}); + +  #FIXME: Need to send canonical dialstring to HylaFAX, but this only +  #       works in the US. + +  $options{'dialstring'} =~ s/[^\d\+]//g; +  if ($options{'dialstring'} =~ /^\d{10}$/) { +    $options{dialstring} = '+1' . $options{'dialstring'}; +  } else { +    return 'Invalid dialstring ' . $options{'dialstring'} . '.'; +  } + +  my $faxjob = &Fax::Hylafax::Client::sendfax(%options, %hylafax_opts); + +  if ($faxjob->success) { +    warn "Successfully queued fax to '$options{dialstring}' with jobid " . +            $faxjob->jobid; +  } else { +    return 'Error while sending FAX: ' . $faxjob->trace; +  } + +  return ''; + +} +  package Mail::Internet;  use Mail::Address; @@ -191,6 +263,8 @@ This package exists.  L<FS::UID>, L<FS::CGI>, L<FS::Record>, the base documentation. +L<Fax::Hylafax::Client> +  =cut  1; diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index e70bb3247..10b4928cb 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -9,7 +9,7 @@ use File::Temp 0.14;  use String::ShellQuote;  use FS::UID qw( datasrc );  use FS::Record qw( qsearch qsearchs ); -use FS::Misc qw( send_email ); +use FS::Misc qw( send_email send_fax );  use FS::cust_main;  use FS::cust_bill_pkg;  use FS::cust_credit; @@ -378,7 +378,7 @@ sub generate_email {    if (ref($args{'to'} eq 'ARRAY')) {      @invoicing_list = @{$args{'to'}};    } else { -    @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list; +    @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $self->cust_main->invoicing_list;    }    return ( @@ -418,7 +418,7 @@ sub send {    my @print_text = $self->print_text('', $template);    my @invoicing_list = $self->cust_main->invoicing_list; -  if ( grep { $_ ne 'POST' } @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; @@ -426,7 +426,7 @@ sub send {      my $error = send_email(        $self->generate_email(          'from'   => $invoice_from, -        'to'     => [ grep { $_ ne 'POST' } @invoicing_list ], +        'to'     => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ],  	'print_text' => [ @print_text ],        )      ); @@ -435,16 +435,34 @@ sub send {    } -  if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal -    @print_text = $self->print_ps('', $template) -      if $conf->config('invoice_latex'); -    my $lpr = $conf->config('lpr'); -    open(LPR, "|$lpr") -      or die "Can't open pipe to $lpr: $!\n"; -    print LPR @print_text; -    close LPR -      or die $! ? "Error closing $lpr: $!\n" -                : "Exit status $? from $lpr\n"; +  if ( grep { $_ =~ /^(POST|FAX)$/ } @invoicing_list ) { +    my $lpr_data; +    if ($conf->config('invoice_latex')) { +      $lpr_data = [ $self->print_ps('', $template) ]; +    } else { +      $lpr_data = \@print_text; +    } + +    if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal +      my $lpr = $conf->config('lpr'); +      open(LPR, "|$lpr") +        or die "Can't open pipe to $lpr: $!\n"; +      print LPR @{$lpr_data}; +      close LPR +        or die $! ? "Error closing $lpr: $!\n" +                  : "Exit status $? from $lpr\n"; +    } + +    if ( grep { $_ eq 'FAX' } @invoicing_list ) { #fax +      unless ($conf->exists('invoice_latex')) { +	die 'FAX invoice destination not supported with plain text invoices.' +      } +      my $dialstring = $self->cust_main->getfield('fax'); +      #Check $dialstring? +      my $error = send_fax(docdata => $lpr_data, dialstring => $dialstring); +      die $error if $error; +    } +    }    ''; diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 8246b93f5..4fcb22681 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -2655,6 +2655,11 @@ is an error, returns the error, otherwise returns false.  sub check_invoicing_list {    my( $self, $arrayref ) = @_;    foreach my $address ( @{$arrayref} ) { + +    if ($address eq 'FAX' and $self->getfield('fax') eq '') { +      return 'Can\'t add FAX invoice destination with a blank FAX number.'; +    } +      my $cust_main_invoice = new FS::cust_main_invoice ( {        'custnum' => $self->custnum,        'dest'    => $address, diff --git a/FS/FS/cust_main_invoice.pm b/FS/FS/cust_main_invoice.pm index 3cabd3a64..03863b83f 100644 --- a/FS/FS/cust_main_invoice.pm +++ b/FS/FS/cust_main_invoice.pm @@ -43,7 +43,7 @@ FS::Record.  The following fields are currently supported:  =item custnum - customer (see L<FS::cust_main>) -=item dest - Invoice destination: If numeric, a svcnum (see L<FS::svc_acct>), if string, a literal email address, or `POST' to enable mailing (the default if no cust_main_invoice records exist) +=item dest - Invoice destination: If numeric, a svcnum (see L<FS::svc_acct>), if string, a literal email address, `POST' to enable mailing (the default if no cust_main_invoice records exist), or `FAX' to enable faxing via a HylaFAX server.  =back @@ -127,7 +127,7 @@ sub checkdest {    my $error = $self->ut_text('dest');    return $error if $error; -  if ( $self->dest eq 'POST' ) { +  if ( $self->dest =~ /^(POST|FAX)$/ ) {      #contemplate our navel    } elsif ( $self->dest =~ /^(\d+)$/ ) {      return "Unknown local account (specified by svcnum: ". $self->dest. ")" @@ -144,7 +144,7 @@ sub checkdest {  =item address -Returns the literal email address for this record (or `POST'). +Returns the literal email address for this record (or `POST' or `FAX').  =cut diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 80d4a140b..fa97ba9eb 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -167,7 +167,7 @@ sub insert {    #my $cust_main = $self->cust_main;    if ( $conf->exists('payment_receipt_email') -       && grep { $_ ne 'POST' } $cust_main->invoicing_list +       && grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list    ) {      my $receipt_template = new Text::Template ( @@ -178,7 +178,7 @@ sub insert {        return '';      }; -    my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list; +    my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;      my $payby = $self->payby;      my $payinfo = $self->payinfo; diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index e3724a3ef..f5c1de3e2 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -423,7 +423,7 @@ sub cancel {    $dbh->commit or die $dbh->errstr if $oldAutoCommit;    my $conf = new FS::Conf; -  my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list; +  my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $self->cust_main->invoicing_list;    if ( !$options{'quiet'} && $conf->exists('emailcancel') && @invoicing_list ) {      my $conf = new FS::Conf;      my $error = send_email( diff --git a/FS/FS/part_export/http.pm b/FS/FS/part_export/http.pm index 0be2a0f36..55d832966 100644 --- a/FS/FS/part_export/http.pm +++ b/FS/FS/part_export/http.pm @@ -18,7 +18,7 @@ tie my %options, 'Tie::IxHash',      type    => 'textarea',      default => join("\n",        'DomainName $svc_x->domain', -      'Email ( grep { $_ ne "POST" } $svc_x->cust_svc->cust_pkg->cust_main->invoicing_list)[0]', +      'Email ( grep { $_ !~ /^(POST|FAX)$/ } $svc_x->cust_svc->cust_pkg->cust_main->invoicing_list)[0]',        'test 1',        'reseller $svc_x->cust_svc->cust_pkg->part_pkg->pkg =~ /reseller/i',      ), diff --git a/FS/FS/part_export/infostreet.pm b/FS/FS/part_export/infostreet.pm index 309e7ce6f..ef16c7c54 100644 --- a/FS/FS/part_export/infostreet.pm +++ b/FS/FS/part_export/infostreet.pm @@ -67,7 +67,7 @@ sub _export_insert {      $_ => $cust_main->getfield( $infostreet2cust_main{$_} );    } keys %infostreet2cust_main ); -  my @emails = grep { $_ ne 'POST' } $cust_main->invoicing_list; +  my @emails = grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;    $contact_info{'email'} = $emails[0] if @emails;    #this one is kinda noment-specific diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm index 4f201cf9c..665ec473f 100644 --- a/FS/FS/part_export/shellcommands.pm +++ b/FS/FS/part_export/shellcommands.pm @@ -216,7 +216,7 @@ sub _export_command {    my $cust_pkg = $svc_acct->cust_svc->cust_pkg;    if ( $cust_pkg ) { -    $email = ( grep { $_ ne 'POST' } $cust_pkg->cust_main->invoicing_list )[0]; +    $email = ( grep { $_ !~ /^(POST|FAX)$/ } $cust_pkg->cust_main->invoicing_list )[0];    } else {      $email = '';    } diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 35596e34b..109ea1d45 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -296,7 +296,7 @@ sub insert {      #welcome email      my $to = '';      if ( $welcome_template && $cust_pkg ) { -      my $to = join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ); +      my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list );        if ( $to ) {          my $wqueue = new FS::queue {            'svcnum' => $self->svcnum, diff --git a/htetc/handler.pl b/htetc/handler.pl index c144eca1a..b44e3f2d4 100644 --- a/htetc/handler.pl +++ b/htetc/handler.pl @@ -118,7 +118,7 @@ sub handler                       small_custview myexit http_header);        use FS::UI::Web;        use FS::Msgcat qw(gettext geterror); -      use FS::Misc qw( send_email ); +      use FS::Misc qw( send_email send_fax );        use FS::Report::Table::Monthly;        use FS::TicketSystem; diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html index eaebcde2b..10c51e77d 100644 --- a/httemplate/docs/install.html +++ b/httemplate/docs/install.html @@ -68,6 +68,7 @@ Before installing, you need:        <li><a href="http://search.cpan.org/dist/Frontier-RPC">Frontier::RPC (Frontier::RPC2)</a>        <li><a href="http://search.cpan.org/search?mode=module&query=MIME::Entity">MIME::Entity (MIME-tools)</a>  <!--      <li><a href="http://search.cpan.org/dist/Crypt-YAPassGen">Crypt::YAPassGen</a> --> +      <li><a href="http://search.cpan.org/search?mode=module&query=MIME::Entity">Fax::Hylafax::Client</a> <i>(Required if using FAX invoice destinations</i>        <li><a href="http://search.cpan.org/dist/ApacheDBI">Apache::DBI</a> <i>(optional but recommended for better webinterface performance)</i>      </ul>  </ul> diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 3910b4b84..61468f382 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -302,8 +302,11 @@ if ( $payby_default eq 'HIDE' ) {    print qq! CHECKED!      if ( ! @invoicing_list && ! $conf->exists('disablepostalinvoicedefault') )         || grep { $_ eq 'POST' } @invoicing_list; -  print qq!>Postal mail invoice</TD></TR>!; -  my $invoicing_list = join(', ', grep { $_ ne 'POST' } @invoicing_list ); +  print qq!>Postal mail invoice</TD></TR><TR><TD>!; +  print qq!<INPUT TYPE="checkbox" NAME="invoicing_list_FAX" VALUE="FAX"!; +  print qq! CHECKED! if (grep { $_ eq 'FAX' } @invoicing_list); +  print qq!>FAX invoice</TD></TR>!; +  my $invoicing_list = join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list );    print qq!<TR><TD>Email invoice <INPUT TYPE="text" NAME="invoicing_list" VALUE="$invoicing_list"></TD></TR>!;    print "<TR><TD>Billing type</TD></TR>", diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi index a1d36986d..d2773a60e 100755 --- a/httemplate/edit/process/cust_main.cgi +++ b/httemplate/edit/process/cust_main.cgi @@ -25,6 +25,7 @@ if ( $payby ) {  my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') );  push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST'); +push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX');  $cgi->param('invoicing_list', join(',', @invoicing_list) ); diff --git a/httemplate/misc/fax-invoice.cgi b/httemplate/misc/fax-invoice.cgi new file mode 100755 index 000000000..46b2a1721 --- /dev/null +++ b/httemplate/misc/fax-invoice.cgi @@ -0,0 +1,25 @@ +<% + +my $conf = new FS::Conf; +my $lpr = $conf->config('lpr'); + +#untaint invnum +my($query) = $cgi->keywords; +$query =~ /^(\d*)$/; +my $invnum = $1; +my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum}); +die "Can't find invoice!\n" unless $cust_bill; + + +my $error = &FS::Misc::send_fax( +  dialstring => $cust_bill->cust_main->getfield('fax'), +  docdata       => [ $cust_bill->print_ps ], +); + +die $error if $error; + +my $custnum = $cust_bill->getfield('custnum'); + +print $cgi->redirect("${p}view/cust_main.cgi?$custnum"); + +%> diff --git a/httemplate/view/cust_bill.cgi b/httemplate/view/cust_bill.cgi index ca0612d09..c217cc389 100755 --- a/httemplate/view/cust_bill.cgi +++ b/httemplate/view/cust_bill.cgi @@ -7,6 +7,8 @@ $query =~ /^((.+)-)?(\d+)$/;  my $templatename = $2;  my $invnum = $3; +my $conf = new FS::Conf; +  my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});  die "Invoice #$invnum not found!" unless $cust_bill;  my $custnum = $cust_bill->getfield('custnum'); @@ -27,9 +29,11 @@ if ( grep { $_ ne 'POST' } $cust_bill->cust_main->invoicing_list ) {          qq!Re-email this invoice</A>!;  } +print qq! | <A HREF="${p}misc/fax-invoice.cgi?$invnum">Refax this invoice</A>! +  if ($conf->exists('hylafax')); +  print '<BR><BR>'; -my $conf = new FS::Conf;  if ( $conf->exists('invoice_latex') ) {    my $link = "${p}view/cust_bill-pdf.cgi?";    $link .= "$templatename-" if $templatename; diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 18a203bd6..561fff992 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -17,9 +17,15 @@ Billing information    </TD>  </TR>  <TR> +  <TD ALIGN="right">FAX invoices</TD> +  <TD BGCOLOR="#ffffff"> +    <%= ( grep { $_ eq 'FAX' } @invoicing_list ) ? 'yes' : 'no' %> +  </TD> +</TR> +<TR>    <TD ALIGN="right">Email invoices</TD>    <TD BGCOLOR="#ffffff"> -    <%= join(', ', grep { $_ ne 'POST' } @invoicing_list ) || 'no' %> +    <%= join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || 'no' %>    </TD>  </TR>  <TR> diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index d6ddfa64c..ea70d701d 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -30,7 +30,7 @@  Highest priority tickets  (<A HREF="<%= FS::TicketSystem->href_customer_tickets($cust_main->custnum) %>">View all tickets for this customer</A>) -(<A HREF="<%= FS::TicketSystem->href_new_ticket($cust_main->custnum, join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ) ) %>">New ticket for this customer</A>) +(<A HREF="<%= FS::TicketSystem->href_new_ticket($cust_main->custnum, join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ) ) %>">New ticket for this customer</A>)  <%= table() %>  <TR>    <TH>#</TH> | 
