Merge branch 'test' of ../kivitendo-erp_20220811
[kivitendo-erp.git] / SL / BackgroundJob / MassRecordCreationAndPrinting.pm
index 458d47a..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 {
@@ -194,7 +172,6 @@ __END__
 
 SL::BackgroundJob::MassRecordCreationAndPrinting
 
-
 =head1 SYNOPSIS
 
 In controller:
@@ -209,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,
@@ -247,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>
 
@@ -254,17 +238,26 @@ 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
 
 =head1 BUGS
+
 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>
 
 Jan Büren E<lt>jan@kivitendo-premium.deE<gt>
+
 =cut