commit b74a00e5100336d13d1536870721796474599a08
Author: Jan Büren <jan@kivitendo-premium.de>
Date:   Mon Oct 5 17:30:07 2015 +0200

    Massendruck weitere Optionen (zweiter Druckbefehl) implementiert
    
    transdate, copy_printer_id (id des zweiten Druckbefehls) als optionale
    Parameter beim Aufruf der Konvertierung inkl. Ausdruck in der API
    bereitgestellt.
    
    Details: perldoc SL/Controller/MassInvoiceCreatePrint.pm

diff --git a/SL/BackgroundJob/MassRecordCreationAndPrinting.pm b/SL/BackgroundJob/MassRecordCreationAndPrinting.pm
index 9b374f657..e14e13190 100644
--- a/SL/BackgroundJob/MassRecordCreationAndPrinting.pm
+++ b/SL/BackgroundJob/MassRecordCreationAndPrinting.pm
@@ -22,6 +22,8 @@ use constant DONE                        => 3;
 # my $data             = {
 #   record_ids          => [ 123, 124, 127, ],
 #   printer_id         => 4711,
+#   copy_printer_id    => 4711,
+#   transdate          => $today || $custom_transdate,
 #   num_created        => 0,
 #   num_printed        => 0,
 #   invoice_ids        => [ 234, 235, ],
