per-agent invoice PDF batches, RT#13727
authorivan <ivan>
Wed, 20 Jul 2011 18:34:19 +0000 (18:34 +0000)
committerivan <ivan>
Wed, 20 Jul 2011 18:34:19 +0000 (18:34 +0000)
FS/FS/AccessRight.pm
FS/FS/Conf.pm
FS/FS/Schema.pm
FS/FS/bill_batch.pm
FS/FS/cust_bill.pm
FS/FS/part_event/Action/cust_bill_print.pm [new file with mode: 0644]
FS/FS/part_event/Action/cust_bill_print_pdf.pm [new file with mode: 0644]
httemplate/elements/menu.html
httemplate/search/bill_batch.cgi

index 2f6f531..458f969 100644 (file)
@@ -272,9 +272,11 @@ tie my %rights, 'Tie::IxHash',
   'Miscellaneous rights' => [
     { rightname=>'Job queue', global=>1 },
     { rightname=>'Time queue', global=>1 },
   'Miscellaneous rights' => [
     { rightname=>'Job queue', global=>1 },
     { rightname=>'Time queue', global=>1 },
-    { rightname=>'Process batches', global=>1 },
-    { rightname=>'Reprocess batches', global=>1 },
-    { rightname=>'Redownload resolved batches', global=>1 },
+    { rightname=>'Process batches', global=>1 }, #Process payment batches
+    { rightname=>'Reprocess batches', global=>1 }, #Reprocess payment batches
+    { rightname=>'Redownload resolved batches', global=>1 }, #Redownload resolved payment batches
+    { rightname=>'Process invoice batches', },
+    { rightname=>'Process global invoice batches', global=>1 },
     { rightname=>'Import', global=>1 }, #some of these are ag-virt'ed now?  give em their own ACLs
     { rightname=>'Export', global=>1 },
     { rightname=> 'Edit rating data', desc=>'Delete CDRs', global=>1 },
     { rightname=>'Import', global=>1 }, #some of these are ag-virt'ed now?  give em their own ACLs
     { rightname=>'Export', global=>1 },
     { rightname=> 'Edit rating data', desc=>'Delete CDRs', global=>1 },
index 7743322..9953ea5 100644 (file)
@@ -1258,7 +1258,14 @@ and customer address. Include units.',
   {
     'key'         => 'invoice_print_pdf',
     'section'     => 'invoicing',
   {
     'key'         => 'invoice_print_pdf',
     'section'     => 'invoicing',
-    'description' => 'Store postal invoices for download in PDF format rather than printing them directly.',
+    'description' => 'For all invoice print operations, store postal invoices for download in PDF format rather than printing them directly.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'invoice_print_pdf-spoolagent',
+    'section'     => 'invoicing',
+    'description' => 'Store postal invoices PDF downloads in per-agent spools.',
     'type'        => 'checkbox',
   },
 
     'type'        => 'checkbox',
   },
 
index 168fae0..6fde8b1 100644 (file)
@@ -3339,13 +3339,14 @@ sub tables_hashref {
 
     'bill_batch' => {
       'columns' => [
 
     'bill_batch' => {
       'columns' => [
-        'batchnum',         'serial',     '', '', '', '',
-        'status',             'char', 'NULL','1', '', '',
-        'pdf',                'blob', 'NULL', '', '', '',
+        'batchnum',         'serial',     '',  '', '', '',
+        'agentnum',            'int', 'NULL',  '', '', '',
+        'status',             'char', 'NULL', '1', '', '',
+        'pdf',                'blob', 'NULL',  '', '', '',
       ],
       'primary_key' => 'batchnum',
       'unique'      => [],
       ],
       'primary_key' => 'batchnum',
       'unique'      => [],
-      'index'       => [],
+      'index'       => [ ['agentnum'] ],
     },
 
     'cust_bill_batch' => {
     },
 
     'cust_bill_batch' => {
index 3afe209..ec5c194 100644 (file)
@@ -2,9 +2,11 @@ package FS::bill_batch;
 
 use strict;
 use vars qw( @ISA $me $DEBUG );
 
 use strict;
 use vars qw( @ISA $me $DEBUG );
+use CAM::PDF;
+use FS::Conf;
 use FS::Record qw( qsearch qsearchs dbh );
 use FS::Record qw( qsearch qsearchs dbh );
+use FS::agent;
 use FS::cust_bill_batch;
 use FS::cust_bill_batch;
-use CAM::PDF;
 
 @ISA = qw( FS::Record );
 $me = '[ FS::bill_batch ]';
 
 @ISA = qw( FS::Record );
 $me = '[ FS::bill_batch ]';
@@ -37,6 +39,8 @@ inherits from FS::Record.  The following fields are currently supported:
 
 =item batchnum - primary key
 
 
 =item batchnum - primary key
 
+=item agentnum - empty for global batches or agent (see L<FS::agent>)
+
 =item status - either 'O' (open) or 'R' (resolved/closed).
 
 =item pdf - blob field for temporarily storing the invoice as a PDF.
 =item status - either 'O' (open) or 'R' (resolved/closed).
 
 =item pdf - blob field for temporarily storing the invoice as a PDF.
@@ -96,26 +100,38 @@ sub close {
   return $self->replace;
 }
 
   return $self->replace;
 }
 
-=back
+sub check {
+  my $self = shift;
+
+  my $error =
+       $self->ut_numbern('batchnum')
+    || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
+    || $self->ut_enum('status', [ 'O', 'R' ] )
+  ;
+  return $error if $error;
 
 
-=head1 CLASS METHODS
+  $self->SUPER::check;
+}
 
 
-=item get_open_batch
+=item agent
 
 
-Returns the currently open batch.  There should only be one at a time.
+Returns the agent (see L<FS::agent>) for this invoice batch.
 
 =cut
 
 
 =cut
 
-sub get_open_batch {
-  my $class = shift;
-  my $batch = qsearchs('bill_batch', { status => 'O' });
-  return $batch if $batch;
-  $batch = FS::bill_batch->new({status => 'O'});
-  my $error = $batch->insert;
-  die $error if $error;
-  return $batch;
+sub agent {
+  my $self = shift;
+  qsearchs( 'agent', { 'agentnum' => $self->agentnum } );
 }
 
 }
 
+=back
+
+=head1 SUBROUTINES
+
+=item process_print_pdf
+
+=cut
+
 use Storable 'thaw';
 use Data::Dumper;
 use MIME::Base64;
 use Storable 'thaw';
 use Data::Dumper;
 use MIME::Base64;
@@ -134,7 +150,6 @@ sub process_print_pdf {
   die $error if $error;
 }
 
   die $error if $error;
 }
 
-
 =back
 
 =head1 BUGS
 =back
 
 =head1 BUGS
index 6e4eba4..7669479 100644 (file)
@@ -1520,14 +1520,36 @@ isn't an open batch, one will be created.
 
 sub batch_invoice {
   my ($self, $opt) = @_;
 
 sub batch_invoice {
   my ($self, $opt) = @_;
-  my $batch = FS::bill_batch->get_open_batch;
+  my $bill_batch = $self->get_open_bill_batch;
   my $cust_bill_batch = FS::cust_bill_batch->new({
   my $cust_bill_batch = FS::cust_bill_batch->new({
-      batchnum => $batch->batchnum,
+      batchnum => $bill_batch->batchnum,
       invnum   => $self->invnum,
   });
   return $cust_bill_batch->insert($opt);
 }
 
       invnum   => $self->invnum,
   });
   return $cust_bill_batch->insert($opt);
 }
 
+=item get_open_batch
+
+Returns the currently open batch as an FS::bill_batch object, creating a new
+one if necessary.  (A per-agent batch if invoice_print_pdf-spoolagent is
+enabled)
+
+=cut
+
+sub get_open_bill_batch {
+  my $self = shift;
+  my $hashref = { status => 'O' };
+  $hashref->{'agentnum'} = $conf->exists('invoice_print_pdf-spoolagent')
+                             ? $self->cust_main->agentnum
+                             : '';
+  my $batch = qsearchs('bill_batch', $hashref);
+  return $batch if $batch;
+  $batch = FS::bill_batch->new($hashref);
+  my $error = $batch->insert;
+  die $error if $error;
+  return $batch;
+}
+
 =item ftp_invoice [ TEMPLATENAME ] 
 
 Sends this invoice data via FTP.
 =item ftp_invoice [ TEMPLATENAME ] 
 
 Sends this invoice data via FTP.
diff --git a/FS/FS/part_event/Action/cust_bill_print.pm b/FS/FS/part_event/Action/cust_bill_print.pm
new file mode 100644 (file)
index 0000000..6b3e6f4
--- /dev/null
@@ -0,0 +1,23 @@
+package FS::part_event::Action::cust_bill_print;
+
+use strict;
+use base qw( FS::part_event::Action );
+
+sub description { 'Send invoice (print only)'; }
+
+sub eventtable_hashref {
+  { 'cust_bill' => 1 };
+}
+
+sub default_weight { 51; }
+
+sub do_action {
+  my( $self, $cust_bill ) = @_;
+
+  #my $cust_main = $self->cust_main($cust_bill);
+  my $cust_main = $cust_bill->cust_main;
+
+  $cust_bill->print;
+}
+
+1;
diff --git a/FS/FS/part_event/Action/cust_bill_print_pdf.pm b/FS/FS/part_event/Action/cust_bill_print_pdf.pm
new file mode 100644 (file)
index 0000000..6b37f38
--- /dev/null
@@ -0,0 +1,26 @@
+package FS::part_event::Action::cust_bill_print_pdf;
+
+use strict;
+use base qw( FS::part_event::Action );
+
+sub description { 'Send invoice (spool PDF only)'; }
+
+sub eventtable_hashref {
+  { 'cust_bill' => 1 };
+}
+
+sub default_weight { 51; }
+
+sub do_action {
+  my( $self, $cust_bill ) = @_;
+
+  #my $cust_main = $self->cust_main($cust_bill);
+  #my $cust_main = $cust_bill->cust_main;
+
+  my $opt = { $self->options };
+  $opt->{'notice_name'} ||= 'Invoice';
+
+  $cust_bill->batch_invoice($opt);
+}
+
+1;
index 1064836..cd9fe06 100644 (file)
@@ -395,8 +395,11 @@ $tools_menu{'Quick payment entry'} =  [ $fsurl.'misc/batch-cust_pay.html', 'Ente
 $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_date;open=1;intransit=1', 'Process credit card and electronic check batches' ]
   if ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
      && $curuser->access_right('Process batches');
 $tools_menu{'Process payment batches'} = [ $fsurl.'search/pay_batch.cgi?magic=_date;open=1;intransit=1', 'Process credit card and electronic check batches' ]
   if ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
      && $curuser->access_right('Process batches');
-$tools_menu{'Download invoice batches'} = [ $fsurl.'search/bill_batch.cgi' ] 
-  if $conf->exists('invoice_print_pdf');
+$tools_menu{'Download invoice batches'} = [ $fsurl.'search/bill_batch.cgi' ]
+  if $curuser->access_right('Process invoice batches')
+  || $curuser->access_right('Process global invoice batches')
+  || $curuser->access_right('Configuration'); #XXX remove in 2.5
+  #now there's a standalone event#if $conf->exists('invoice_print_pdf');
 $tools_menu{'Bulk DID Orders'} =  [ $fsurl.'browse/did_order.html', 'View/manage bulk DID orders' ]
   if $curuser->access_right('Import');
 $tools_menu{'Job Queue'} =  [ $fsurl.'search/queue.html', 'View pending job queue' ]
 $tools_menu{'Bulk DID Orders'} =  [ $fsurl.'browse/did_order.html', 'View/manage bulk DID orders' ]
   if $curuser->access_right('Import');
 $tools_menu{'Job Queue'} =  [ $fsurl.'search/queue.html', 'View pending job queue' ]
index 72e5d3a..6d7e18f 100755 (executable)
@@ -3,10 +3,10 @@
                 'name_singular' => 'batch',
                 'query'         => { 'table'     => 'bill_batch',
                                      'hashref'   => $hashref,
                 'name_singular' => 'batch',
                 'query'         => { 'table'     => 'bill_batch',
                                      'hashref'   => $hashref,
-                                     'extra_sql' => $extra_sql.
-                                        'ORDER BY batchnum DESC',
+                                     #'extra_sql' => $extra_sql.
+                                      'order_by'  => 'ORDER BY batchnum DESC',
                                    },
                                    },
-                'count_query'   => "$count_query $extra_sql",
+                'count_query'   => $count_query,
                 'header'        => [ 'Batch',
                                      'Item Count',
                                      'Status',
                 'header'        => [ 'Batch',
                                      'Item Count',
                                      'Status',
                                      sub { shift->status eq 'O' ? "b" : '' },
                                    ],
                  'really_disable_download' => 1,
                                      sub { shift->status eq 'O' ? "b" : '' },
                                    ],
                  'really_disable_download' => 1,
+                 'agent_virt' => 1,
+                 'agent_null_right' => [ 'Process global invoice batches', 'Configuration' ],
+                 'agent_pos' => 1,
+
       )
 
 %>
 <%init>
 
       )
 
 %>
 <%init>
 
+my $curuser = $FS::CurrentUser::CurrentUser;
+
 die "access denied"
 die "access denied"
-  unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+  unless $curuser->access_right('Process invoice batches')
+      || $curuser->access_right('Process global invoice batches')
+      || $curuser->access_right('Configuration'); #remove in 2.5
 
 my %statusmap = ('O'=>'Open', 'R'=>'Closed');
 my $hashref = {};
 
 my %statusmap = ('O'=>'Open', 'R'=>'Closed');
 my $hashref = {};
-my $count_query = 'SELECT COUNT(*) FROM bill_batch';
+my $count_query = "SELECT COUNT(*) FROM bill_batch WHERE". # $extra_sql AND "
+                    $curuser->agentnums_sql(
+                      'null_right' => ['Process global invoice batches', 'Configuration' ],
+                    );
 
 
-my $extra_sql = ''; # may add something here later
+#my $extra_sql = ''; # may add something here later
 my $link = [ "${p}view/bill_batch.cgi?batchnum=", 'batchnum' ];
 my $dlink = sub {
   [ "${p}view/bill_batch.cgi?start_download=1;".
 my $link = [ "${p}view/bill_batch.cgi?batchnum=", 'batchnum' ];
 my $dlink = sub {
   [ "${p}view/bill_batch.cgi?start_download=1;".