Merge pull request #37 from kivitendo/2021-delivery-order-controller-8
[kivitendo-erp.git] / SL / Controller / Order.pm
index 5c14971..d605f66 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use parent qw(SL::Controller::Base);
 
 use SL::Helper::Flash qw(flash_later);
+use SL::HTML::Util;
 use SL::Presenter::Tag qw(select_tag hidden_tag div_tag);
 use SL::Locale::String qw(t8);
 use SL::SessionFile::Random;
@@ -56,11 +57,11 @@ use Rose::Object::MakeMethods::Generic
 __PACKAGE__->run_before('check_auth');
 
 __PACKAGE__->run_before('recalc',
-                        only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction
+                        only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_invoice_for_advance_payment save_and_final_invoice save_and_ap_transaction
                                      print send_email) ]);
 
 __PACKAGE__->run_before('get_unalterable_data',
-                        only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction
+                        only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_invoice_for_advance_payment save_and_final_invoice save_and_ap_transaction
                                      print send_email) ]);
 
 #
@@ -330,7 +331,7 @@ sub action_print {
     $self->js->flash('info', t8('The document has been printed.'));
   }
 
-  my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $doc_filename);
+  my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $doc_filename, $formname);
   if (scalar @warnings) {
     $self->js->flash('warning', $_) for @warnings;
   }
@@ -479,24 +480,25 @@ sub action_send_email {
   # Is an old file version available?
   my $attfile;
   if ($::form->{attachment_policy} eq 'old_file') {
-    $attfile = SL::File->get_all(object_id   => $self->order->id,
-                                 object_type => $::form->{formname},
-                                 file_type   => 'document');
+    $attfile = SL::File->get_all(object_id     => $self->order->id,
+                                 object_type   => $self->type,
+                                 file_type     => 'document',
+                                 print_variant => $::form->{formname});
   }
 
   if ($::form->{attachment_policy} ne 'no_file' && !($::form->{attachment_policy} eq 'old_file' && $attfile)) {
     my $doc;
-    my @errors = $self->generate_pdf(\$doc, {media      => $::form->{media},
-                                            format     => $::form->{print_options}->{format},
-                                            formname   => $::form->{print_options}->{formname},
-                                            language   => $self->order->language,
-                                            printer_id => $::form->{print_options}->{printer_id},
-                                            groupitems => $::form->{print_options}->{groupitems}});
+    my @errors = $self->generate_doc(\$doc, {media      => $::form->{media},
+                                             format     => $::form->{print_options}->{format},
+                                             formname   => $::form->{print_options}->{formname},
+                                             language   => $self->order->language,
+                                             printer_id => $::form->{print_options}->{printer_id},
+                                             groupitems => $::form->{print_options}->{groupitems}});
     if (scalar @errors) {
       return $self->js->flash('error', t8('Generating the document failed: #1', $errors[0]))->render($self);
     }
 
-    my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $::form->{attachment_filename});
+    my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $::form->{attachment_filename}, $::form->{formname});
     if (scalar @warnings) {
       flash_later('warning', $_) for @warnings;
     }
@@ -521,7 +523,7 @@ sub action_send_email {
   $intnotes   .= t8('Cc')         . ": " . $::form->{cc}                                                              . "\n"    if $::form->{cc};
   $intnotes   .= t8('Bcc')        . ": " . $::form->{bcc}                                                             . "\n"    if $::form->{bcc};
   $intnotes   .= t8('Subject')    . ": " . $::form->{subject}                                                         . "\n\n";
-  $intnotes   .= t8('Message')    . ": " . $::form->{message};
+  $intnotes   .= t8('Message')    . ": " . SL::HTML::Util->strip($::form->{message});
 
   $self->order->update_attributes(intnotes => $intnotes);
 
@@ -556,9 +558,32 @@ sub action_show_periodic_invoices_config_dialog {
                                                                                 language_id      => $::form->{language_id},
                                                                                 translation_type =>"preset_text_periodic_invoices_email_subject"),
                                                    email_body              => GenericTranslations->get(
+                                                                                language_id      => $::form->{language_id},
+                                                                                translation_type => "salutation_general")
+                                                                            . GenericTranslations->get(
+                                                                                language_id      => $::form->{language_id},
+                                                                                translation_type => "salutation_punctuation_mark") . "\n\n"
+                                                                            . GenericTranslations->get(
                                                                                 language_id      => $::form->{language_id},
                                                                                 translation_type =>"preset_text_periodic_invoices_email_body"),
   );
