Dateimanagement: Massendruck
authorMartin Helmling <martin.helmling@octosoft.eu>
Tue, 19 Apr 2016 10:39:43 +0000 (12:39 +0200)
committerMartin Helmling martin.helmling@octosoft.eu <martin.helmling@octosoft.eu>
Wed, 1 Feb 2017 07:52:09 +0000 (08:52 +0100)
Der Massendruck per BackgroundJob nutzt nun das FileManagement

Die erzeugten Dateien werden ggf. mit PDF Anhängen erweitert
und entsprechend abgespeichert.

Per Flag kann dem massendruck mitgeteilt werden,
dass eine leere Seite ggf hinzugefügt wird
(Template in templates/print/Standard/emptyPage.pdf o.ä.),
damit nächster Lieferschein auf neuem Blatt beginnt.

pdfinfo wird beim installationscheck gesucht,
leere Seite in Druckvorlagen

Vereinheitlichen der HTML -> PDF Konvertierung

Der HASH "variable_content_types" wird an unterschiedlichsten Stellen mit
unterschiedlichen oder unvollständiger Information befüllt.

Nun wird es an zentraler Stelle gemacht

24 files changed:
SL/BackgroundJob/CreatePeriodicInvoices.pm
SL/BackgroundJob/MassDeliveryOrderPrinting.pm [new file with mode: 0644]
SL/BackgroundJob/MassRecordCreationAndPrinting.pm
SL/Controller/MassDeliveryOrderPrint.pm [new file with mode: 0644]
SL/Controller/MassInvoiceCreatePrint.pm
SL/DB/Helper/FlattenToForm.pm
SL/Form.pm
SL/Helper/File.pm
SL/Helper/MassPrintCreatePDF.pm [new file with mode: 0644]
bin/mozilla/do.pl
bin/mozilla/io.pl
config/kivitendo.conf.default
js/kivi.MassDeliveryOrderPrint.js [new file with mode: 0644]
js/kivi.MassInvoiceCreatePrint.js
js/locale/de.js
locale/de/all
scripts/installation_check.pl
templates/webpages/do/orders_bottom.html
templates/webpages/do/orders_top.html
templates/webpages/mass_delivery_order_print/_filter.html [new file with mode: 0644]
templates/webpages/mass_delivery_order_print/_print_status.html [new file with mode: 0644]
templates/webpages/mass_delivery_order_print/list_delivery_orders.html [new file with mode: 0644]
templates/webpages/mass_invoice_create_print_from_do/_create_print_all_step_1.html
templates/webpages/report_generator/html_report.html

index 1b57cbe..c8b16ab 100644 (file)
@@ -337,13 +337,8 @@ sub _print_invoice {
   $form->{OUT}          = $config->printer->printer_command;
   $form->{OUT_MODE}     = '|-';
 
-  $form->{TEMPLATE_DRIVER_OPTIONS} = {
-    variable_content_types => {
-      longdescription => 'html',
-      partnotes       => 'html',
-      notes           => 'html',
-    },
-  };
+  $form->{TEMPLATE_DRIVER_OPTIONS} = { };
+  $form->{TEMPLATE_DRIVER_OPTIONS}->{variable_content_types} = $form->get_variable_content_types();
 
   $form->prepare_for_printing;
 
diff --git a/SL/BackgroundJob/MassDeliveryOrderPrinting.pm b/SL/BackgroundJob/MassDeliveryOrderPrinting.pm
new file mode 100644 (file)
index 0000000..c46a8d7
--- /dev/null
@@ -0,0 +1,105 @@
+package SL::BackgroundJob::MassDeliveryOrderPrinting;
+
+use strict;
+use warnings;
+
+use parent qw(SL::BackgroundJob::Base);
+
+use SL::DB::DeliveryOrder;
+use SL::DB::Order;  # origin order to delivery_order
+use SL::DB::Printer;
+use SL::SessionFile;
+use SL::Template;
+use SL::Helper::MassPrintCreatePDF qw(:all);
+use SL::Helper::CreatePDF qw(:all);
+use SL::Helper::File qw(store_pdf append_general_pdf_attachments);
+
+use constant WAITING_FOR_EXECUTION       => 0;
+use constant PRINTING_DELIVERY_ORDERS    => 1;
+use constant DONE                        => 2;
+
+# Data format:
+# my $data             = {
+#   record_ids          => [ 123, 124, 127, ],
+#   printer_id         => 4711,
+#   num_created        => 0,
+#   num_printed        => 0,
+#   printed_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 convert_deliveryorders_to_pdf {
+  my ($self) = @_;
+
+  my $job_obj = $self->{job_obj};
+  my $db      = $job_obj->db;
+
+  $job_obj->set_data(status => PRINTING_DELIVERY_ORDERS())->save;
+  my $data   = $job_obj->data_as_hash;
+
+  my $printer_id = $data->{printer_id};
+  if ( $data->{media} ne 'printer' ) {
+      undef $printer_id;
+      $data->{media} = 'file';
+  }
+  my %variables  = (
+    type         => 'delivery_order',
+    formname     =>  $data->{formname},
+    format       =>  $data->{format},
+    media        =>  $data->{media},
+    printer_id   =>  $printer_id,
+    copies       =>  $data->{copies},
+  );
+
+  my @pdf_file_names;
+  foreach my $delivery_order_id (@{ $data->{record_ids} }) {
+    my $number = $delivery_order_id;
+    my $delivery_order = SL::DB::DeliveryOrder->new(id => $delivery_order_id)->load;
+
+    eval {
+      $number = $delivery_order->donumber;
+
+      my %params = (
+        variables  => \%variables,
+        document   => $delivery_order,
+        return     => 'file_name',
+       );
+
+      push @pdf_file_names, $self->create_massprint_pdf(%params);
+
+      $data->{num_created}++;
+
+      1;
+
+    } or do {
+      push @{ $data->{conversion_errors} }, { id => $delivery_order->id, number => $number, message => $@ };
+    };
+
+    $job_obj->update_attributes(data_as_hash => $data);
+  }
+
+  $self->merge_massprint_pdf(file_names => \@pdf_file_names, type => 'delivery_order' ) if scalar(@pdf_file_names) > 0;
+}
+
+sub run {
+  my ($self, $job_obj) = @_;
+
+  $self->{job_obj}         = $job_obj;
+
+  $self->convert_deliveryorders_to_pdf;
+  $self->print_pdfs;
+
+  my $data       = $job_obj->data_as_hash;
+  $data->{num_printed} =  $data->{num_created};
+  $job_obj->update_attributes(data_as_hash => $data);
+  $job_obj->set_data(status => DONE())->save;
+
+  return 1;
+}
+
+1;
+
index 16823dc..e134807 100644 (file)
@@ -12,12 +12,16 @@ use SL::DB::Printer;
 use SL::SessionFile;
 use SL::Template;
 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);
 use SL::Webdav;
 
 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, ],
@@ -46,12 +50,17 @@ 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;
+      if (!$db->with_transaction(sub {
+        $invoice = $sales_delivery_order->convert_to_invoice(sub { $data->{transdate} ? ('attributes' => { transdate => $data->{transdate} }) :
+                                                                         undef }->() ) || die $db->error;
+        1;
+      })) {
+        die $db->error;
+      }
 
       $data->{num_created}++;
       push @{ $data->{invoice_ids} }, $invoice->id;
@@ -75,42 +84,36 @@ 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 %params = (
+        variables => \%variables,
         return    => 'file_name',
-        variable_content_types => { longdescription => 'html',
-                                    partnotes       => 'html',
-                                    notes           => 'html',}
+        document  => $invoice,
       );
+      push @pdf_file_names, $self->create_massprint_pdf(%params);
 
+      $data->{num_printed}++;
 