@@ -48,8 +50,8 @@ sub create_invoices {
       $number                  = $sales_delivery_order->donumber;
 
       if (!$db->do_transaction(sub {
-        $invoice = $sales_delivery_order->convert_to_invoice(item_filter => \&delivery_order_item_filter, queue_sort => 1) || die $db->error;
-        # $delivery_order->post_save_sanity_check; # just a hint at e8521eee (#90 od)
+        $invoice = $sales_delivery_order->convert_to_invoice(sub { $data->{transdate} ? ('attributes' => { transdate => $data->{transdate} }) :
+                                                                         undef }->() ) || die $db->error;
         1;
       })) {
         die $db->error;
@@ -166,25 +168,29 @@ sub convert_invoices_to_pdf {
 sub print_pdfs {
   my ($self)     = @_;
 
-  my $job_obj    = $self->{job_obj};
-  my $data       = $job_obj->data_as_hash;
-  my $printer_id = $data->{printer_id};
+  my $job_obj         = $self->{job_obj};
+  my $data            = $job_obj->data_as_hash;
+  my $printer_id      = $data->{printer_id};
+  my $copy_printer_id = $data->{copy_printer_id};
 
   return if !$printer_id;
 
-  my $printer = SL::DB::Printer->new(id => $printer_id)->load;
-  my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command);
   my $out;
 
-  if (!open $out, '|-', $command) {
-    push @{ $data->{print_errors} }, { message => $::locale->text('Could not execute printer command: #1', $!) };
-    $job_obj->update_attributes(data_as_hash => $data);
-    return;
+  foreach  my $local_printer_id ($printer_id, $copy_printer_id) {
+    next unless $local_printer_id;
+    my $printer = SL::DB::Printer->new(id => $local_printer_id)->load;
+    my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command);
+    if (!open $out, '|-', $command) {
+      push @{ $data->{print_errors} }, { message => $::locale->text('Could not execute printer command: #1', $!) };
+      $job_obj->update_attributes(data_as_hash => $data);
+      return;
+    }
+    binmode $out;
+    print $out $self->{merged_pdf};
+    close $out;
   }
 
-  binmode $out;
-  print $out $self->{merged_pdf};
-  close $out;
 }
 
 sub run {
@@ -228,6 +234,8 @@ my $job              = SL::DB::BackgroundJob->new(
   )->set_data(
     record_ids         => [ map { $_->id } @records[0..$num - 1] ],
     printer_id         => $::form->{printer_id},
+    copy_printer_id    => $::form->{copy_printer_id},
+    transdate          => $::form->{transdate} || undef,
     status             => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
     num_created        => 0,
     num_printed        => 0,
@@ -266,6 +274,11 @@ This background job has 4 states which are described by the four constants above
 
 Converts the source objects (DeliveryOrder) to destination objects (Invoice).
 On success objects will be saved.
+If param C<data->{transdate}> is set, this will be the transdate. No safety checks are done.
+The original conversion from order to delivery order had a post_save_sanity_check
+C<$delivery_order-E<gt>post_save_sanity_check; # just a hint at e8521eee (#90 od)>
+The params of convert_to_invoice are created on the fly with a anonym sub, as a alternative check
+ perlsecret Enterprise ()x!!
 
 =item C<convert_invoices_to_pdf>
 
@@ -273,7 +286,8 @@ Takes the new destination objects and merges them via print template in one pdf.
 
 =item C<print_pdfs>
 
-Sent the pdf to the printer command (if checked).
+Sent the pdf to the printer command.
+If param C<data->{copy_printer_id}> is set, the pdf will be sent to a second printer command.
 
 =back
 
@@ -282,6 +296,12 @@ Sent the pdf to the printer command (if checked).
 Currently the calculation from the gui (form) differs from the calculation via convert (PTC).
 Furthermore mass conversion with foreign currencies could lead to problems (daily rate check).
 
+=head1 TODO
+
+It would be great to extend this Job for general background printing. The original project
+code converted sales order to delivery orders (84e7c540) this could be merged in unstable.
+The states should be CONVERTING_SOURCE_RECORDS, PRINTING_DESTINATION_RECORDS etc
+
 =head1 AUTHOR
 
 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
diff --git a/SL/Controller/MassInvoiceCreatePrint.pm b/SL/Controller/MassInvoiceCreatePrint.pm
index 8fecd6459..0e62700bb 100644
--- a/SL/Controller/MassInvoiceCreatePrint.pm
+++ b/SL/Controller/MassInvoiceCreatePrint.pm
@@ -21,7 +21,7 @@ use SL::System::TaskServer;
 
 use Rose::Object::MakeMethods::Generic
 (
-  'scalar --get_set_init' => [ qw(invoice_models invoice_ids sales_delivery_order_models printers default_printer_id) ],
+  'scalar --get_set_init' => [ qw(invoice_models invoice_ids sales_delivery_order_models printers default_printer_id today) ],
 );
 
 __PACKAGE__->run_before('setup');
@@ -118,7 +118,7 @@ sub action_create_print_all_start {
 
   $self->sales_delivery_order_models->disable_plugin('paginated');
 
-  my @records           = @{ $self->sales_delivery_order_models->get };
+  my @records          = @{ $self->sales_delivery_order_models->get };
   my $num              = min(scalar(@records), $::form->{number_of_invoices} // scalar(@records));
 
   my $job              = SL::DB::BackgroundJob->new(
@@ -129,6 +129,8 @@ sub action_create_print_all_start {
   )->set_data(
     record_ids         => [ map { $_->id } @records[0..$num - 1] ],
     printer_id         => $::form->{printer_id},
+    copy_printer_id    => $::form->{copy_printer_id},
+    transdate          => $::form->{transdate},
     status             => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
     num_created        => 0,
     num_printed        => 0,
@@ -185,6 +187,7 @@ sub action_create_print_all_download {
 
 sub init_printers { SL::DB::Manager::Printer->get_all_sorted }
 sub init_invoice_ids { [] }
+sub init_today         { DateTime->today_local }
 
 sub init_sales_delivery_order_models {
   my ($self) = @_;
@@ -434,6 +437,12 @@ Gets all printer commands
 
 Gets a list of (empty) invoice ids
 
+=item C<init_today>
+
+Gets the current day. Currently used in custom code.
+Has to be initialised (get_set_init) and can be used as default for
+a date tag like C<[% L.date_tag("transdate", SELF.today, id=transdate) %]>.
+
 =item C<init_sales_delivery_order_models>
 
 Calls _init_sales_delivery_order_models with a param
@@ -449,8 +458,9 @@ Gets all invoice_models via the ids in invoice_ids (at the beginning no ids exis
 
 =item C<init_default_printer_id>
 
-Gets the default printer for sales_invoices. Maybe this function is not used, but
-might be useful in the next version (working in client project).
+Gets the default printer for sales_invoices. Currently this function is not called, but
+might be useful in the next version.Calling template code and Controller already expect a default:
+C<L.select_tag("", printers, title_key="description", default=SELF.default_printer_id, id="cpa_printer_id") %]>
 
 =item C<setup>
 
@@ -476,12 +486,6 @@ Using BackgroundJobs to mass create / transfer stuff is the way to do it. The or
 was taken from one client project (mosu) with some extra (maybe not standard compliant) customized
 stuff (using cvars for extra filters and a very compressed Controller for linking (ODSalesOrder.pm)).
 
-Filtering needs to be extended for Delivery Order Number (Natural Sort).
-
-A second printer (copy) needs to be implemented.
-
-Both todos are marked in the template code.
-
 
 =head1 AUTHOR
 
diff --git a/js/kivi.MassInvoiceCreatePrint.js b/js/kivi.MassInvoiceCreatePrint.js
index b27ab6a81..59c7939f4 100644
--- a/js/kivi.MassInvoiceCreatePrint.js
+++ b/js/kivi.MassInvoiceCreatePrint.js
@@ -43,7 +43,9 @@ namespace('kivi.MassInvoiceCreatePrint', function(ns) {
 
     var data = {
       number_of_invoices: $('#cpa_number_of_invoices').val(),
-      printer_id:         $('#cpa_printer_id').val()
+      printer_id:         $('#cpa_printer_id').val(),
+      copy_printer_id:    $('#cpa_copy_printer_id').val(),
+      transdate:          $('#transdate').val()
     };
     kivi.submit_ajax_form('controller.pl?action=MassInvoiceCreatePrint/create_print_all_start', '[name^=filter\\.]', data);
   };