+  # for older configs, replace email preset text if not yet set.
+  $config->email_subject(GenericTranslations->get(
+                                              language_id      => $::form->{language_id},
+                                              translation_type =>"preset_text_periodic_invoices_email_subject")
+                        ) unless $config->email_subject;
+
+  $config->email_body(GenericTranslations->get(
+                                              language_id      => $::form->{language_id},
+                                              translation_type => "salutation_general")
+                    . GenericTranslations->get(
+                                              language_id      => $::form->{language_id},
+                                              translation_type => "salutation_punctuation_mark") . "\n\n"
+                    . GenericTranslations->get(
+                                              language_id      => $::form->{language_id},
+                                              translation_type =>"preset_text_periodic_invoices_email_body")
+                     ) unless $config->email_body;
+
   $config->periodicity('m')             if none { $_ eq $config->periodicity             }       @SL::DB::PeriodicInvoicesConfig::PERIODICITIES;
   $config->order_value_periodicity('p') if none { $_ eq $config->order_value_periodicity } ('p', @SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIODICITIES);
 
@@ -652,6 +677,16 @@ sub action_save_and_delivery_order {
   );
 }
 
+sub action_save_and_supplier_delivery_order {
+  my ($self) = @_;
+
+  $self->save_and_redirect_to(
+    controller => 'controller.pl',
+    action     => 'DeliveryOrder/add_from_order',
+    type       => 'supplier_delivery_order',
+  );
+}
+
 # save the order and redirect to the frontend subroutine for a new
 # invoice
 sub action_save_and_invoice {
@@ -663,6 +698,26 @@ sub action_save_and_invoice {
   );
 }
 
