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',
104 variable_content_types => { longdescription => 'html',
111 $create_params{variables}->{$_} = $variables{$_} for keys %variables;
113 $invoice->flatten_to_form($create_params{variables}, format_amounts => 1);
114 $create_params{variables}->prepare_for_printing;
116 push @pdf_file_names, $ctrl->create_pdf(%create_params);
118 # copy file to webdav folder
119 if ($::instance_conf->get_webdav_documents) {
120 my $webdav = SL::Webdav->new(
122 number => $invoice->invnumber,
124 my $webdav_file = SL::Webdav::File->new(
126 filename => t8('Invoice') . '_' . $invoice->invnumber . '.pdf',
129 $webdav_file->store(file => $pdf_file_names[-1]);
132 push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
136 $data->{num_printed}++;
141 push @{ $data->{print_errors} }, { id => $invoice->id, number => $invoice->invnumber, message => $@ };
144 $job_obj->update_attributes(data_as_hash => $data);
147 if (@pdf_file_names) {
148 my $data = $job_obj->data_as_hash;
151 $self->{merged_pdf} = $ctrl->merge_pdfs(file_names => \@pdf_file_names);
152 unlink @pdf_file_names;
155 my $file_name = 'mass_invoice' . $job_obj->id . '.pdf';
156 my $sfile = SL::SessionFile->new($file_name, mode => 'w');
157 $sfile->fh->print($self->{merged_pdf});
160 $data->{pdf_file_name} = $file_name;
166 push @{ $data->{print_errors} }, { message => $@ };
169 $job_obj->update_attributes(data_as_hash => $data);
176 my $job_obj = $self->{job_obj};
177 my $data = $job_obj->data_as_hash;
178 my $printer_id = $data->{printer_id};
179 my $copy_printer_id = $data->{copy_printer_id};
181 return if !$printer_id;
185 foreach my $local_printer_id ($printer_id, $copy_printer_id) {
186 next unless $local_printer_id;
187 my $printer = SL::DB::Printer->new(id => $local_printer_id)->load;
188 my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command);
189 if (!open $out, '|-', $command) {
190 push @{ $data->{print_errors} }, { message => $::locale->text('Could not execute printer command: #1', $!) };
191 $job_obj->update_attributes(data_as_hash => $data);
195 print $out $self->{merged_pdf};
202 my ($self, $job_obj) = @_;
204 $self->{job_obj} = $job_obj;
205 $self->{invoices} = [];
207 $self->create_invoices;
208 $self->convert_invoices_to_pdf;
211 $job_obj->set_data(status => DONE())->save;
226 SL::BackgroundJob::MassRecordCreationAndPrinting
232 use SL::BackgroundJob::MassRecordCreationAndPrinting
234 my $job = SL::DB::BackgroundJob->new(
237 package_name => 'MassRecordCreationAndPrinting',
240 record_ids => [ map { $_->id } @records[0..$num - 1] ],
241 printer_id => $::form->{printer_id},
242 copy_printer_id => $::form->{copy_printer_id},
243 transdate => $::form->{transdate} || undef,
244 status => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
248 conversion_errors => [ ],
251 )->update_next_run_at;
252 SL::System::TaskServer->new->wake_up;
256 This background job has 4 states which are described by the four constants above.
260 =item * WAITING_FOR_EXECUTION
261 Background has been initialised and needs to be picked up by the task_server
263 =item * CONVERTING_DELIVERY_ORDERS
266 =item * PRINTING_INVOICES
267 Printing, if done via print command
270 To release the process and for the user information
278 =item C<create_invoices>
280 Converts the source objects (DeliveryOrder) to destination objects (Invoice).
281 On success objects will be saved.
282 If param C<data->{transdate}> is set, this will be the transdate. No safety checks are done.
283 The original conversion from order to delivery order had a post_save_sanity_check
284 C<$delivery_order-E<gt>post_save_sanity_check; # just a hint at e8521eee (#90 od)>
285 The params of convert_to_invoice are created on the fly with a anonym sub, as a alternative check
286 perlsecret Enterprise ()x!!
288 =item C<convert_invoices_to_pdf>
290 Takes the new destination objects and merges them via print template in one pdf.
294 Sent the pdf to the printer command.
295 If param C<data->{copy_printer_id}> is set, the pdf will be sent to a second printer command.
301 Currently the calculation from the gui (form) differs from the calculation via convert (PTC).
302 Furthermore mass conversion with foreign currencies could lead to problems (daily rate check).
306 It would be great to extend this Job for general background printing. The original project
307 code converted sales order to delivery orders (84e7c540) this could be merged in unstable.
308 The states should be CONVERTING_SOURCE_RECORDS, PRINTING_DESTINATION_RECORDS etc
312 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
314 Jan Büren E<lt>jan@kivitendo-premium.deE<gt>