1 package SL::BackgroundJob::MassRecordCreationAndPrinting;
 
   6 use parent qw(SL::BackgroundJob::Base);
 
   8 use SL::DB::DeliveryOrder;
 
   9 use SL::DB::Order;  # origin order to delivery_order
 
  14 use SL::Locale::String qw(t8);
 
  17 use constant WAITING_FOR_EXECUTION       => 0;
 
  18 use constant CONVERTING_DELIVERY_ORDERS  => 1;
 
  19 use constant PRINTING_INVOICES           => 2;
 
  20 use constant DONE                        => 3;
 
  23 #   record_ids          => [ 123, 124, 127, ],
 
  25 #   copy_printer_id    => 4711,
 
  26 #   transdate          => $today || $custom_transdate,
 
  29 #   invoice_ids        => [ 234, 235, ],
 
  30 #   conversion_errors  => [ { id => 124, number => 'A981723', message => "Stuff went boom" }, ],
 
  31 #   print_errors       => [ { id => 234, number => 'L87123123', message => "Printer is out of coffee" }, ],
 
  32 #   pdf_file_name      => 'qweqwe.pdf',
 
  33 #   session_id         => $::auth->get_session_id,
 
  39   my $job_obj = $self->{job_obj};
 
  40   my $db      = $job_obj->db;
 
  42   $job_obj->set_data(status => CONVERTING_DELIVERY_ORDERS())->save;
 
  44   foreach my $delivery_order_id (@{ $job_obj->data_as_hash->{record_ids} }) {
 
  45     my $number = $delivery_order_id;
 
  46     my $data   = $job_obj->data_as_hash;
 
  50       my $sales_delivery_order = SL::DB::DeliveryOrder->new(id => $delivery_order_id)->load;
 
  51       $number                  = $sales_delivery_order->donumber;
 
  53       if (!$db->do_transaction(sub {
 
  54         $invoice = $sales_delivery_order->convert_to_invoice(sub { $data->{transdate} ? ('attributes' => { transdate => $data->{transdate} }) :
 
  55                                                                          undef }->() ) || die $db->error;
 
  61       $data->{num_created}++;
 
  62       push @{ $data->{invoice_ids} }, $invoice->id;
 
  63       push @{ $self->{invoices}    }, $invoice;
 
  67       push @{ $data->{conversion_errors} }, { id => $delivery_order_id, number => $number, message => $@ };
 
  70     $job_obj->update_attributes(data_as_hash => $data);
 
  74 sub convert_invoices_to_pdf {
 
  77   return if !@{ $self->{invoices} };
 
  79   my $job_obj = $self->{job_obj};
 
  80   my $db      = $job_obj->db;
 
  82   $job_obj->set_data(status => PRINTING_INVOICES())->save;
 
  84   require SL::Controller::MassInvoiceCreatePrint;
 
  86   my $printer_id = $job_obj->data_as_hash->{printer_id};
 
  87   my $ctrl       = SL::Controller::MassInvoiceCreatePrint->new;
 
  90     formname     => 'invoice',
 
  92     media        => $printer_id ? 'printer' : 'file',
 
  97   foreach my $invoice (@{ $self->{invoices} }) {
 
  98     my $data = $job_obj->data_as_hash;
 
 101       my %create_params = (
 
 102         template  => $ctrl->find_template(name => 'invoice', printer_id => $printer_id),
 
 103         variables => Form->new(''),
 
 104         return    => 'file_name',
 
 105         variable_content_types => { longdescription => 'html',
 
 112       $create_params{variables}->{$_} = $variables{$_} for keys %variables;
 
 114       $invoice->flatten_to_form($create_params{variables}, format_amounts => 1);
 
 115       $create_params{variables}->prepare_for_printing;
 
 117       push @pdf_file_names, $ctrl->create_pdf(%create_params);
 
 119       # copy file to webdav folder
 
 120       if ($::instance_conf->get_webdav_documents) {
 
 121         my $webdav = SL::Webdav->new(
 
 123           number   => $invoice->invnumber,
 
 125         my $webdav_file = SL::Webdav::File->new(
 
 127           filename => t8('Invoice') . '_' . $invoice->invnumber . '.pdf',
 
 130           $webdav_file->store(file => $pdf_file_names[-1]);
 
 133           push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
 
 137       $data->{num_printed}++;
 
 142       push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
 
 145     $job_obj->update_attributes(data_as_hash => $data);
 
 148   if (@pdf_file_names) {
 
 149     my $data = $job_obj->data_as_hash;
 
 152       $self->{merged_pdf} = $ctrl->merge_pdfs(file_names => \@pdf_file_names);
 
 153       unlink @pdf_file_names;
 
 156         my $file_name = 'mass_invoice' . $job_obj->id . '.pdf';
 
 157         my $sfile     = SL::SessionFile->new($file_name, mode => 'w', session_id => $data->{session_id});
 
 158         $sfile->fh->print($self->{merged_pdf});
 
 161         $data->{pdf_file_name} = $file_name;
 
 167       push @{ $data->{print_errors} }, { message => $@ };
 
 170     $job_obj->update_attributes(data_as_hash => $data);
 
 177   my $job_obj         = $self->{job_obj};
 
 178   my $data            = $job_obj->data_as_hash;
 
 179   my $printer_id      = $data->{printer_id};
 
 180   my $copy_printer_id = $data->{copy_printer_id};
 
 182   return if !$printer_id;
 
 186   foreach  my $local_printer_id ($printer_id, $copy_printer_id) {
 
 187     next unless $local_printer_id;
 
 188     my $printer = SL::DB::Printer->new(id => $local_printer_id)->load;
 
 189     my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command);
 
 190     if (!open $out, '|-', $command) {
 
 191       push @{ $data->{print_errors} }, { message => $::locale->text('Could not execute printer command: #1', $!) };
 
 192       $job_obj->update_attributes(data_as_hash => $data);
 
 196     print $out $self->{merged_pdf};
 
 203   my ($self, $job_obj) = @_;
 
 205   $self->{job_obj}         = $job_obj;
 
 206   $self->{invoices} = [];
 
 208   $self->create_invoices;
 
 209   $self->convert_invoices_to_pdf;
 
 212   $job_obj->set_data(status => DONE())->save;
 
 227 SL::BackgroundJob::MassRecordCreationAndPrinting
 
 233 use SL::BackgroundJob::MassRecordCreationAndPrinting
 
 235 my $job              = SL::DB::BackgroundJob->new(
 
 238     package_name       => 'MassRecordCreationAndPrinting',
 
 241     record_ids         => [ map { $_->id } @records[0..$num - 1] ],
 
 242     printer_id         => $::form->{printer_id},
 
 243     copy_printer_id    => $::form->{copy_printer_id},
 
 244     transdate          => $::form->{transdate} || undef,
 
 245     status             => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
 
 249     conversion_errors  => [ ],
 
 252   )->update_next_run_at;
 
 253   SL::System::TaskServer->new->wake_up;
 
 257 This background job has 4 states which are described by the four constants above.
 
 261 =item * WAITING_FOR_EXECUTION
 
 262   Background has been initialised and needs to be picked up by the task_server
 
 264 =item * CONVERTING_DELIVERY_ORDERS
 
 267 =item * PRINTING_INVOICES
 
 268   Printing, if done via print command
 
 271   To release the process and for the user information
 
 279 =item C<create_invoices>
 
 281 Converts the source objects (DeliveryOrder) to destination objects (Invoice).
 
 282 On success objects will be saved.
 
 283 If param C<data->{transdate}> is set, this will be the transdate. No safety checks are done.
 
 284 The original conversion from order to delivery order had a post_save_sanity_check
 
 285 C<$delivery_order-E<gt>post_save_sanity_check; # just a hint at e8521eee (#90 od)>
 
 286 The params of convert_to_invoice are created on the fly with a anonym sub, as a alternative check
 
 287  perlsecret Enterprise ()x!!
 
 289 =item C<convert_invoices_to_pdf>
 
 291 Takes the new destination objects and merges them via print template in one pdf.
 
 295 Sent the pdf to the printer command.
 
 296 If param C<data->{copy_printer_id}> is set, the pdf will be sent to a second printer command.
 
 302 Currently the calculation from the gui (form) differs from the calculation via convert (PTC).
 
 303 Furthermore mass conversion with foreign currencies could lead to problems (daily rate check).
 
 307 It would be great to extend this Job for general background printing. The original project
 
 308 code converted sales order to delivery orders (84e7c540) this could be merged in unstable.
 
 309 The states should be CONVERTING_SOURCE_RECORDS, PRINTING_DESTINATION_RECORDS etc
 
 313 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
 
 315 Jan Büren E<lt>jan@kivitendo-premium.deE<gt>