Merge branch 'test' of ../kivitendo-erp_20220811
[kivitendo-erp.git] / SL / BackgroundJob / MassRecordCreationAndPrinting.pm
index 6ebe086..4cc2519 100644 (file)
@@ -11,21 +11,30 @@ use SL::DB::Invoice;
 use SL::DB::Printer;
 use SL::SessionFile;
 use SL::Template;
+use SL::ARAP;
+use SL::Locale::String qw(t8);
+use SL::Helper::MassPrintCreatePDF qw(:all);
+use SL::Helper::CreatePDF qw(:all);
+use SL::Helper::File qw(store_pdf append_general_pdf_attachments doc_storage_enabled);
 
 use constant WAITING_FOR_EXECUTION       => 0;
 use constant CONVERTING_DELIVERY_ORDERS  => 1;
 use constant PRINTING_INVOICES           => 2;
 use constant DONE                        => 3;
+
 # Data format:
 # 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, ],
 #   conversion_errors  => [ { id => 124, number => 'A981723', message => "Stuff went boom" }, ],
 #   print_errors       => [ { id => 234, number => 'L87123123', message => "Printer is out of coffee" }, ],
 #   pdf_file_name      => 'qweqwe.pdf',
+#   session_id         => $::auth->get_session_id,
 # };
 
 sub create_invoices {
@@ -33,6 +42,7 @@ sub create_invoices {
 
   my $job_obj = $self->{job_obj};
   my $db      = $job_obj->db;
+  my $dbh     = $db->dbh;
 
   $job_obj->set_data(status => CONVERTING_DELIVERY_ORDERS())->save;
 
@@ -41,16 +51,30 @@ sub create_invoices {
     my $data   = $job_obj->data_as_hash;
 
     eval {
-      my $invoice;
       my $sales_delivery_order = SL::DB::DeliveryOrder->new(id => $delivery_order_id)->load;
       $number                  = $sales_delivery_order->donumber;
+      my %conversion_params    = $data->{transdate} ? ('attributes' => { transdate => $data->{transdate} }) : ();
+      my $invoice              = $sales_delivery_order->convert_to_invoice(%conversion_params);
+
+      die $db->error if !$invoice;
+
+      ARAP->close_orders_if_billed('dbh'     => $dbh,
+                                   'arap_id' => $invoice->id,
+                                   'table'   => 'ar',);
 
-      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)
-        1;
-      })) {
-        die $db->error;
+      # update shop status
+      my @linked_shop_orders = $invoice->linked_records(
+        from      => 'ShopOrder',
+        via       => [ 'DeliveryOrder', 'Order' ],
+      );
+      #if (scalar @linked_shop_orders[0][0] >= 1){
+        #do update
+      my $shop_order = $linked_shop_orders[0][0];
+      if ($shop_order){
+      require SL::Shop;
+        my $shop_config = SL::DB::Manager::Shop->get_first( query => [ id => $shop_order->shop_id ] );
+        my $shop = SL::Shop->new( config => $shop_config );
+        $shop->connector->set_orderstatus($shop_order->shop_trans_id, "completed");
       }
 
       $data->{num_created}++;
@@ -75,96 +99,50 @@ sub convert_invoices_to_pdf {
   my $db      = $job_obj->db;
 
   $job_obj->set_data(status => PRINTING_INVOICES())->save;
+  my $data = $job_obj->data_as_hash;
 
-  require SL::Controller::MassInvoiceCreatePrint;
-
-  my $printer_id = $job_obj->data_as_hash->{printer_id};
-  my $ctrl       = SL::Controller::MassInvoiceCreatePrint->new;
+  my $printer_id = $data->{printer_id};
+  if ( $data->{media} ne 'printer' ) {
+      undef $printer_id;
+      $data->{media} = 'file';
+  }
   my %variables  = (
     type         => 'invoice',
     formname     => 'invoice',
     format       => 'pdf',
     media        => $printer_id ? 'printer' : 'file',
+    printer_id   => $printer_id,
   );
 
   my @pdf_file_names;
 
   foreach my $invoice (@{ $self->{invoices} }) {
-    my $data = $job_obj->data_as_hash;
 
     eval {
-      my %create_params = (
-        template  => $ctrl->find_template(name => 'invoice', printer_id => $printer_id),
-        variables => Form->new(''),
+      my @errors = ();
+      my %params = (
+        variables => \%variables,
         return    => 'file_name',
+        document  => $invoice,
+        errors    => \@errors,
       );
-
-      $create_params{variables}->{$_} = $variables{$_} for keys %variables;
-
-      $invoice->flatten_to_form($create_params{variables}, format_amounts => 1);
-      $create_params{variables}->prepare_for_printing;
-
-      push @pdf_file_names, $ctrl->create_pdf(%create_params);
-
+      push @pdf_file_names, $self->create_massprint_pdf(%params);
       $data->{num_printed}++;
 
-      1;
-
-    } or do {
-      push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
-    };
-
-    $job_obj->update_attributes(data_as_hash => $data);
-  }
-
-  if (@pdf_file_names) {
-    my $data = $job_obj->data_as_hash;
-
-    eval {
-      $self->{merged_pdf} = $ctrl->merge_pdfs(file_names => \@pdf_file_names);
-      unlink @pdf_file_names;
-
-      if (!$printer_id) {
-        my $file_name = 'mass_invoice' . $job_obj->id . '.pdf';
-        my $sfile     = SL::SessionFile->new($file_name, mode => 'w');
-        $sfile->fh->print($self->{merged_pdf});
-        $sfile->fh->close;
-
-        $data->{pdf_file_name} = $file_name;
+      if (scalar @errors) {
+        push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => join(', ', @errors) };
       }
 
       1;
 
     } or do {
-      push @{ $data->{print_errors} }, { message => $@ };
+      push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
     };
 
     $job_obj->update_attributes(data_as_hash => $data);
   }
-}
-
-sub print_pdfs {
-  my ($self)     = @_;
-
-  my $job_obj    = $self->{job_obj};
-  my $data       = $job_obj->data_as_hash;
-  my $printer_id = $data->{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;
-  }
 
-  binmode $out;
-  print $out $self->{merged_pdf};
-  close $out;
+  $self->merge_massprint_pdf(file_names => \@pdf_file_names, type => 'invoice' ) if scalar(@pdf_file_names) > 0;
 }
 
 sub run {
@@ -208,6 +186,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,
@@ -246,6 +226,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>
 
@@ -253,7 +238,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
 
@@ -262,6 +248,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>