-
-      $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);
-
+      # OLD WebDAV Code, may be deleted:
       # copy file to webdav folder
       if ($::instance_conf->get_webdav_documents) {
         my $webdav = SL::Webdav->new(
@@ -129,8 +132,6 @@ sub convert_invoices_to_pdf {
         }
       }
 
-      $data->{num_printed}++;
-
       1;
 
     } or do {
@@ -140,52 +141,7 @@ sub convert_invoices_to_pdf {
     $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', session_id => $data->{session_id});
-        $sfile->fh->print($self->{merged_pdf});
-        $sfile->fh->close;
-
-        $data->{pdf_file_name} = $file_name;
-      }
-
-      1;
-
-    } or do {
-      push @{ $data->{print_errors} }, { 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};
-  my $copy_printer_id = $data->{copy_printer_id};
-
-  return if !$printer_id;
-
-  my $out;
-
-  foreach  my $local_printer_id ($printer_id, $copy_printer_id) {
-    next unless $local_printer_id;
-    SL::DB::Printer
-      ->new(id => $local_printer_id)
-      ->load
-      ->print_document(content => $self->{merged_pdf});
-  }
-
+  $self->merge_massprint_pdf(file_names => \@pdf_file_names, type => 'invoice' ) if scalar(@pdf_file_names) > 0;
 }
 
 sub run {
diff --git a/SL/Controller/MassDeliveryOrderPrint.pm b/SL/Controller/MassDeliveryOrderPrint.pm
new file mode 100644 (file)
index 0000000..ca3026b
--- /dev/null
@@ -0,0 +1,283 @@
+package SL::Controller::MassDeliveryOrderPrint;
+
+use strict;
+
+use parent qw(SL::Controller::Base);
+
+use File::Slurp ();
+use File::Copy;
+use List::MoreUtils qw(uniq);
+use List::Util qw(first);
+
+use SL::Controller::Helper::GetModels;
+use SL::BackgroundJob::MassDeliveryOrderPrinting;
+use SL::DB::Customer;
+use SL::DB::DeliveryOrder;
+use SL::DB::Order;
+use SL::DB::Part;
+use SL::DB::Printer;
+use SL::Helper::MassPrintCreatePDF qw(:all);
+use SL::Helper::CreatePDF qw(:all);
+use SL::Helper::PrintOptions;
+use SL::Helper::Flash;
+use SL::Locale::String;
+use SL::SessionFile;
+use SL::System::TaskServer;
+
+use Rose::Object::MakeMethods::Generic
+(
+  'scalar --get_set_init' => [ qw(delivery_order_models delivery_order_ids printers filter_summary temp_files) ],
+);
+
+__PACKAGE__->run_before('setup');
+
+#
+# actions
+#
+sub action_list_delivery_orders {
+  my ($self) = @_;
+
+  my $show = ($::form->{noshow}?0:1);
+  delete $::form->{noshow};
+
+  if ($::form->{ids}) {
+    my $key = 'MassDeliveryOrderPrint::ids-' . $::form->{ids};
+    $self->delivery_order_ids($::auth->get_session_value($key) || []);
+    $self->delivery_order_models->add_additional_url_params(ids => $::form->{ids});
+  }
+
+  my %selected_ids = map { +($_ => 1) } @{ $self->delivery_order_ids };
+
+  my $pr = SL::DB::Manager::Printer->find_by(
+      printer_description => $::locale->text("sales_delivery_order_printer"));
+  if ($pr ) {
+      $::form->{printer_id} = $pr->id;
+  }
+  $self->render('mass_delivery_order_print/list_delivery_orders',
+                title        => $::locale->text('Print delivery orders'),
+                nowshow      => $show,
+                print_opt    => $self->print_options(hide_language_id => 1),
+                selected_ids => \%selected_ids);
+}
+
+sub action_mass_mdo_download {
+  my ($self) = @_;
+  my $job    = SL::DB::BackgroundJob->new(id => $::form->{job_id})->load;
+
+  my $sfile  = SL::SessionFile->new($job->data_as_hash->{pdf_file_name}, mode => 'r');
+  die $! if !$sfile->fh;
+
+  my $merged_pdf = do { local $/; my $fh = $sfile->fh; <$fh> };
+  $sfile->fh->close;
+
+  my $file_name =  t8('Sales Delivery Orders') . '-' . DateTime->now_local->strftime('%Y%m%d%H%M%S') . '.pdf';
+  $file_name    =~ s{[^\w\.]+}{_}g;
+
+  return $self->send_file(
+    \$merged_pdf,
+    type => 'application/pdf',
+    name => $file_name,
+  );
+}
+
+sub action_mass_mdo_status {
+  my ($self) = @_;
+  $::lxdebug->enter_sub();
+  eval {
+    my $job = SL::DB::BackgroundJob->new(id => $::form->{job_id})->load;
+    my $html = $self->render('mass_delivery_order_print/_print_status', { output => 0 }, job => $job);
+
+    $self->js->html('#mass_print_dialog', $html);
+    if ( $job->data_as_hash->{status} == SL::BackgroundJob::MassDeliveryOrderPrinting->DONE() ) {
+      foreach my $dorder_id (@{$job->data_as_hash->{record_ids}}) {
+        $self->js->prop('#multi_id_id_'.$dorder_id,'checked',0);
+      }
+      $self->js->prop('#multi_all','checked',0);
+      $self->js->run('kivi.MassDeliveryOrderPrint.massConversionFinished');
+    }
+    1;
+  } or do {
+    $self->js->run('kivi.MassDeliveryOrderPrint.massConversionFinished')
+      ->run('kivi.MassDeliveryOrderPrint.massConversionFinishProcess')
+      ->flash('error', t8('No such job #1 in the database.',$::form->{job_id}));
+  };
+  $self->js->render;
+
+  $::lxdebug->leave_sub();
+}
+
+sub action_mass_mdo_print {
+  my ($self) = @_;
+  $::lxdebug->enter_sub();
+
+  eval {
+    my @do_ids = @{ $::form->{id} || [] };
+    push @do_ids, map { $::form->{"trans_id_$_"} } grep { $::form->{"multi_id_$_"} } (1..$::form->{rowcount});
+
+    my @delivery_orders = map { SL::DB::DeliveryOrder->new(id => $_)->load } @do_ids;
+
+    if (!@delivery_orders) {
+      $self->js->flash('error', t8('No delivery orders have been selected.'));
+    } else {
+      my $job              = SL::DB::BackgroundJob->new(
+        type               => 'once',
+        active             => 1,
+        package_name       => 'MassDeliveryOrderPrinting',
+
+      )->set_data(
+        record_ids         => [ @do_ids ],
+        printer_id         => $::form->{printer_id},
+        formname           => $::form->{formname},
+        format             => $::form->{format},
+        media              => $::form->{media},
+        bothsided          => ($::form->{bothsided}?1:0),
+        copies             => $::form->{copies},
+        status             => SL::BackgroundJob::MassDeliveryOrderPrinting->WAITING_FOR_EXECUTION(),
+        num_created        => 0,
+        num_printed        => 0,
+        printed_ids        => [ ],
+        conversion_errors  => [ ],
+        print_errors       => [ ],
+        session_id         => $::auth->get_session_id,
+
+      )->update_next_run_at;
+
+      SL::System::TaskServer->new->wake_up;
+      my $html = $self->render('mass_delivery_order_print/_print_status', { output => 0 }, job => $job);
+
+      $self->js
+        ->html('#mass_print_dialog', $html)
+        ->run('kivi.MassDeliveryOrderPrint.massConversionPopup')
+        ->run('kivi.MassDeliveryOrderPrint.massConversionStarted');
+    }
+    1;
+  } or do {
+    my $errstr = $@;
+    my $htmlstr = $errstr;
+    $htmlstr =~ s/\n/<br>/g;
+    $self->js->flash('error', t8('Document generating failed. Please check Templates an LateX !'));
+    $self->js->flash_detail('error', $htmlstr);
+  };
+  $self->js->render;
+  $::lxdebug->leave_sub();
+}
+
+sub action_downloadpdf {
+  my ($self) = @_;
+  $::lxdebug->enter_sub();
+  if ( $::form->{filename} ) {
+    my $content = scalar File::Slurp::read_file($::form->{filename});
+    my $file_name = $::form->get_formname_translation($::form->{formname}) .
+      '-' . DateTime->now_local->strftime('%Y%m%d%H%M%S') . '.pdf';
+    $file_name    =~ s{[^\w\.]+}{_}g;
+
+    unlink($::form->{filename});
+
+    return $self->send_file(
+      \$content,
+      type => 'application/pdf',
+      name => $file_name,
+    );
+  } else {
+    flash('error', t8('No filename exists!'));
+  }
+  $::lxdebug->leave_sub();
+}
+
+#
+# filters
+#
+
+sub init_printers { SL::DB::Manager::Printer->get_all_sorted }
+sub init_delivery_order_ids { [] }
+sub init_temp_files { [] }
+
+sub init_delivery_order_models {
+  my ($self)             = @_;
+  my @delivery_order_ids = @{ $self->delivery_order_ids };
+
+  SL::Controller::Helper::GetModels->new(
+    controller   => $_[0],
+    model        => 'DeliveryOrder',
+    (paginated   => 0,) x !!@delivery_order_ids,
+    sorted       => {
+      _default     => {
+        by           => 'reqdate',
+        dir          => 0,
+      },
+      customer     => t8('Customer'),
+      donumber     => t8('Delivery Order Number'),
+      employee     => t8('Employee'),
+      ordnumber    => t8('Order Number'),
+      reqdate      => t8('Delivery Date'),
+      transdate    => t8('Date'),
+    },
+    with_objects => [ qw(customer employee) ],
+    query        => [
+      '!customer_id' => undef,
+      or             => [ closed    => undef, closed    => 0 ],
+      (id            => \@delivery_order_ids) x !!@delivery_order_ids,
+    ],
+  );
+}
+
+sub init_filter_summary {
+  my ($self) =@_;
+  my $filter = $::form->{filter} || { customer => {}, shipto => {}, };
+
+  my @filters;
+  push @filters, t8('Customer')                              . ' ' . $filter->{customer}->{'name:substr::ilike'}     if $filter->{customer}->{'name:substr::ilike'};
+  push @filters, t8('Shipping address (name)')               . ' ' . $filter->{shipto}->{'shiptoname:substr::ilike'} if $filter->{shipto}->{'shiptoname:substr::ilike'};
+  push @filters, t8('Delivery Date') . ' ' . t8('From Date') . ' ' . $filter->{'reqdate:date::ge'}                   if $filter->{'reqdate:date::ge'};
+  push @filters, t8('Delivery Date') . ' ' . t8('To Date')   . ' ' . $filter->{'reqdate:date::le'}                   if $filter->{'reqdate:date::le'};
+
+  return join ', ', @filters;
+}
+
+sub setup {
+  my ($self) = @_;
+  $::auth->assert('sales_delivery_order_edit');
+  $::request->layout->use_javascript("${_}.js")  for qw(kivi.MassDeliveryOrderPrint);
+}
+
+
+sub generate_documents {
+  my ($self, @delivery_orders) = @_;
+
+  my %pdf_params = (
+    'documents'       => \@delivery_orders ,
+    'variables'       => {
+      'type'            => $::form->{type},
+      'formname'        => $::form->{formname},
+      'language_id'     => '',
+      'format'          => 'pdf',
+      'media'           => 'file',
+      'printer_id'      => $::form->{printer_id},
+    });
+
+  my ($temp_fh, $outname) = File::Temp::tempfile(
+    'kivitendo-outfileXXXXXX',
+    SUFFIX => '.pdf',
+    DIR    => $::lx_office_conf{paths}->{userspath},
+    UNLINK => 0,
+  );
+  close $temp_fh;
+
+  my @pdf_file_names = $self->create_pdfs(%pdf_params);
+  my $fcount = scalar(@pdf_file_names);
+  if ( $fcount < 2 ) {
+    copy($pdf_file_names[0],$outname);
+  } else {
+    if ( !$self->merge_pdfs(file_names => \@pdf_file_names, out_path => $outname, bothsided => $::form->{bothsided} )) {
+      $::lxdebug->leave_sub();
+      return 0;
+    }
+  }
+  foreach my $dorder (@delivery_orders) {
+    $self->js->prop('#multi_id_id_'.$dorder->id,'checked',0);
+  }
+  $self->js->prop('#multi_all','checked',0);
+  return $outname;
+}
+
+1;
index b7212c7..ef5bfaf 100644 (file)
@@ -13,12 +13,12 @@ use SL::Controller::Helper::GetModels;
 use SL::DB::DeliveryOrder;
 use SL::DB::Order;
 use SL::DB::Printer;
+use SL::Helper::MassPrintCreatePDF qw(:all);
 use SL::Helper::CreatePDF qw(:all);
 use SL::Helper::Flash;
 use SL::Locale::String;
 use SL::SessionFile;
 use SL::System::TaskServer;
-
 use Rose::Object::MakeMethods::Generic
 (
   'scalar --get_set_init' => [ qw(invoice_models invoice_ids sales_delivery_order_models printers default_printer_id today) ],
@@ -130,6 +130,7 @@ sub action_create_print_all_start {
     record_ids         => [ map { $_->id } @records[0..$num - 1] ],
     printer_id         => $::form->{printer_id},
     copy_printer_id    => $::form->{copy_printer_id},
+    bothsided          => ($::form->{bothsided}?1:0),
     transdate          => $::form->{transdate},
     status             => SL::BackgroundJob::MassRecordCreationAndPrinting->WAITING_FOR_EXECUTION(),
     num_created        => 0,
@@ -172,7 +173,7 @@ sub action_create_print_all_download {
   $sfile->fh->close;
 
   my $type      = 'Invoices';
-  my $file_name =  t8($type) . '-' . DateTime->today_local->strftime('%Y%m%d%H%M%S') . '.pdf';
+  my $file_name =  t8($type) . '-' . DateTime->now_local->strftime('%Y%m%d%H%M%S') . '.pdf';
   $file_name    =~ s{[^\w\.]+}{_}g;
 
   return $self->send_file(
@@ -187,6 +188,7 @@ sub action_create_print_all_download {
 #
 
 sub init_printers { SL::DB::Manager::Printer->get_all_sorted }
+#sub init_att      { require SL::Controller::Attachments; SL::Controller::Attachments->new() }
 sub init_invoice_ids { [] }
 sub init_today         { DateTime->today_local }
 
@@ -268,30 +270,6 @@ sub setup {
 # helpers
 #
 
-sub create_pdfs {
-  my ($self, %params) = @_;
-
-  my @pdf_file_names;
-  foreach my $invoice (@{ $params{invoices} }) {
-    my %create_params = (
-      template  => $self->find_template(name => 'invoice', printer_id => $params{printer_id}),
-      variables => Form->new(''),
-      return    => 'file_name',
-      variable_content_types => { longdescription => 'html',
-                                  partnotes       => 'html',
-                                  notes           => 'html',}
-    );
-
-    $create_params{variables}->{$_} = $params{variables}->{$_} for keys %{ $params{variables} };
-
-    $invoice->flatten_to_form($create_params{variables}, format_amounts => 1);
-    $create_params{variables}->prepare_for_printing;
-
-    push @pdf_file_names, $self->create_pdf(%create_params);
-  }
-
-  return @pdf_file_names;
-}
 
 sub download_or_print_documents {
   my ($self, %params) = @_;
@@ -300,13 +278,13 @@ sub download_or_print_documents {
 
   eval {
     my %pdf_params = (
-      invoices        => $params{invoices},
-      printer_id      => $params{printer_id},
+      documents       => $params{invoices},
       variables       => {
         type        => 'invoice',
         formname    => 'invoice',
         format      => 'pdf',
         media       => $params{printer_id} ? 'printer' : 'file',
+        printer_id  => $params{printer_id},
       });
 
     @pdf_file_names = $self->create_pdfs(%pdf_params);
@@ -314,7 +292,7 @@ sub download_or_print_documents {
     unlink @pdf_file_names;
 
     if (!$params{printer_id}) {
-      my $file_name =  t8("Invoices") . '-' . DateTime->today_local->strftime('%Y%m%d%H%M%S') . '.pdf';
+      my $file_name =  t8("Invoices") . '-' . DateTime->now_local->strftime('%Y%m%d%H%M%S') . '.pdf';
       $file_name    =~ s{[^\w\.]+}{_}g;
 
       return $self->send_file(
index dff9e1d..5166ff9 100644 (file)
@@ -82,7 +82,9 @@ sub flatten_to_form {
 
     $idx++;
 
-    $form->{"partsgroup_${idx}"} = $item->part->partsgroup->partsgroup if _has($item->part, 'partsgroup_id');
+    $form->{"std_warehouse_${idx}"} = $item->part->warehouse->description if _has($item->part, 'warehouse_id');
+    $form->{"std_bin_${idx}"}       = $item->part->bin->description       if _has($item->part, 'bin_id');
+    $form->{"partsgroup_${idx}"}    = $item->part->partsgroup->partsgroup if _has($item->part, 'partsgroup_id');
     _copy($item,          $form, "${items_name}_", "_${idx}", 0,               qw(id)) if $items_name;
     # TODO: is part_type correct here? Do we need to set part_type as default?
     _copy($item->part,    $form, '',               "_${idx}", 0,               qw(id partnumber weight part_type));
index f50a121..84349d2 100644 (file)
@@ -2846,6 +2846,22 @@ sub lastname_used {
   $main::lxdebug->leave_sub();
 }
 
+sub get_variable_content_types {
+  my %html_variables  = (
+      longdescription => 'html',
+      partnotes       => 'html',
+      notes           => 'html',
+      orignotes       => 'html',
+      notes1          => 'html',
+      notes2          => 'html',
+      notes3          => 'html',
+      notes4          => 'html',
+      header_text     => 'html',
+      footer_text     => 'html',
+  );
+  return \%html_variables;
+}
+
 sub current_date {
   $main::lxdebug->enter_sub();
 
index 7b31ebd..fcf48d6 100644 (file)
@@ -80,7 +80,10 @@ SL::Helper::File - Helper for $::Form to store generated PDF-Documents
 
  $self->store_pdf($self);
 
- $self->append_general_pdf_attachments($self) if ( $ext_for_format eq 'pdf' );
+ $self->append_general_pdf_attachments(filepath => $pdf_filename, type => $form->{type}) if ( $ext_for_format eq 'pdf' );
+
+#It is also used in MassPrint Helper
+# 
 
 =head1 DESCRIPTION
 
diff --git a/SL/Helper/MassPrintCreatePDF.pm b/SL/Helper/MassPrintCreatePDF.pm
new file mode 100644 (file)
index 0000000..454088e
--- /dev/null
@@ -0,0 +1,169 @@
+package SL::Helper::MassPrintCreatePDF;
+
+use strict;
+
+use Exporter 'import';
+our @EXPORT_OK = qw(create_massprint_pdf merge_massprint_pdf create_pdfs print_pdfs);
+our %EXPORT_TAGS = (
+  all => \@EXPORT_OK,
+);
+use SL::Helper::CreatePDF qw(:all);
+use SL::Helper::File qw(store_pdf append_general_pdf_attachments);
+
+sub create_pdfs {
+  my ($self, %params) = @_;
+  my @pdf_file_names;
+  foreach my $document (@{ $params{documents} }) {
+    $params{document} = $document;
+    push @pdf_file_names, $self->create_massprint_pdf(%params);
+  }
+
+  return @pdf_file_names;
+}
+
+sub create_massprint_pdf {
+  my ($self, %params) = @_;
+  my $form = Form->new('');
+  my %create_params = (
+      variables => $form,
+      return    => 'file_name',
+  );
+  ## find_template may return a list !
+  $create_params{template} = $self->find_template(name => $params{variables}->{formname}, printer_id => $params{printer_id});
+  $form->{cwd}= POSIX::getcwd();
+
+  $form->{$_} = $params{variables}->{$_} for keys %{ $params{variables} };
+
+  $create_params{variable_content_types} = $form->get_variable_content_types();
+  $params{document}->flatten_to_form($form, format_amounts => 1);
+  # flatten_to_form sets payment_terms from customer/vendor - we do not want that here
+  # really ??
+  delete $form->{payment_terms} if !$form->{payment_id};
+
+  $form->prepare_for_printing;
+  $form->{attachment_filename} = $form->generate_attachment_filename;
+
+  my $pdf_filename = $self->create_pdf(%create_params);
+
+  if ( $::instance_conf->get_doc_storage && ! $form->{preview}) {
+    $self->append_general_pdf_attachments(filepath => $pdf_filename, type => $form->{type} );
+    $form->{tmpfile} = $pdf_filename;
+    $form->{id}      = $params{document}->id;
+    $self->store_pdf($form);
+  }
+  $form->{id} = $params{document}->id;
+  if ( ! $form->{preview} ) {
+    if ( ref($params{document}) eq 'SL::DB::DeliveryOrder' ) {
+      $form->{snumbers} = "ordnumber_" . $params{document}->donumber;
+    }
+    else {
+      $form->{snumbers} = "unknown";
+    }
+    $form->{addition} = "PRINTED";
+    $form->{what_done} = $::form->{type};
+    $form->save_history;
+  }
+  return $pdf_filename;
+}
+
+sub merge_massprint_pdf {
+  my ($self, %params)     = @_;
+  return unless $params{file_names} && $params{type};
+
+  my $job_obj = $self->{job_obj};
+  my $data    = $job_obj->data_as_hash;
+  my @pdf_file_names = @{$params{file_names}};
+
+  eval {
+    my $file_name = 'mass_'.$params{type}.'_'.$job_obj->id . '.pdf';
+    my $sfile     = SL::SessionFile->new($file_name, mode => 'w', session_id => $data->{session_id});
+    $sfile->fh->close;
+    $data->{pdf_file_name} = $sfile->file_name;
+
+    $self->merge_pdfs(file_names => \@pdf_file_names, bothsided => $data->{bothsided}, out_path => $data->{pdf_file_name});
+    unlink @pdf_file_names;
+
+    1;
+
+  } or do {
+    push @{ $data->{print_errors} }, { 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};
+  my $copy_printer_id = $data->{copy_printer_id};
+
+  return if !$printer_id;
+
+  my $out;
+
+  foreach  my $local_printer_id ($printer_id, $copy_printer_id) {
+    next unless $local_printer_id;
+    SL::DB::Printer
+      ->new(id => $local_printer_id)
+      ->load
+      ->print_document(file_name => $data->{pdf_file_name});
+  }
+
+}
+
+1;
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+SL::Helper::MassPrint_CreatePDF
+
+
+=head1 DESCRIPTION
+
+This Helper used bei Background Processing for Mass Printing.
+The redundant way to fill data for createPDF is concentrated into this helper.
+There are some additional settings for printing which are missed in CreatePDF Helper
+and also the appending of generic PDF-Documents.
+
+(This extension may be included in the CreatePDF Helper).
+
+
+=head1 REQUIRES
+
+L<SL::Helper::CreatePDF>
+
+=head1 METHODS
+
+=head2 C<create_massprint_pdf PARAMS>
+
+a tempory $form is used to set
+
+=over 2
+
+=item 1. content types
+
+=item 2. flatten_to_form
+
+=item 3. prepare_for_printing
+
+=item 4. set history
+
+=back
+
+before printing is done
+
+
+=head1 AUTHOR
+
+Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
+
+
+=cut
+
index 0e8918b..1e5c5a2 100644 (file)
@@ -302,7 +302,7 @@ sub form_header {
 
   $form->{follow_up_trans_info} = $form->{donumber} .'('. $form->{VC_OBJ}->name .')';
 
-  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.File kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io autocomplete_customer autocomplete_part));
+  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.File kivi.MassDeliveryOrderPrint kivi.SalesPurchase ckeditor/ckeditor ckeditor/adapters/jquery kivi.io autocomplete_customer autocomplete_part));
 
   my @custom_hidden;
   push @custom_hidden, map { "shiptocvar_" . $_->name } @{ SL::DB::Manager::CustomVariableConfig->get_all(where => [ module => 'ShipTo' ]) };
@@ -507,6 +507,7 @@ sub orders {
   my $locale   = $main::locale;
   my $cgi      = $::request->{cgi};
 
+  $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.MassDeliveryOrderPrint));
   ($form->{ $form->{vc} }, $form->{"$form->{vc}_id"}) = split(/--/, $form->{ $form->{vc} });
 
   report_generator_set_default_sort('transdate', 1);
@@ -544,7 +545,7 @@ sub orders {
   my $href = build_std_url('action=orders', grep { $form->{$_} } @hidden_variables);
 
   my %column_defs = (
-    'ids'                     => { 'text' => '', },
+    'ids'                     => { 'text' => '<input type="checkbox" id="multi_all" value="1">', 'align' => 'center' },
     'transdate'               => { 'text' => $locale->text('Delivery Order Date'), },
     'reqdate'                 => { 'text' => $locale->text('Reqdate'), },
     'id'                      => { 'text' => $locale->text('ID'), },
@@ -642,9 +643,25 @@ sub orders {
     push @options, $locale->text('Not delivered');
   }
 
+  # all_vc ruft get_employee auf, dort wird emloyee überschrieben, deshalb retten:
+  my $save_employee_id = $form->{'employee_id'};
+  my $save_employee    = $form->{'employee'};
+  $form->all_vc(\%myconfig, $form->{vc}, ($form->{vc} eq 'customer') ? "AR" : "AP");
+  $form->{'employee_id'} = $save_employee_id;
+  $form->{'employee'}    = $save_employee;
+
+  my $pr = SL::DB::Manager::Printer->find_by(
+      printer_description => $::locale->text("sales_delivery_order_printer"));
+  if ($pr ) {
+      $form->{printer_id} = $pr->id;
+  }
+
   $report->set_options('top_info_text'        => join("\n", @options),
                        'raw_top_info_text'    => $form->parse_html_template('do/orders_top'),
-                       'raw_bottom_info_text' => $form->parse_html_template('do/orders_bottom'),
+                       'raw_bottom_info_text' => $form->parse_html_template('do/orders_bottom',
+                        {
+                           print_options   => print_options(inline => 1,hide_language_id => 1),
+                        }),
                        'output_format'        => 'HTML',
                        'title'                => $form->{title},
                        'attachment_basename'  => $attachment_basename . strftime('_%Y%m%d', localtime time),
@@ -669,9 +686,10 @@ sub orders {
 
     my $row = { map { $_ => { 'data' => $dord->{$_} } } @columns };
 
+    my $ord_id = $dord->{id};
     $row->{ids}  = {
-      'raw_data' =>   $cgi->hidden('-name' => "trans_id_${idx}", '-value' => $dord->{id})
-                    . $cgi->checkbox('-name' => "multi_id_${idx}", '-value' => 1, '-label' => ''),
+      'raw_data' =>   $cgi->hidden('-name' => "trans_id_${idx}", '-value' => $ord_id)
+                    . $cgi->checkbox('-name' => "multi_id_${idx}",' id' => "multi_id_id_".$ord_id, '-value' => 1, '-label' => ''),
       'valign'   => 'center',
       'align'    => 'center',
     };
index abbdda1..f071871 100644 (file)
@@ -1294,11 +1294,7 @@ sub print_form {
 
   $form->{TEMPLATE_DRIVER_OPTIONS} = { };
   if (any { $form->{type} eq $_ } qw(sales_quotation sales_order sales_delivery_order invoice request_quotation purchase_order purchase_delivery_order credit_note)) {
-    $form->{TEMPLATE_DRIVER_OPTIONS}->{variable_content_types} = {
-      longdescription => 'html',
-      partnotes       => 'html',
-      notes           => 'html',
-    };
+    $form->{TEMPLATE_DRIVER_OPTIONS}->{variable_content_types} = $form->get_variable_content_types();
   }
 
   $form->isblank("email", $locale->text('E-mail address missing!'))
index 7f5b626..f4b8fe4 100644 (file)
@@ -64,6 +64,10 @@ bind_password =
 # Set language for login and admin forms. Currently "de" (German)
 # and "en" (English, not perfect) are available.
 language = de
+# MassPrint Timeout
+# must be less than cgi timeout
+#
+massprint_timeout = 30
 
 # Set default_manager for admin forms. Currently "german"
 # and "swiss" are available.
diff --git a/js/kivi.MassDeliveryOrderPrint.js b/js/kivi.MassDeliveryOrderPrint.js
new file mode 100644 (file)
index 0000000..426b4c1
--- /dev/null
@@ -0,0 +1,53 @@
+namespace('kivi.MassDeliveryOrderPrint', function(ns) {
+    
+  ns.massConversionFinishProcess = function() {
+    $('#mass_print_dialog').dialog('close');
+  };
+
+  ns.massConversionStarted = function() {
+   $('#mdo_start_process_button,.ui-dialog-titlebar button.ui-dialog-titlebar-close').prop('disabled', 'disabled');
+   $('#mdo_start_process_abort_link').remove();
+   $('#mass_print_dialog').data('timerId', setInterval(function() {
+      $.get("controller.pl", {
+        action: 'MassDeliveryOrderPrint/mass_mdo_status',
+        job_id: $('#mdo_job_id').val()
+      }, kivi.eval_json_result);
+    }, 5000));
+  };
+
+  ns.massConversionPopup = function() {
+    kivi.popup_dialog({
+      id: 'mass_print_dialog',
+      dialog: {
+        title: kivi.t8('Generate and print sales delivery orders')
+      }
+    });
+  };
+
+  ns.massConversionFinished = function() {
+    clearInterval($('#mass_print_dialog').data('timerId'));
+    $('.ui-dialog-titlebar button.ui-dialog-titlebar-close').prop('disabled', '')
+  };
+
+  ns.submitMultiOrders = function () {
+      $("#old_table_id").remove();
+      var checkboxes = $('input[type=checkbox]').filter(function () { return  $(this).prop('checked'); });
+      if (checkboxes.size() == 0) {
+          alert(kivi.t8("No delievery orders selected, please set one checkbox!"));
+          return false;
+      }
+      
+      var tmpform = $("#report_table_id").clone();
+      tmpform.hide();
+      tmpform.attr('id',"old_table_id");
+      tmpform.appendTo("#print_multi_id");
+      return kivi.submit_ajax_form('controller.pl?action=MassDeliveryOrderPrint/mass_mdo_print',$('#print_multi_id'));
+  };
+
+  ns.setup = function() {
+    $('#multi_all').checkall("input[name^='multi_id']");
+    $('#print_multi_button').click(kivi.MassDeliveryOrderPrint.submitMultiOrders);
+  };
+});
+
+$(kivi.MassDeliveryOrderPrint.setup);
index 6135519..bfb215e 100644 (file)
@@ -45,6 +45,7 @@ namespace('kivi.MassInvoiceCreatePrint', function(ns) {
     var data = {
       action:             'MassInvoiceCreatePrint/create_print_all_start',
       number_of_invoices: $('#cpa_number_of_invoices').val(),
+      bothsided:          $('#cpa_bothsided').val(),
       printer_id:         $('#cpa_printer_id').val(),
       copy_printer_id:    $('#cpa_copy_printer_id').val(),
       transdate:          $('#transdate').val()
index 2f197b8..71749f7 100644 (file)
@@ -50,12 +50,14 @@ namespace("kivi").setupLocale({
 "Enter longdescription":"Langtext eingeben",
 "Error: Name missing":"Fehler: Name fehlt",
 "Function block actions":"Funktionsblockaktionen",
+"Generate and print sales delivery orders":"Erzeuge und drucke Lieferscheine",
 "Hide all details":"Alle Details verbergen",
 "Hide details":"Details verbergen",
 "History":"Historie",
 "If you switch to a different tab without saving you will lose the data you've entered in the current tab.":"Wenn Sie auf einen anderen Tab wechseln, ohne vorher zu speichern, so gehen die im aktuellen Tab eingegebenen Daten verloren.",
 "Map":"Karte",
 "No":"Nein",
+"No delievery orders selected, please set one checkbox!":"Kein Lieferschein selektiert, bitte eine Box anklicken!",
 "No delivery orders have been selected.":"Es wurden keine Lieferscheine ausgewählt.",
 "No entries have been selected.":"Es wurden keine Einträge ausgewählt.",
 "No invoices have been selected.":"Es wurden keine Rechnungen ausgewählt.",
index 813284a..9cf72dd 100644 (file)
@@ -723,6 +723,7 @@ $self->{texts} = {
   'Created by'                  => 'Erstellt von',
   'Created for'                 => 'Erstellt f&uuml;r',
   'Created on'                  => 'Erstellt am',
+  'Creating Documents'          => 'Erzeuge Dokumente',
   'Creating invoices'           => 'Erzeuge Rechnungen',
   'Creating the PDF failed:'    => 'PDF-Erzeugung fehlgeschlagen:',
   'Creation Date'               => 'Erstelldatum',
@@ -995,6 +996,7 @@ $self->{texts} = {
   'Document Project (description)' => 'Projektnummer des Belegs (Beschreibung)',
   'Document Project (number)'   => 'Projektnummer des Belegs',
   'Document Project Number'     => 'Projektnummer des Belegs',
+  'Document generating failed. Please check Templates an LateX !' => 'Das Dokument konnte nicht erzeugt werden. Bitte Vorlagen und LateX prüfen!',
   'Documentation'               => 'Dokumentation',
   'Documentation (in German)'   => 'Dokumentation',
   'Documents in the WebDAV repository' => 'Dokumente im WebDAV-Repository',
@@ -1002,7 +1004,7 @@ $self->{texts} = {
   'Done.'                       => 'Fertig.',
   'Double partnumbers'          => 'Doppelte Artikelnummern',
   'Download PDF'                => 'PDF herunterladen',
-  'Download PDF, do not print'  => 'PDF herunterladen, nicht drucken',
+  'Download PDF, do not print'  => 'Nicht drucken, sondern PDF herunterladen',
   'Download SEPA XML export file' => 'SEPA-XML-Exportdatei herunterladen',
   'Download picture'            => 'Bild herunterladen',
   'Download sample file'        => 'Beispieldatei herunterladen',
@@ -1383,6 +1385,7 @@ $self->{texts} = {
   'General ledger corrections'  => 'Korrekturen im Hauptbuch',
   'General ledger transaction \'#1\' posted' => 'Dialogbuchung \'#1\' verbucht.',
   'General settings'            => 'Allgemeine Einstellungen',
+  'Generate and print sales delivery orders' => 'Erzeuge und drucke Lieferscheine',
   'Generic Tax Report'          => 'USTVA Bericht',
   'Germany'                     => 'Deutschland',
   'Git revision: #1, #2 #3'     => 'Git-Revision: #1, #2 #3',
@@ -1830,6 +1833,7 @@ $self->{texts} = {
   'No customer has been selected yet.' => 'Es wurde noch kein Kunde ausgewählt.',
   'No data was found.'          => 'Es wurden keine Daten gefunden.',
   'No default currency'         => 'Keine Standardwährung',
+  'No delievery orders selected, please set one checkbox!' => 'Kein Lieferschein selektiert, bitte eine Box anklicken!',
   'No delivery orders have been selected.' => 'Es wurden keine Lieferscheine ausgewählt.',
   'No delivery term has been created yet.' => 'Es wurden noch keine Lieferbedingungen angelegt',
   'No department has been created yet.' => 'Es wurde noch keine Abteilung erfasst.',
@@ -1840,6 +1844,9 @@ $self->{texts} = {
   'No entries have been selected.' => 'Es wurden keine Einträge ausgewählt.',
   'No errors have occurred.'    => 'Es sind keine Fehler aufgetreten.',
   'No file has been uploaded yet.' => 'Es wurde noch keine Datei hochgeladen.',
+  'No file selected, please set one checkbox!' => 'Kein Element selektiert,bitte eine Box anklicken',
+  'No file uploaded yet'        => 'Keine Datei hochgeladen',
+  'No filename exists!'         => 'Kein Dateiname angegeben',
   'No function blocks have been created yet.' => 'Es wurden noch keine Funktionsblöcke angelegt.',
   'No groups have been created yet.' => 'Es wurden noch keine Gruppen angelegt.',
   'No internal phone extensions have been configured yet.' => 'Es wurden noch keine internen Durchwahlen konfiguriert.',
@@ -1871,6 +1878,7 @@ $self->{texts} = {
   'No sections have been created yet.' => 'Es wurden noch keine Abschnitte angelegt.',
   'No shipto selected to delete' => 'Keine Lieferadresse zum Löschen ausgewählt',
   'No start date given, setting to #1' => 'Kein Startdatum gegeben, setze Startdatum auf #1',
+  'No such job #1 in the database.' => 'Hintergrund-Job #1 existiert nicht mehr.',
   'No summary account'          => 'Kein Sammelkonto',
   'No text blocks have been created for this position.' => 'Für diese Position wurden noch keine Textblöcke angelegt.',
   'No text has been entered yet.' => 'Es wurde noch kein Text eingegeben.',
@@ -1919,6 +1927,8 @@ $self->{texts} = {
   'Number of bins'              => 'Anzahl Lagerpl&auml;tze',
   'Number of columns of custom variables in form details (second row)' => 'Anzahl der Spalten für benutzerdef. Variablen in den Formulardetails (zweite Positionszeile)',
   'Number of copies'            => 'Anzahl Kopien',
+  'Number of deliveryorders created:' => 'Anzahl erzeugter Lieferscheine:',
+  'Number of deliveryorders printed:' => 'Anzahl gedruckter Lieferscheine:',
   'Number of entries changed: #1' => 'Anzahl geänderter Einträge: #1',
   'Number of invoices'          => 'Anzahl Rechnungen',
   'Number of invoices created:' => 'Anzahl erstellter Rechnungen:',
@@ -2184,11 +2194,15 @@ $self->{texts} = {
   'Print'                       => 'Drucken',
   'Print and Post'              => 'Drucken und Buchen',
   'Print automatically'         => 'Automatisch ausdrucken',
-  'Print destination'           => 'Druckausgabe',
+  'Print both sided'            => 'Beidseitig ausdrucken',
+  'Print delivery orders'       => 'Drucke Lieferscheine',
+  'Print destination'           => 'Druckort',
   'Print destination (copy)'    => 'Druckausgabe (Kopie)',
   'Print dunnings'              => 'Mahnungen drucken',
   'Print list'                  => 'Liste ausdrucken',
   'Print options'               => 'Druckoptionen',
+  'Print selected'              => 'Drucken',
+  'Print selected delivery orders both sided' => 'Ausgewählte Lieferscheine (ggf beidseitig)',
   'Print template base file name' => 'Druckvorlagen-Basisdateiname',
   'Print templates'             => 'Druckvorlagen',
   'Print templates to use'      => 'Zu verwendende Druckvorlagen',
@@ -2199,6 +2213,7 @@ $self->{texts} = {
   'Printer Management'          => 'Druckeradministration',
   'Printer management'          => 'Druckerverwaltung',
   'Printing ... '               => 'Es wird gedruckt.',
+  'Printing Documents'          => 'Drucke Dokumente',
   'Printing invoices (this can take a while)' => 'Drucke Rechnungen (kann eine Weile dauern)',
   'Prior year'                  => 'Vorheriges Jahr',
   'Priority'                    => 'Priorität',
@@ -2576,6 +2591,7 @@ $self->{texts} = {
   'Ship via'                    => 'Transportmittel',
   'Shipping Address'            => 'Lieferadresse',
   'Shipping Point'              => 'Versandort',
+  'Shipping address (name)'     => '',
   'Shipping date'               => 'Lieferdatum',
   'Shipto'                      => 'Lieferanschriften',
   'Shipto deleted.'             => 'Lieferadresse gelöscht',
@@ -3156,6 +3172,7 @@ $self->{texts} = {
   'There are Bins defined in your Inventory.' => 'Unter Stammdaten/Waren sind Lagerplätze definiert.',
   'There are Bins defined in your master data.' => 'Unter Stammdaten/Waren sind Lagerplätze defininert',
   'There are bookings to the account 3803 after 01.01.2007. If you didn\'t change this account manually to 19% the bookings are probably incorrect.' => 'Das Konto 3803 wurde nach dem 01.01.2007 bebucht. Falls Sie dieses Konto nicht manuell auf 19% gestellt haben sind die Buchungen wahrscheinlich mit falscher Umsatzsteuer gebucht worden.',
+  'There are currently no delivery orders, or none matches your filter conditions.' => 'kein Lieferschein vorhanden',
   'There are currently no open invoices, or none matches your filter conditions.' => 'Es gibt momentan keine offenen Rechnungen, oder keine erfüllt die Filterkriterien.',
   'There are currently no open sales delivery orders.' => 'Es gibt zur Zeit keine offenen Verkaufslieferscheine.',
   'There are double partnumbers in your database.' => 'In ihrer Datenbank befinden sich mehrfach vergebene Artikelnummern.',
@@ -3491,6 +3508,7 @@ $self->{texts} = {
   'Warning'                     => 'Warnung',
   'Warning! Loading a draft will discard unsaved data!' => 'Achtung! Beim Laden eines Entwurfs werden ungespeicherte Daten verworfen!',
   'Warnings and errors'         => 'Warnungen und Fehler',
+  'Watch status'                => 'Hintergrund-Job Status',
   'WebDAV'                      => 'WebDAV',
   'WebDAV link'                 => 'WebDAV-Link',
   'WebDAV save documents'       => 'Belege in WebDAV-Ablage speichern',
@@ -3767,6 +3785,7 @@ $self->{texts} = {
   'running'                     => 'läuft',
   'sales tax identification number' => 'USt-IdNr.',
   'sales_delivery_order_list'   => 'lieferscheinliste_verkauf',
+  'sales_delivery_order_printer' => '',
   'sales_invoice_printer'       => 'Rechnungsdrucker',
   'sales_order'                 => 'Kundenauftrag',
   'sales_order_list'            => 'auftragsliste',
index 2535a2c..94751b9 100755 (executable)
@@ -202,6 +202,19 @@ sub kpsewhich {
 EOL
   }
 }
+sub check_pdfinfo {
+  my $line = "Looking for pdfinfo executable";
+  my $shell_out = `pdfinfo -v 2>&1 | grep version 2> /dev/null`;
+  my ($label,$vers,$ver_string)  = split / /,$shell_out;
+  if ( $label && $label eq 'pdfinfo' ) {
+    print_line($line, $ver_string, 'green');
+  } else {
+    print_line($line, 'not installed','red');
+    my %modinfo = ( name => 'pdfinfo' );
+    push @missing_modules, \%modinfo;
+
+  }
+}
 
 sub check_pdfinfo {
   my $line = "Looking for pdfinfo executable";
index 4138ca4..be56ee2 100644 (file)
@@ -1,10 +1,22 @@
 [%- USE T8 %]
 [% USE HTML %]
- [% 'New invoice' | $T8 %]<br>
+<table  width="100%">
+   <tr><td width = "200px" >
+ [% 'New invoice' | $T8 %]</td><td width = "150px">
  <input class="submit" type="submit" name="action" value="[% 'Continue' | $T8 %]">
  <input type="hidden" name="nextsub" value="invoice_multi">
  <input type="hidden" name="type" value="[% HTML.escape(type) %]">
  <input type="hidden" name="vc" value="[% HTML.escape(vc) %]">
  <input type="hidden" name="callback" value="[% HTML.escape(callback) %]">
  <input type="hidden" name="rowcount" value="[% HTML.escape(rowcount) %]">
-</form>
+</td><td></td></tr></table></form>
+<form method="post" id="print_multi_id">
+[% print_options %]
+<div id="mass_print_dialog" style="display: none"></div>
+<table  width="100%">
+  <tr><td width="300px" align="right">[% 'Print selected delivery orders both sided' | $T8 %]</td>
+      <td><input type="checkbox" name="bothsided" value="1">
+<input type="hidden" name="type" value="[% HTML.escape(type) %]">
+<input type="hidden" name="rowcount" value="[% HTML.escape(rowcount) %]">
+<input class="submit" type="button" name="action" id="print_multi_button" value="[% 'Print selected' | $T8 %]">
+</td><td></td></tr></table></form>
index bd402c4..964e122 100644 (file)
@@ -1 +1,2 @@
-<form method="post" action="do.pl">
+[%- INCLUDE 'common/flash.html' %]
+<form method="post" id="do_id" action="do.pl">
diff --git a/templates/webpages/mass_delivery_order_print/_filter.html b/templates/webpages/mass_delivery_order_print/_filter.html
new file mode 100644 (file)
index 0000000..7bb547e
--- /dev/null
@@ -0,0 +1,41 @@
+[%- USE L %][%- USE LxERP %][%- USE HTML %]
+<div>
+ <form action="controller.pl" method="post">
+  <div class="filter_toggle" [% IF nowshow==0 %]style="display:none"[% END %]>
+   <a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Show Filter') %]</a>
+   [% IF SELF.filter_summary %]([% LxERP.t8("Current filter") %]: [% SELF.filter_summary %])[% END %]
+  </div>
+
+  <div class="filter_toggle" [% IF nowshow==1 %]style="display:none"[% END %]>
+   <a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Hide Filter') %]</a>
+   <table id="filter_table">
+    <tr>
+     <th align="right">[% LxERP.t8('Customer') %]</th>
+     <td>[% L.input_tag('filter.customer.name:substr::ilike', filter.customer.name_substr__ilike, size = 20) %]</td>
+    </tr>
+    <tr>
+     <th align="right">[% LxERP.t8('Shipping address (name)') %]</th>
+     <td>[% L.input_tag('filter.shipto.shiptoname:substr::ilike', filter.shipto.shiptoname_substr__ilike, size = 20) %]</td>
+    </tr>
+    <tr>
+     <th align="right">[% LxERP.t8('Delivery Date') %] [% LxERP.t8('From Date') %]</th>
+     <td>[% L.date_tag('filter.reqdate:date::ge', filter.reqdate_date__ge) %]</td>
+    </tr>
+    <tr>
+     <th align="right">[% LxERP.t8('Delivery Date') %] [% LxERP.t8('To Date') %]</th>
+     <td>[% L.date_tag('filter.reqdate:date::le', filter.reqdate_date__le) %]</td>
+    </tr>
+   </table>
+
+   [% L.hidden_tag('action', 'ODMassPrint/dispatch') %]
+   [% L.hidden_tag('sort_by', FORM.sort_by) %]
+   [% L.hidden_tag('sort_dir', FORM.sort_dir) %]
+   [% L.hidden_tag('page', FORM.page) %]
+   [% L.submit_tag(LIST_ACTION, LxERP.t8('Continue'))%]
+
+   <a href="#" onClick="javascript:$('#filter_table input,#filter_table select').val('');">[% LxERP.t8('Reset') %]</a>
+
+  </div>
+
+ </form>
+</div>
diff --git a/templates/webpages/mass_delivery_order_print/_print_status.html b/templates/webpages/mass_delivery_order_print/_print_status.html
new file mode 100644 (file)
index 0000000..3d38a0d
--- /dev/null
@@ -0,0 +1,106 @@
+[%- USE LxERP -%][%- USE L -%][%- USE HTML -%]
+[% SET data = job.data_as_hash %]
+<h2>[% LxERP.t8("Watch status") %]</h2>
+
+[% L.hidden_tag('', job.id, id="mdo_job_id") %]
+
+<p>
+ [% LxERP.t8("This status output will be refreshed every five seconds.") %]
+</p>
+
+<p>
+ [% IF data.status < 2 %]
+  [% L.link("login.pl?action=company_logo", LxERP.t8("Open new tab"), target="_blank") %]
+
+ [% ELSE %]
+ [% IF data.pdf_file_name %]
+   [% L.link(SELF.url_for(action="mass_mdo_download", job_id=job.id), LxERP.t8("Download PDF")) %]
+ [% END %]
+ [% L.link("#", LxERP.t8("Close window"), onclick="kivi.MassDeliveryOrderPrint.massConversionFinishProcess();") %]
+[% END %]
+</p>
+
+<p>
+ <table>
+  <tr>
+   <th valign="top" align="left">[% LxERP.t8("Current status:") %]</th>
+   <td valign="top">
+    [% IF !data.status %]
+     [% LxERP.t8("waiting for job to be started") %]
+    [% ELSIF data.status == 1 %]
+     [% LxERP.t8("Creating Documents") %]
+    [% ELSIF data.status == 2 %]
+     [% LxERP.t8("Printing Documents") %]
+    [% ELSE %]
+     [% LxERP.t8("Done.") %]
+     [% IF data.pdf_file_name %]
+      [% LxERP.t8("The file is available for download.") %]
+     [% ELSIF data.printer_id %]
+      [% LxERP.t8("The file has been sent to the printer.") %]
+     [% END %]
+    [% END %]
+   </td>
+  </tr>
+
+  <tr>
+   <th valign="top" align="left">[% LxERP.t8("Number of deliveryorders created:") %]</th>
+   <td valign="top">[% IF data.status > 0 %][% HTML.escape(data.num_created) %] / [% HTML.escape(data.record_ids.size) %][% ELSE %]–[% END %]</td>
+  </tr>
+
+  <tr>
+   <th valign="top" align="left">[% LxERP.t8("Number of deliveryorders printed:") %]</th>
+   <td valign="top">[% IF data.status > 1 %][% HTML.escape(data.num_printed) %] / [% HTML.escape(data.record_ids.size) %][% ELSE %]–[% END %]</td>
+  </tr>
+
+  <tr>
+   <th valign="top" align="left">[% LxERP.t8("Errors during conversion:") %]</th>
+   <td valign="top">
+[% IF !data.status %]
+  –
+[% ELSIF !data.conversion_errors.size %]
+ [% LxERP.t8("No errors have occurred.") %]
+[% ELSE %]
+    <table>
+     <tr class="listheader">
+      <th>[% LxERP.t8("Delivery Order") %]</th>
+      <th>[% LxERP.t8("Error") %]</th>
+     </tr>
+
+ [% FOREACH error = data.conversion_errors %]
+     <tr>
+      <td valign="top">[% IF error.id %][% L.link(SELF.url_for(controller='do.pl', action='edit', type='sales_delivery_order', id=error.id), HTML.escape(error.number), target="_blank") %][% ELSE %]–[% END %]</td>
+      <td valign="top">[% HTML.escape(error.message) %]</td>
+     </tr>
+ [% END %]
+    </table>
+[% END %]
+   </td>
+  </tr>
+
+  <tr>
+   <th valign="top" align="left">[% LxERP.t8("Errors during printing:") %]</th>
+   <td valign="top">
+[% IF data.status < 2 %]
+ –
+[% ELSIF !data.print_errors.size %]
+ [% LxERP.t8("No errors have occurred.") %]
+[% ELSE %]
+    <table>
+     <tr class="listheader">
+      <th>[% LxERP.t8("Invoice") %]</th>
+      <th>[% LxERP.t8("Error") %]</th>
+     </tr>
+
+ [% FOREACH error = data.print_errors %]
+     <tr>
+      <td valign="top">[% IF error.id %][% L.link(SELF.url_for(controller='is.pl', action='edit', type='sales_invoice',id=error.id), HTML.escape(error.number), target="_blank") %][% ELSE %]–[% END %]</td>
+      <td valign="top">[% HTML.escape(error.message) %]</td>
+     </tr>
+ [% END %]
+    </table>
+[% END %]
+   </td>
+  </tr>
+
+ </table>
+</p>
diff --git a/templates/webpages/mass_delivery_order_print/list_delivery_orders.html b/templates/webpages/mass_delivery_order_print/list_delivery_orders.html
new file mode 100644 (file)
index 0000000..a7fa7a2
--- /dev/null
@@ -0,0 +1,72 @@
+[% USE HTML %][% USE L %][% USE LxERP %]
+
+<h1>[% FORM.title %]</h1>
+
+[%- INCLUDE "common/flash.html" %]
+
+[% LIST_ACTION     = 'action_list_delivery_orders' %]
+[%- PROCESS 'mass_delivery_order_print/_filter.html' filter=SELF.filter %]
+
+[% IF nowshow==1 %]
+[% delivery_orders = SELF.delivery_order_models.get;
+   MODELS          = SELF.delivery_order_models %]
+[%- IF !delivery_orders.size %]
+ <p>
+  [%- LxERP.t8("There are currently no delivery orders, or none matches your filter conditions.") %]
+ </p>
+[%- ELSE %]
+
+ <form method="post" action="controller.pl">
+  <table width="100%">
+   <thead>
+    <tr class="listheading">
+     <th>[% L.checkbox_tag("", id="check_all", checkall="[data-checkall=1]") %]</th>
+     <th>[% L.sortable_table_header("transdate") %]</th>
+     <th>[% L.sortable_table_header("reqdate") %]</th>
+     <th>[% L.sortable_table_header("donumber") %]</th>
+     <th>[% L.sortable_table_header("ordnumber") %]</th>
+     <th>[% L.sortable_table_header("customer") %]</th>
+     <th>[% LxERP.t8("Shipto") %]</th>
+    </tr>
+   </thead>
+
+   <tbody>
+    [%- FOREACH delivery_order = delivery_orders %]
+     [% delivery_order_id = delivery_order.id
+        sales_order       = delivery_order.sales_order %]
+     <tr class="listrow">
+      <td>[% L.checkbox_tag('id[]', value=delivery_order.id, "data-checkall"=1, checked=selected_ids.$delivery_order_id) %]</td>
+      <td>[% HTML.escape(delivery_order.transdate_as_date) %]</td>
+      <td>[% HTML.escape(delivery_order.reqdate_as_date) %]</td>
+      <td>[% L.link(SELF.url_for(controller="do.pl", action="edit", type="sales_delivery_order", id=delivery_order.id), delivery_order.donumber) %]</td>
+      <td>[% HTML.escape(delivery_order.ordnumber) %]</td>
+      <td>[% HTML.escape(delivery_order.customer.name) %]</td>
+      <td>[% HTML.escape(SELF.make_shipto_title(delivery_order.shipto || delivery_order.custom_shipto)) %]</td>
+     </tr>
+    [%- END %]
+   </tbody>
+  </table>
+
+  [% IF !SELF.delivery_order_ids.size %]
+   [% L.paginate_controls %]
+  [% END %]
+
+  <hr size="3" noshade>
+
+  <p>[% print_opt %]</p>
+  [% IF SELF.printers.size %]
+   <p>
+    [% LxERP.t8("Print destination") %]:
+    [% SET  printers = [ { description=LxERP.t8("Download PDF, do not print") } ] ;
+       CALL printers.import(SELF.printers);
+       L.select_tag("printer_id", printers, title_key="description", default=FORM.printer_id) %]
+   </p>
+  [% END %]
+
+  <p>
+   [% L.hidden_tag("action", "MassDeliveryOrderPrint/dispatch") %]
+   [% L.submit_tag("action_print", LxERP.t8("Print")) %]
+  </p>
+ </form>
+[%- END %]
+[%- END %]
index 794f518..e66b41f 100644 (file)
   <td>[% LxERP.t8("Number of invoices to create") %]:</td>
   <td>[% L.input_tag('', num_delivery_orders, size="5", id="cpa_number_of_invoices") %]</td>
  </tr>
-
+ <tr>
+  <td>[% LxERP.t8("Print both sided") %]:</td>
+  <td>[% L.checkbox_tag('', id="cpa_bothsided") %]</td>
+ </tr>
  <tr>
   <td>[% LxERP.t8("Print destination") %]:</td>
   <td>
index 19a5ca6..2dfc871 100644 (file)
@@ -29,7 +29,7 @@
 
  [% IF DATA_PRESENT %]
  <p>
-  <table [% IF TABLE_CLASS %]class="[% TABLE_CLASS %]"[% END %] width="100%">
+  <table [% IF TABLE_CLASS %]class="[% TABLE_CLASS %]"[% END %] id="report_table_id" width="100%">
    [%- FOREACH row = HEADER_ROWS %]
    <tr>
     [% FOREACH col = row %]