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',
38 my $job_obj = $self->{job_obj};
39 my $db = $job_obj->db;
41 $job_obj->set_data(status => CONVERTING_DELIVERY_ORDERS())->save;
43 foreach my $delivery_order_id (@{ $job_obj->data_as_hash->{record_ids} }) {
44 my $number = $delivery_order_id;
45 my $data = $job_obj->data_as_hash;
49 my $sales_delivery_order = SL::DB::DeliveryOrder->new(id => $delivery_order_id)->load;
50 $number = $sales_delivery_order->donumber;
52 if (!$db->do_transaction(sub {
53 $invoice = $sales_delivery_order->convert_to_invoice(sub { $data->{transdate} ? ('attributes' => { transdate => $data->{transdate} }) :
54 undef }->() ) || die $db->error;
60 $data->{num_created}++;
61 push @{ $data->{invoice_ids} }, $invoice->id;
62 push @{ $self->{invoices} }, $invoice;
66 push @{ $data->{conversion_errors} }, { id => $delivery_order_id, number => $number, message => $@ };
69 $job_obj->update_attributes(data_as_hash => $data);
73 sub convert_invoices_to_pdf {
76 return if !@{ $self->{invoices} };
78 my $job_obj = $self->{job_obj};
79 my $db = $job_obj->db;
81 $job_obj->set_data(status => PRINTING_INVOICES())->save;
83 require SL::Controller::MassInvoiceCreatePrint;
85 my $printer_id = $job_obj->data_as_hash->{printer_id};
86 my $ctrl = SL::Controller::MassInvoiceCreatePrint->new;
89 formname => 'invoice',
91 media => $printer_id ? 'printer' : 'file',
96 foreach my $invoice (@{ $self->{invoices} }) {
97 my $data = $job_obj->data_as_hash;
100 my %create_params = (
101 template => $ctrl->find_template(name => 'invoice', printer_id => $printer_id),
102 variables => Form->new(''),
103 return => 'file_name',
106 $create_params{variables}->{$_} = $variables{$_} for keys %variables;
108 $invoice->flatten_to_form($create_params{variables}, format_amounts => 1);
109 $create_params{variables}->prepare_for_printing;
111 push @pdf_file_names, $ctrl->create_pdf(%create_params);
113 # copy file to webdav folder
114 if ($::instance_conf->get_webdav_documents) {
115 my $webdav = SL::Webdav->new(
117 number => $invoice->invnumber,
119 my $webdav_file = SL::Webdav::File->new(
121 filename => t8('Invoice') . '_' . $invoice->invnumber . '.pdf',
124 $webdav_file->store(file => $pdf_file_names[-1]);
127 push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
131 $data->{num_printed}++;
136 push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
139 $job_obj->update_attributes(data_as_hash => $data);
142 if (@pdf_file_names) {
143 my $data = $job_obj->data_as_hash;
146 $self->{merged_pdf} = $ctrl->merge_pdfs(file_names => \@pdf_file_names);
147 unlink @pdf_file_names;
150 my $file_name = 'mass_invoice' . $job_obj->id . '.pdf';
151 my $sfile = SL::SessionFile->new($file_name, mode => 'w');
152 $sfile->fh->print($self->{merged_pdf});
155 $data->{pdf_file_name} = $file_name;
161 push @{ $data->{print_errors} }, { message => $@ };
164 $job_obj->update_attributes(data_as_hash => $data);
171 my $job_obj = $self->{job_obj};
172 my $data = $job_obj->data_as_hash;
173 my $printer_id = $data->{printer_id};
174 my $copy_printer_id = $data->{copy_printer_id};
176 return if !$printer_id;
180 foreach my $local_printer_id ($printer_id, $copy_printer_id) {
181 next unless $local_printer_id;
182 my $printer = SL::DB::Printer->new(id => $local_printer_id)->load;
183 my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command);
184 if (!open $out, '|-', $command) {
185 push @{ $data->{print_errors} }, { message => $::locale->text('Could not execute printer command: #1', $!) };
186 $job_obj->update_attributes(data_as_hash => $data);
190 print $out $self->{merged_pdf};
197 my ($self, $job_obj) = @_;
199 $self->{job_obj} = $job_obj;
200 $self->{invoices} = [];
202 $self->create_invoices;
203 $self->convert_invoices_to_pdf;
206 $job_obj->set_data(status => DONE())->save;
221 SL::BackgroundJob::MassRecordCreationAndPrinting
227 use SL::BackgroundJob::MassRecordCreationAndPrinting
229 my $job = SL::DB::BackgroundJob->new(
232 package_name => 'MassRecordCreationAndPrinting',
235 record_ids => [ map { $_->id } @records[0..$num - 1] ],
236 printer_id => $::form->{printer_id},
237 copy_printer_id => $::form->{copy_printer_id},
238 transdate => $::form->{transdate} || undef,
239 status => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
243 conversion_errors => [ ],
246 )->update_next_run_at;
247 SL::System::TaskServer->new->wake_up;
251 This background job has 4 states which are described by the four constants above.
255 =item * WAITING_FOR_EXECUTION
256 Background has been initialised and needs to be picked up by the task_server
258 =item * CONVERTING_DELIVERY_ORDERS
261 =item * PRINTING_INVOICES
262 Printing, if done via print command
265 To release the process and for the user information
273 =item C<create_invoices>
275 Converts the source objects (DeliveryOrder) to destination objects (Invoice).
276 On success objects will be saved.
277 If param C<data->{transdate}> is set, this will be the transdate. No safety checks are done.
278 The original conversion from order to delivery order had a post_save_sanity_check
279 C<$delivery_order-E<gt>post_save_sanity_check; # just a hint at e8521eee (#90 od)>
280 The params of convert_to_invoice are created on the fly with a anonym sub, as a alternative check
281 perlsecret Enterprise ()x!!
283 =item C<convert_invoices_to_pdf>
285 Takes the new destination objects and merges them via print template in one pdf.
289 Sent the pdf to the printer command.
290 If param C<data->{copy_printer_id}> is set, the pdf will be sent to a second printer command.
296 Currently the calculation from the gui (form) differs from the calculation via convert (PTC).
297 Furthermore mass conversion with foreign currencies could lead to problems (daily rate check).
301 It would be great to extend this Job for general background printing. The original project
302 code converted sales order to delivery orders (84e7c540) this could be merged in unstable.
303 The states should be CONVERTING_SOURCE_RECORDS, PRINTING_DESTINATION_RECORDS etc
307 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
309 Jan Büren E<lt>jan@kivitendo-premium.deE<gt>