+sub action_save_and_invoice_for_advance_payment {
+  my ($self) = @_;
+
+  $self->save_and_redirect_to(
+    controller       => 'oe.pl',
+    action           => 'oe_invoice_from_order',
+    new_invoice_type => 'invoice_for_advance_payment',
+  );
+}
+
+sub action_save_and_final_invoice {
+  my ($self) = @_;
+
+  $self->save_and_redirect_to(
+    controller       => 'oe.pl',
+    action           => 'oe_invoice_from_order',
+    new_invoice_type => 'final_invoice',
+  );
+}
+
 # workflow from sales order to sales quotation
 sub action_sales_quotation {
   $_[0]->workflow_sales_or_request_for_quotation();
@@ -765,8 +820,10 @@ sub action_show_customer_vendor_details_dialog {
   $details{payment_terms}       = $cv->payment->description       if $cv->payment;
   $details{pricegroup}          = $cv->pricegroup->pricegroup     if $is_customer && $cv->pricegroup;
 
-  foreach my $entry (@{ $cv->additional_billing_addresses }) {
-    push @{ $details{ADDITIONAL_BILLING_ADDRESSES} },   { map { $_ => $entry->$_ } @{$entry->meta->columns} };
+  if ($is_customer) {
+    foreach my $entry (@{ $cv->additional_billing_addresses }) {
+      push @{ $details{ADDITIONAL_BILLING_ADDRESSES} },   { map { $_ => $entry->$_ } @{$entry->meta->columns} };
+    }
   }
   foreach my $entry (@{ $cv->shipto }) {
     push @{ $details{SHIPTO} },   { map { $_ => $entry->$_ } @{$entry->meta->columns} };
@@ -1340,6 +1397,8 @@ sub build_contact_select {
 sub build_billing_address_select {
   my ($self) = @_;
 
+  return '' if $self->cv ne 'customer';
+
   select_tag('order.billing_address_id',
              [ {displayable_id => '', id => ''}, $self->order->{$self->cv}->additional_billing_addresses ],
              value_key  => 'id',
@@ -1945,6 +2004,18 @@ sub setup_edit_action_bar {
   my @req_trans_cost_art = qw(kivi.Order.check_transport_cost_article_presence) x!!$::instance_conf->get_transport_cost_reminder_article_number_id;
   my @req_cusordnumber   = qw(kivi.Order.check_cusordnumber_presence)           x($self->type eq sales_order_type() && $::instance_conf->get_order_warn_no_cusordnumber);
 
+  my $has_invoice_for_advance_payment;
+  if ($self->order->id && $self->type eq sales_order_type()) {
+    my $lr = $self->order->linked_records(direction => 'to', to => ['Invoice']);
+    $has_invoice_for_advance_payment = any {'SL::DB::Invoice' eq ref $_ && "invoice_for_advance_payment" eq $_->type} @$lr;
+  }
+
+  my $has_final_invoice;
+  if ($self->order->id && $self->type eq sales_order_type()) {
+    my $lr = $self->order->linked_records(direction => 'to', to => ['Invoice']);
+    $has_final_invoice               = any {'SL::DB::Invoice' eq ref $_ && "final_invoice" eq $_->type} @$lr;
+  }
+
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
       combobox => [
@@ -2004,6 +2075,16 @@ sub setup_edit_action_bar {
           ],
           only_if   => (any { $self->type eq $_ } (sales_order_type(), purchase_order_type()))
         ],
+        action => [
+          t8('Save and Supplier Delivery Order'),
+          call      => [ 'kivi.Order.save', 'save_and_supplier_delivery_order', $::instance_conf->get_order_warn_duplicate_parts,
+                                                                       $::instance_conf->get_order_warn_no_deliverydate,
+                                                                                                                        ],
+          checks    => [ 'kivi.Order.check_save_active_periodic_invoices',
+                         @req_trans_cost_art, @req_cusordnumber,
+          ],
+          only_if   => (any { $self->type eq $_ } (purchase_order_type()))
+        ],
         action => [
           t8('Save and Invoice'),
           call      => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
@@ -2011,6 +2092,26 @@ sub setup_edit_action_bar {
                          @req_trans_cost_art, @req_cusordnumber,
           ],
         ],
+        action => [
+          ($has_invoice_for_advance_payment ? t8('Save and Further Invoice for Advance Payment') : t8('Save and Invoice for Advance Payment')),
+          call      => [ 'kivi.Order.save', 'save_and_invoice_for_advance_payment', $::instance_conf->get_order_warn_duplicate_parts ],
+          checks    => [ 'kivi.Order.check_save_active_periodic_invoices',
+                         @req_trans_cost_art, @req_cusordnumber,
+          ],
+          disabled  => $has_final_invoice ? t8('This order has already a final invoice.')
+                                          : undef,
+          only_if   => (any { $self->type eq $_ } (sales_order_type())),
+        ],
+        action => [
+          t8('Save and Final Invoice'),
+          call      => [ 'kivi.Order.save', 'save_and_final_invoice', $::instance_conf->get_order_warn_duplicate_parts ],
+          checks    => [ 'kivi.Order.check_save_active_periodic_invoices',
+                         @req_trans_cost_art, @req_cusordnumber,
+          ],
+          disabled  => $has_final_invoice ? t8('This order has already a final invoice.')
+                                          : undef,
+          only_if   => (any { $self->type eq $_ } (sales_order_type())) && $has_invoice_for_advance_payment,
+        ],
         action => [
           t8('Save and AP Transaction'),
           call      => [ 'kivi.Order.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ],
@@ -2325,7 +2426,7 @@ sub save_history {
 }
 
 sub store_doc_to_webdav_and_filemanagement {
-  my ($self, $content, $filename) = @_;
+  my ($self, $content, $filename, $variant) = @_;
 
   my $order = $self->order;
   my @errors;
@@ -2355,7 +2456,8 @@ sub store_doc_to_webdav_and_filemanagement {
                      source        => 'created',
                      file_type     => 'document',
                      file_name     => $filename,
-                     file_contents => $content);
+                     file_contents => $content,
+                     print_variant => $variant);
       1;
     } or do {
       push @errors, t8('Storing the document in the storage backend failed: #1', $@);