|  | package SL::Controller::Reclamation;
 | 
  
    |  | 
 | 
  
    |  | use strict;
 | 
  
    |  | use parent qw(SL::Controller::Base);
 | 
  
    |  | 
 | 
  
    |  | use SL::Helper::Flash qw(flash_later);
 | 
  
    |  | use SL::Presenter::Tag qw(select_tag hidden_tag div_tag);
 | 
  
    |  | use SL::Presenter::ReclamationFilter qw(filter);
 | 
  
    |  | use SL::Locale::String qw(t8);
 | 
  
    |  | use SL::SessionFile::Random;
 | 
  
    |  | use SL::PriceSource;
 | 
  
    |  | use SL::ReportGenerator;
 | 
  
    |  | use SL::Controller::Helper::ReportGenerator;
 | 
  
    |  | use SL::Webdav;
 | 
  
    |  | use SL::File;
 | 
  
    |  | use SL::MIME;
 | 
  
    |  | use SL::Util qw(trim);
 | 
  
    |  | use SL::YAML;
 | 
  
    |  | use SL::DB::History;
 | 
  
    |  | use SL::DB::Reclamation;
 | 
  
    |  | use SL::DB::ReclamationItem;
 | 
  
    |  | use SL::DB::Default;
 | 
  
    |  | use SL::DB::Printer;
 | 
  
    |  | use SL::DB::Language;
 | 
  
    |  | use SL::DB::RecordLink;
 | 
  
    |  | use SL::DB::Shipto;
 | 
  
    |  | use SL::DB::Translation;
 | 
  
    |  | use SL::DB::ValidityToken;
 | 
  
    |  | 
 | 
  
    |  | use SL::Helper::CreatePDF qw(:all);
 | 
  
    |  | use SL::Helper::PrintOptions;
 | 
  
    |  | use SL::Helper::UserPreferences::PositionsScrollbar;
 | 
  
    |  | use SL::Helper::UserPreferences::UpdatePositions;
 | 
  
    |  | 
 | 
  
    |  | use SL::Controller::Helper::GetModels;
 | 
  
    |  | 
 | 
  
    |  | use List::Util qw(first sum0);
 | 
  
    |  | use List::UtilsBy qw(sort_by uniq_by);
 | 
  
    |  | use List::MoreUtils qw(any none pairwise first_index);
 | 
  
    |  | use English qw(-no_match_vars);
 | 
  
    |  | use File::Spec;
 | 
  
    |  | use Cwd;
 | 
  
    |  | use Sort::Naturally;
 | 
  
    |  | 
 | 
  
    |  | use Rose::Object::MakeMethods::Generic
 | 
  
    |  | (
 | 
  
    |  |  scalar => [ qw(item_ids_to_delete is_custom_shipto_to_delete) ],
 | 
  
    |  |  'scalar --get_set_init' => [qw(
 | 
  
    |  |     all_price_factors cv models p part_picker_classification_ids reclamation
 | 
  
    |  |     search_cvpartnumber show_update_button type valid_types
 | 
  
    |  |  )],
 | 
  
    |  | );
 | 
  
    |  | 
 | 
  
    |  | 
 | 
  
    |  | # safety
 | 
  
    |  | __PACKAGE__->run_before('check_auth');
 | 
  
    |  | 
 | 
  
    |  | __PACKAGE__->run_before('recalc',
 | 
  
    |  |                         only => [qw(
 | 
  
    |  |                           save save_as_new print preview_pdf send_email
 | 
  
    |  |                           save_and_show_email_dialog
 | 
  
    |  |                           workflow_save_and_sales_or_purchase_reclamation
 | 
  
    |  |                           save_and_order
 | 
  
    |  |                           save_and_delivery_order
 | 
  
    |  |                           save_and_credit_note
 | 
  
    |  |                        )]);
 | 
  
    |  | 
 | 
  
    |  | __PACKAGE__->run_before('get_unalterable_data',
 | 
  
    |  |                         only => [qw(
 | 
  
    |  |                           save save_as_new print preview_pdf send_email
 | 
  
    |  |                           save_and_show_email_dialog
 | 
  
    |  |                           workflow_save_and_sales_or_purchase_reclamation
 | 
  
    |  |                           save_and_order
 | 
  
    |  |                           save_and_delivery_order
 | 
  
    |  |                           save_and_credit_note
 | 
  
    |  |                         )]);
 | 
  
    |  | 
 | 
  
    |  | __PACKAGE__->run_before('get_record_links_data_from_form',
 | 
  
    |  |                         only => [qw(
 | 
  
    |  |                           save save_as_new print preview_pdf send_email
 | 
  
    |  |                           save_and_show_email_dialog
 | 
  
    |  |                           workflow_save_and_sales_or_purchase_reclamation
 | 
  
    |  |                           save_and_order
 | 
  
    |  |                           save_and_delivery_order
 | 
  
    |  |                           save_and_credit_note
 | 
  
    |  |                         )]);
 | 
  
    |  | 
 | 
  
    |  | #
 | 
  
    |  | # actions
 | 
  
    |  | #
 | 
  
    |  | 
 | 
  
    |  | # add a new reclamation
 | 
  
    |  | sub action_add {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation->transdate(DateTime->now_local());
 | 
  
    |  | 
 | 
  
    |  |   $self->pre_render();
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('add'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_add_from_order {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   unless ($::form->{from_id}) {
 | 
  
    |  |     $self->js->flash('error', t8("Can't create new reclamation. No 'from_id' was given."));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   require SL::DB::Order;
 | 
  
    |  |   my $order = SL::DB::Order->new(id => $::form->{from_id})->load;
 | 
  
    |  |   my $reclamation = $order->convert_to_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation($reclamation);
 | 
  
    |  | 
 | 
  
    |  |   $self->reinit_after_new_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('add'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_add_from_delivery_order {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   unless ($::form->{from_id}) {
 | 
  
    |  |     $self->js->flash('error', t8("Can't create new reclamation. No 'from_id' was given."));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   require SL::DB::DeliveryOrder;
 | 
  
    |  |   my $delivery_order = SL::DB::DeliveryOrder->new(id => $::form->{from_id})->load;
 | 
  
    |  |   my $reclamation = $delivery_order->convert_to_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation($reclamation);
 | 
  
    |  | 
 | 
  
    |  |   $self->reinit_after_new_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('add'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_add_from_sales_invoice {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   unless ($::form->{from_id}) {
 | 
  
    |  |     $self->js->flash('error', t8("Can't create new reclamation. No 'from_id' was given."));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   require SL::DB::Invoice;
 | 
  
    |  |   my $invoice = SL::DB::Invoice->new(id => $::form->{from_id})->load;
 | 
  
    |  |   my $reclamation = $invoice->convert_to_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation($reclamation);
 | 
  
    |  | 
 | 
  
    |  |   $self->reinit_after_new_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('add'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_add_from_purchase_invoice {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   unless ($::form->{from_id}) {
 | 
  
    |  |     $self->js->flash('error', t8("Can't create new reclamation. No 'from_id' was given."));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   require SL::DB::PurchaseInvoice;
 | 
  
    |  |   my $invoice = SL::DB::PurchaseInvoice->new(id => $::form->{from_id})->load;
 | 
  
    |  |   $invoice->{type} = $invoice->invoice_type; #can't add type → invoice_type in SL/DB/PurchaseInvoice
 | 
  
    |  |   my $reclamation = $invoice->convert_to_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation($reclamation);
 | 
  
    |  | 
 | 
  
    |  |   $self->reinit_after_new_reclamation();
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('add'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # edit an existing reclamation
 | 
  
    |  | sub action_edit {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   unless ($::form->{id}) {
 | 
  
    |  |     $self->js->flash('error', t8("Can't edit unsaved reclamation. No 'id' was given."));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->load_reclamation;
 | 
  
    |  | 
 | 
  
    |  |   $self->recalc();
 | 
  
    |  |   $self->pre_render();
 | 
  
    |  | 
 | 
  
    |  |   $self->render(
 | 
  
    |  |     'reclamation/form',
 | 
  
    |  |     title => $self->get_title_for('edit'),
 | 
  
    |  |     %{$self->{template_args}},
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # delete the reclamation
 | 
  
    |  | sub action_delete {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   my $errors = $self->delete();
 | 
  
    |  | 
 | 
  
    |  |   if (scalar @{ $errors }) {
 | 
  
    |  |     $self->js->flash('error', $_) foreach @{ $errors };
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   flash_later('info', t8('The reclamation has been deleted'));
 | 
  
    |  | 
 | 
  
    |  |   my @redirect_params = (
 | 
  
    |  |     action => 'add',
 | 
  
    |  |     type   => $self->type,
 | 
  
    |  |   );
 | 
  
    |  | 
 | 
  
    |  |   $self->redirect_to(@redirect_params);
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # save the reclamation
 | 
  
    |  | sub action_save {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   my $errors = $self->save();
 | 
  
    |  |   if (scalar @{ $errors }) {
 | 
  
    |  |     $self->js->flash('error', $_) foreach @{ $errors };
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  |   flash_later('info', t8('The reclamation has been saved'));
 | 
  
    |  | 
 | 
  
    |  |   my @redirect_params = (
 | 
  
    |  |     action => 'edit',
 | 
  
    |  |     type   => $self->type,
 | 
  
    |  |     id     => $self->reclamation->id,
 | 
  
    |  |   );
 | 
  
    |  |   $self->redirect_to(@redirect_params);
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_list {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->_setup_search_action_bar;
 | 
  
    |  |   $self->prepare_report;
 | 
  
    |  |   $self->report_generator_list_objects(
 | 
  
    |  |     report => $self->{report},
 | 
  
    |  |     objects => $self->models->get,
 | 
  
    |  |     options => {
 | 
  
    |  |       action_bar_additional_submit_values => {
 | 
  
    |  |         type => $self->type,
 | 
  
    |  |       },
 | 
  
    |  |     },
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # save the reclamation as new document an open it for edit
 | 
  
    |  | sub action_save_as_new {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   my $reclamation = $self->reclamation;
 | 
  
    |  | 
 | 
  
    |  |   if (!$reclamation->id) {
 | 
  
    |  |     $self->js->flash('error', t8('This object has not been saved yet.'));
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   # load reclamation from db to check if values changed
 | 
  
    |  |   my $saved_reclamation = SL::DB::Reclamation->new(id => $reclamation->id)->load;
 | 
  
    |  | 
 | 
  
    |  |   my %new_attrs;
 | 
  
    |  |   # If it has been changed manually then use it as-is, otherwise change.
 | 
  
    |  |   $new_attrs{record_number} = (trim($reclamation->record_number) eq $saved_reclamation->record_number)
 | 
  
    |  |                             ? ''
 | 
  
    |  |                             : trim($reclamation->record_number);
 | 
  
    |  |   $new_attrs{transdate} = ($reclamation->transdate == $saved_reclamation->transdate)
 | 
  
    |  |                         ? DateTime->today_local
 | 
  
    |  |                         : $reclamation->transdate;
 | 
  
    |  |   if ($reclamation->reqdate == $saved_reclamation->reqdate) {
 | 
  
    |  |     $new_attrs{reqdate} = '';
 | 
  
    |  |   } else {
 | 
  
    |  |     $new_attrs{reqdate} = $reclamation->reqdate;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   # Update employee
 | 
  
    |  |   $new_attrs{employee}  = SL::DB::Manager::Employee->current;
 | 
  
    |  | 
 | 
  
    |  |   # Create new record from current one
 | 
  
    |  |   $self->reclamation(
 | 
  
    |  |            SL::DB::Reclamation->new_from(
 | 
  
    |  |              $reclamation,
 | 
  
    |  |              destination_type   => $reclamation->type,
 | 
  
    |  |              attributes         => \%new_attrs,
 | 
  
    |  |              no_linked_records => 1,
 | 
  
    |  |            )
 | 
  
    |  |          );
 | 
  
    |  | 
 | 
  
    |  |   if (!$::form->{form_validity_token}) {
 | 
  
    |  |     $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_RECLAMATION_SAVE())->token;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   # save
 | 
  
    |  |   $self->action_save();
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # print the reclamation
 | 
  
    |  | #
 | 
  
    |  | # This is called if "print" is pressed in the print dialog.
 | 
  
    |  | # If PDF creation was requested and succeeded, the pdf is offered for download
 | 
  
    |  | # via send_file (which uses ajax in this case).
 | 
  
    |  | sub action_print {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->save_with_render_error();
 | 
  
    |  | 
 | 
  
    |  |   $self->js_reset_reclamation_and_item_ids_after_save;
 | 
  
    |  | 
 | 
  
    |  |   my $format      = $::form->{print_options}->{format};
 | 
  
    |  |   my $media       = $::form->{print_options}->{media};
 | 
  
    |  |   my $formname    = $::form->{print_options}->{formname};
 | 
  
    |  |   my $copies      = $::form->{print_options}->{copies};
 | 
  
    |  |   my $groupitems  = $::form->{print_options}->{groupitems};
 | 
  
    |  |   my $printer_id  = $::form->{print_options}->{printer_id};
 | 
  
    |  | 
 | 
  
    |  |   # only pdf and opendocument by now
 | 
  
    |  |   if (none { $format eq $_ } qw(pdf opendocument opendocument_pdf)) {
 | 
  
    |  |     return $self->js->flash('error', t8('Format \'#1\' is not supported yet/anymore.', $format))->render;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   # only screen or printer by now
 | 
  
    |  |   if (none { $media eq $_ } qw(screen printer)) {
 | 
  
    |  |     return $self->js->flash('error', t8('Media \'#1\' is not supported yet/anymore.', $media))->render;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   # create a form for generate_attachment_filename
 | 
  
    |  |   my $form   = Form->new;
 | 
  
    |  |   $form->{record_number} = $self->reclamation->record_number;
 | 
  
    |  |   $form->{type}          = $self->type;
 | 
  
    |  |   $form->{format}        = $format;
 | 
  
    |  |   $form->{formname}      = $formname;
 | 
  
    |  |   $form->{language}      = '_' . $self->reclamation->language->template_code if $self->reclamation->language;
 | 
  
    |  |   my $pdf_filename       = $form->generate_attachment_filename();
 | 
  
    |  | 
 | 
  
    |  |   my $pdf;
 | 
  
    |  |   my @errors = generate_pdf($self->reclamation, \$pdf, {
 | 
  
    |  |                               format     => $format,
 | 
  
    |  |                               formname   => $formname,
 | 
  
    |  |                               language   => $self->reclamation->language,
 | 
  
    |  |                               printer_id => $printer_id,
 | 
  
    |  |                               groupitems => $groupitems,
 | 
  
    |  |                             });
 | 
  
    |  |   if (scalar @errors) {
 | 
  
    |  |     return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   if ($media eq 'screen') { # screen/download
 | 
  
    |  |     $self->js->flash('info', t8('The PDF has been created'));
 | 
  
    |  |     $self->send_file(
 | 
  
    |  |       \$pdf,
 | 
  
    |  |       type         => SL::MIME->mime_type_from_ext($pdf_filename),
 | 
  
    |  |       name         => $pdf_filename,
 | 
  
    |  |       js_no_render => 1,
 | 
  
    |  |     );
 | 
  
    |  |   } elsif ($media eq 'printer') { # printer
 | 
  
    |  |     my $printer_id = $::form->{print_options}->{printer_id};
 | 
  
    |  |     SL::DB::Printer->new(id => $printer_id)->load->print_document(
 | 
  
    |  |       copies  => $copies,
 | 
  
    |  |       content => $pdf,
 | 
  
    |  |     );
 | 
  
    |  |     $self->js->flash('info', t8('The PDF has been printed'));
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   my @warnings = store_pdf_to_webdav_and_filemanagement($self->reclamation, $pdf, $pdf_filename);
 | 
  
    |  |   if (scalar @warnings) {
 | 
  
    |  |     $self->js->flash('warning', $_) for @warnings;
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->save_history('PRINTED');
 | 
  
    |  | 
 | 
  
    |  |   $self->js
 | 
  
    |  |     ->run('kivi.ActionBar.setEnabled', '#save_and_email_action')
 | 
  
    |  |     ->render;
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_preview_pdf {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->save_with_render_error();
 | 
  
    |  | 
 | 
  
    |  |   $self->js_reset_reclamation_and_item_ids_after_save;
 | 
  
    |  | 
 | 
  
    |  |   my $format      = 'pdf';
 | 
  
    |  |   my $media       = 'screen';
 | 
  
    |  |   my $formname    = $self->type;
 | 
  
    |  | 
 | 
  
    |  |   # only pdf
 | 
  
    |  |   # create a form for generate_attachment_filename
 | 
  
    |  |   my $form   = Form->new;
 | 
  
    |  |   $form->{record_number} = $self->reclamation->record_number;
 | 
  
    |  |   $form->{type}          = $self->type;
 | 
  
    |  |   $form->{format}        = $format;
 | 
  
    |  |   $form->{formname}      = $formname;
 | 
  
    |  |   $form->{language}      = '_' . $self->reclamation->language->template_code if $self->reclamation->language;
 | 
  
    |  |   my $pdf_filename       = $form->generate_attachment_filename();
 | 
  
    |  | 
 | 
  
    |  |   my $pdf;
 | 
  
    |  |   my @errors = generate_pdf($self->reclamation, \$pdf, {
 | 
  
    |  |                              format     => $format,
 | 
  
    |  |                              formname   => $formname,
 | 
  
    |  |                              language   => $self->reclamation->language,
 | 
  
    |  |                            });
 | 
  
    |  |   if (scalar @errors) {
 | 
  
    |  |     return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render;
 | 
  
    |  |   }
 | 
  
    |  |   $self->save_history('PREVIEWED');
 | 
  
    |  |   $self->js->flash('info', t8('The PDF has been previewed'));
 | 
  
    |  |   # screen/download
 | 
  
    |  |   $self->send_file(
 | 
  
    |  |     \$pdf,
 | 
  
    |  |     type         => SL::MIME->mime_type_from_ext($pdf_filename),
 | 
  
    |  |     name         => $pdf_filename,
 | 
  
    |  |     js_no_render => 0,
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # open the email dialog
 | 
  
    |  | sub action_save_and_show_email_dialog {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->save_with_render_error();
 | 
  
    |  | 
 | 
  
    |  |   unless ($self->reclamation->customervendor) {
 | 
  
    |  |     return $self->js->flash('error',
 | 
  
    |  |                             $self->cv eq 'customer' ?
 | 
  
    |  |                                 t8('Cannot send E-mail without customer given')
 | 
  
    |  |                               : t8('Cannot send E-mail without vendor given'))
 | 
  
    |  |                     ->render($self);
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   my $form = Form->new;
 | 
  
    |  |   $form->{record_number}    = $self->reclamation->record_number;
 | 
  
    |  |   $form->{cv_record_number} = $self->reclamation->cv_record_number;
 | 
  
    |  |   $form->{formname}         = $self->type;
 | 
  
    |  |   $form->{type}             = $self->type;
 | 
  
    |  |   $form->{language}         = '_' . $self->reclamation->language->template_code if $self->reclamation->language;
 | 
  
    |  |   $form->{language_id}      = $self->reclamation->language->id                  if $self->reclamation->language;
 | 
  
    |  |   $form->{format}           = 'pdf';
 | 
  
    |  |   $form->{cp_id}            = $self->reclamation->contact->cp_id if $self->reclamation->contact;
 | 
  
    |  | 
 | 
  
    |  |   my $email_form;
 | 
  
    |  |   $email_form->{to}   = $self->reclamation->contact->cp_email if $self->reclamation->contact;
 | 
  
    |  |   $email_form->{to} ||= $self->reclamation->customervendor->email;
 | 
  
    |  |   $email_form->{cc}   = $self->reclamation->customervendor->cc;
 | 
  
    |  |   $email_form->{bcc}  = join ', ', grep $_, $self->reclamation->customervendor->bcc, SL::DB::Default->get->global_bcc;
 | 
  
    |  |   # TODO: get addresses from shipto, if any
 | 
  
    |  |   $email_form->{subject}             = $form->generate_email_subject();
 | 
  
    |  |   $email_form->{attachment_filename} = $form->generate_attachment_filename();
 | 
  
    |  |   $email_form->{message}             = $form->generate_email_body();
 | 
  
    |  |   $email_form->{js_send_function}    = 'kivi.Reclamation.send_email()';
 | 
  
    |  | 
 | 
  
    |  |   my %files = $self->get_files_for_email_dialog();
 | 
  
    |  |   $self->{all_employees} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
 | 
  
    |  |   my $dialog_html = $self->render('common/_send_email_dialog', { output => 0 },
 | 
  
    |  |                                   email_form  => $email_form,
 | 
  
    |  |                                   show_bcc    => $::auth->assert('email_bcc', 'may fail'),
 | 
  
    |  |                                   FILES       => \%files,
 | 
  
    |  |                                   is_customer => $self->cv eq 'customer',
 | 
  
    |  |                                   ALL_EMPLOYEES => $self->{all_employees},
 | 
  
    |  |   );
 | 
  
    |  | 
 | 
  
    |  |   $self->js
 | 
  
    |  |       ->run('kivi.Reclamation.show_email_dialog', $dialog_html)
 | 
  
    |  |       ->reinit_widgets
 | 
  
    |  |       ->render($self);
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # send email
 | 
  
    |  | #
 | 
  
    |  | # TODO: handling error messages: flash is not displayed in dialog, but in the main form
 | 
  
    |  | sub action_send_email {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   my $errors = $self->save();
 | 
  
    |  | 
 | 
  
    |  |   if (scalar @{ $errors }) {
 | 
  
    |  |     $self->js->run('kivi.Reclamation.close_email_dialog');
 | 
  
    |  |     $self->js->flash('error', $_) foreach @{ $errors };
 | 
  
    |  |     return $self->js->render();
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $self->js_reset_reclamation_and_item_ids_after_save;
 | 
  
    |  | 
 | 
  
    |  |   # move $::form->{email_form} to $::form
 | 
  
    |  |   my $email_form  = delete $::form->{email_form};
 | 
  
    |  |   my %field_names = (to => 'email');
 | 
  
    |  |   $::form->{ $field_names{$_} // $_ } = $email_form->{$_} for keys %{ $email_form };
 | 
  
    |  | 
 | 
  
    |  |   # for Form::cleanup which may be called in Form::send_email
 | 
  
    |  |   $::form->{cwd}    = getcwd();
 | 
  
    |  |   $::form->{tmpdir} = $::lx_office_conf{paths}->{userspath};
 | 
  
    |  | 
 | 
  
    |  |   $::form->{$_}     = $::form->{print_options}->{$_} for keys %{$::form->{print_options}};
 | 
  
    |  |   $::form->{media}  = 'email';
 | 
  
    |  | 
 | 
  
    |  |   if (($::form->{attachment_policy} // '') !~ m{^(?:old_file|no_file)$}) {
 | 
  
    |  |     my $pdf;
 | 
  
    |  |     my @errors = generate_pdf($self->reclamation, \$pdf, {
 | 
  
    |  |                                media      => $::form->{media},
 | 
  
    |  |                                format     => $::form->{print_options}->{format},
 | 
  
    |  |                                formname   => $::form->{print_options}->{formname},
 | 
  
    |  |                                language   => $self->reclamation->language,
 | 
  
    |  |                                printer_id => $::form->{print_options}->{printer_id},
 | 
  
    |  |                                groupitems => $::form->{print_options}->{groupitems}
 | 
  
    |  |                              });
 | 
  
    |  |     if (scalar @errors) {
 | 
  
    |  |       return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render($self);
 | 
  
    |  |     }
 | 
  
    |  | 
 | 
  
    |  |     my @warnings = store_pdf_to_webdav_and_filemanagement($self->reclamation, $pdf, $::form->{attachment_filename});
 | 
  
    |  |     if (scalar @warnings) {
 | 
  
    |  |       flash_later('warning', $_) for @warnings;
 | 
  
    |  |     }
 | 
  
    |  | 
 | 
  
    |  |     my $sfile = SL::SessionFile::Random->new(mode => "w");
 | 
  
    |  |     $sfile->fh->print($pdf);
 | 
  
    |  |     $sfile->fh->close;
 | 
  
    |  | 
 | 
  
    |  |     $::form->{tmpfile} = $sfile->file_name;
 | 
  
    |  |     $::form->{tmpdir}  = $sfile->get_path; # for Form::cleanup which may be called in Form::send_email
 | 
  
    |  |   }
 | 
  
    |  | 
 | 
  
    |  |   $::form->{id} = $self->reclamation->id; # this is used in SL::Mailer to create a linked record to the mail
 | 
  
    |  |   $::form->send_email(\%::myconfig, 'pdf');
 | 
  
    |  | 
 | 
  
    |  |   # internal notes
 | 
  
    |  |   my $intnotes = $self->reclamation->intnotes;
 | 
  
    |  |   $intnotes   .= "\n\n" if $self->reclamation->intnotes;
 | 
  
    |  |   $intnotes   .= t8('[email]')                                       . "\n";
 | 
  
    |  |   $intnotes   .= t8('Date')       . ": " . $::locale->format_date_object(
 | 
  
    |  |                                              DateTime->now_local,
 | 
  
    |  |                                              precision => 'seconds') . "\n";
 | 
  
    |  |   $intnotes   .= t8('To (email)') . ": " . $::form->{email}          . "\n";
 | 
  
    |  |   $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};
 | 
  
    |  | 
 | 
  
    |  |   $self->reclamation->update_attributes(intnotes => $intnotes);
 | 
  
    |  | 
 | 
  
    |  |   $self->save_history('MAILED');
 | 
  
    |  | 
 | 
  
    |  |   flash_later('info', t8('The email has been sent.'));
 | 
  
    |  | 
 | 
  
    |  |   my @redirect_params = (
 | 
  
    |  |     action => 'edit',
 | 
  
    |  |     type   => $self->type,
 | 
  
    |  |     id     => $self->reclamation->id,
 | 
  
    |  |   );
 | 
  
    |  | 
 | 
  
    |  |   $self->redirect_to(@redirect_params);
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | sub action_save_and_order {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   my $to_type = $self->reclamation->is_sales ? 'sales_order'
 | 
  
    |  |                                              : 'purchase_order';
 | 
  
    |  | 
 | 
  
    |  |   $self->save_with_render_error();
 | 
  
    |  |   flash_later('info', t8('The reclamation has been saved'));
 | 
  
    |  |   $self->redirect_to(
 | 
  
    |  |     controller => 'Order',
 | 
  
    |  |     action     => 'add_from_reclamation',
 | 
  
    |  |     type       => $to_type,
 | 
  
    |  |     from_id    => $self->reclamation->id,
 | 
  
    |  |   );
 | 
  
    |  | }
 | 
  
    |  | 
 | 
  
    |  | # workflow from purchase to sales reclamation
 | 
  
    |  | sub action_save_and_sales_reclamation {
 | 
  
    |  |   my ($self) = @_;
 | 
  
    |  | 
 | 
  
    |  |   $self->save_with_render_error();
 | 
  
    |  |