+ if ($form->{print_nextsub}) {
+ call_sub($form->{print_nextsub});
+ $main::lxdebug->leave_sub();
+ return;
+ }
+
+ # if this goes to the printer pass through
+ my $old_form;
+ if ($form->{media} eq 'printer' || $form->{media} eq 'queue') {
+ $form->error($locale->text('Select postscript or PDF!'))
+ if ($form->{format} !~ /(postscript|pdf)/);
+
+ $old_form = Form->new;
+ map { $old_form->{$_} = $form->{$_} } keys %$form;
+ }
+
+ if (!$form->{id} || (($form->{formname} eq "proforma") && !$form->{proforma} && (($form->{type} =~ /_order$/) || ($form->{type} =~ /_quotation$/)))) {
+ if ($form->{formname} eq "proforma") {
+ $form->{proforma} = 1;
+ }
+ $form->{print_and_save} = 1;
+ my $formname = $form->{formname};
+ &save();
+ $form->{formname} = $formname;
+ &edit();
+ $::lxdebug->leave_sub();
+ $::dispatcher->end_request;
+ }
+
+ &print_form($old_form);
+
+ $main::lxdebug->leave_sub();
+}
+
+sub print_form {
+ $main::lxdebug->enter_sub();
+
+ my $form = $main::form;
+ my %myconfig = %main::myconfig;
+ my $locale = $main::locale;
+
+ _check_io_auth();
+
+ my $defaults = SL::DB::Default->get;
+ $form->error($::locale->text('No print templates have been created for this client yet. Please do so in the client configuration.')) if !$defaults->templates;
+ $form->{templates} = $defaults->templates;
+
+ my ($old_form, %params) = @_;
+
+ my $inv = "inv";
+ my $due = "due";
+ my $numberfld = "invnumber";
+ my $order;
+
+ my $display_form =
+ ($form->{display_form}) ? $form->{display_form} : "display_form";
+
+ # $form->{"notes"} will be overridden by the customer's/vendor's "notes" field. So save it here.
+ $form->{ $form->{"formname"} . "notes" } = $form->{"notes"};
+
+ if ($form->{formname} eq "invoice") {
+ $form->{label} = $locale->text('Invoice');
+ }
+ if ($form->{formname} eq 'sales_order') {
+ $inv = "ord";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{label} = $locale->text('Confirmation');
+ $numberfld = "sonumber";
+ $order = 1;
+ }
+
+ if (($form->{type} eq 'invoice') && ($form->{formname} eq 'proforma') ) {
+ $inv = "inv";
+ $due = "due";
+ $form->{"${inv}date"} = $form->{invdate};
+ $form->{label} = $locale->text('Proforma Invoice');
+ $numberfld = "sonumber";
+ $order = 0;
+ }
+
+ if (($form->{type} eq 'sales_order') && ($form->{formname} eq 'proforma') ) {
+ $inv = "inv";
+ $due = "due";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{"invdate"} = $form->{transdate};
+ $form->{invnumber} = $form->{ordnumber};
+ $form->{label} = $locale->text('Proforma Invoice');
+ $numberfld = "sonumber";
+ $order = 1;
+ }
+
+ if ($form->{formname} eq 'purchase_order') {
+ $inv = "ord";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{label} = $locale->text('Purchase Order');
+ $numberfld = "ponumber";
+ $order = 1;
+ }
+ if ($form->{formname} eq 'bin_list') {
+ $inv = "ord";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{label} = $locale->text('Bin List');
+ $order = 1;
+ }
+ if ($form->{formname} eq 'sales_quotation') {
+ $inv = "quo";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{label} = $locale->text('Quotation');
+ $numberfld = "sqnumber";
+ $order = 1;
+ }
+
+ if (($form->{type} eq 'sales_quotation') && ($form->{formname} eq 'proforma') ) {
+ $inv = "quo";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{"invdate"} = $form->{transdate};
+ $form->{label} = $locale->text('Proforma Invoice');
+ $numberfld = "sqnumber";
+ $order = 1;
+ }
+
+ if (($form->{type} eq 'sales_order') && ($form->{formname} eq 'ic_supply') ) {
+ $inv = "inv";
+ $due = "due";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{"invdate"} = $form->{transdate};
+ $form->{invnumber} = $form->{ordnumber};
+ $form->{label} = $locale->text('Intra-Community supply');
+ $numberfld = "sonumber";
+ $order = 1;
+ }
+
+ if ($form->{formname} eq 'request_quotation') {
+ $inv = "quo";
+ $due = "req";
+ $form->{"${inv}date"} = $form->{transdate};
+ $form->{label} = $locale->text('RFQ');
+ $numberfld = "rfqnumber";
+ $order = 1;
+ }
+
+ if ($form->{type} =~ /_delivery_order$/) {
+ undef $due;
+ $inv = "do";
+ $form->{"${inv}date"} = $form->{transdate};
+ $numberfld = $form->{type} =~ /^sales/ ? 'sdonumber' : 'pdonumber';
+ $form->{label} = $form->{formname} eq 'pick_list' ? $locale->text('Pick List') : $locale->text('Delivery Order');
+ }
+ if ($form->{type} =~ /letter/) {
+ undef $due;
+ undef $inv;
+ $form->{label} = $locale->text('Letter');
+ }
+
+ $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} = $form->get_variable_content_types();
+ }
+
+ $form->isblank("email", $locale->text('E-mail address missing!'))
+ if ($form->{media} eq 'email');
+ $form->isblank("${inv}date",
+ $locale->text($form->{label})
+ . ": "
+ . $locale->text(' Date missing!'));
+
+ # $locale->text('Invoice Number missing!')
+ # $locale->text('Invoice Date missing!')
+ # $locale->text('Order Number missing!')
+ # $locale->text('Order Date missing!')
+ # $locale->text('Quotation Number missing!')
+ # $locale->text('Quotation Date missing!')
+
+ $form->{what_done} = $form->{formname};
+
+ &validate_items;
+
+ # Save the email address given in the form because it should override the setting saved for the customer/vendor.
+ my ($saved_email, $saved_cc, $saved_bcc) =
+ ($form->{"email"}, $form->{"cc"}, $form->{"bcc"});
+
+ my $language_saved = $form->{language_id};
+ my $payment_id_saved = $form->{payment_id};
+ my $delivery_term_id_saved = $form->{delivery_term_id};
+ my $salesman_id_saved = $form->{salesman_id};
+ my $cp_id_saved = $form->{cp_id};
+ my $taxzone_id_saved = $form->{taxzone_id};
+ my $currency_saved = $form->{currency};
+
+ call_sub("$form->{vc}_details") if ($form->{vc});
+
+ $form->{language_id} = $language_saved;
+ $form->{payment_id} = $payment_id_saved;
+ $form->{delivery_term_id} = $delivery_term_id_saved;
+ $form->{taxzone_id} = $taxzone_id_saved;
+ $form->{currency} = $currency_saved;
+
+ $form->{"email"} = $saved_email if ($saved_email);
+ $form->{"cc"} = $saved_cc if ($saved_cc);
+ $form->{"bcc"} = $saved_bcc if ($saved_bcc);
+
+ if (!$cp_id_saved) {
+ # No contact was selected. Delete all contact variables because
+ # IS->customer_details() and IR->vendor_details() get the default
+ # contact anyway.
+ map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form })));
+ }
+
+ my ($language_tc, $output_numberformat, $output_dateformat, $output_longdates);
+ if ($form->{"language_id"}) {
+ ($language_tc, $output_numberformat, $output_dateformat, $output_longdates) =
+ AM->get_language_details(\%myconfig, $form, $form->{language_id});
+ } else {
+ $output_dateformat = $myconfig{"dateformat"};
+ $output_numberformat = $myconfig{"numberformat"};
+ $output_longdates = 1;
+ }
+
+ # Store the output number format so that the template modules know
+ # how to parse the amounts back if requested.
+ $myconfig{output_numberformat} = $output_numberformat || $myconfig{numberformat};
+
+ ($form->{employee}) = split /--/, $form->{employee};
+
+ # create the form variables
+ if ($form->{type} =~ /_delivery_order$/) {
+ DO->order_details(\%myconfig, \%$form);
+ } elsif ($order) {
+ OE->order_details(\%myconfig, \%$form);
+ } elsif ($form->{type} eq 'letter') {
+ # right now, no details are needed
+ # but i do not want to break the bad default (invoice)
+ } else {
+ IS->invoice_details(\%myconfig, \%$form, $locale);
+ }
+
+ $form->get_employee_data('prefix' => 'employee', 'id' => $form->{employee_id});
+ $form->get_employee_data('prefix' => 'salesman', 'id' => $salesman_id_saved);
+
+ if ($form->{shipto_id}) {
+ $form->get_shipto(\%myconfig);
+ }
+
+ $form->{notes} =~ s/^\s+//g;
+
+ delete $form->{printer_command};
+
+ $form->{language} = $form->get_template_language(\%myconfig);
+
+ my $printer_code;
+ if ($form->{media} ne 'email') {
+ $printer_code = $form->get_printer_code(\%myconfig);
+ if ($printer_code ne "") {
+ $printer_code = "_" . $printer_code;
+ }
+ }
+
+ if ($form->{language} ne "") {
+ my $template_arrays = $form->{TEMPLATE_ARRAYS} || $form;
+ map { $template_arrays->{unit}->[$_] = AM->translate_units($form, $form->{language}, $template_arrays->{unit}->[$_], $template_arrays->{qty}->[$_]); } (0..scalar(@{ $template_arrays->{unit} }) - 1);
+
+ $form->{language} = "_" . $form->{language};
+ }
+
+ # Format dates.
+ format_dates($output_dateformat, $output_longdates,
+ qw(invdate orddate quodate pldate duedate reqdate transdate
+ shippingdate deliverydate validitydate paymentdate
+ datepaid transdate_oe transdate_do transdate_quo deliverydate_oe dodate
+ employee_startdate employee_enddate
+ ),
+ grep({ /^datepaid_\d+$/ ||
+ /^transdate_oe_\d+$/ ||
+ /^transdate_do_\d+$/ ||
+ /^transdate_quo_\d+$/ ||
+ /^deliverydate_oe_\d+$/ ||
+ /^reqdate_\d+$/ ||
+ /^deliverydate_\d+$/ ||
+ /^transdate_\d+$/
+ } keys(%{$form})));
+
+ reformat_numbers($output_numberformat, 2,
+ qw(invtotal ordtotal quototal subtotal linetotal
+ listprice sellprice netprice discount
+ tax taxbase total paid payment),
+ grep({ /^(?:linetotal|nodiscount_linetotal|listprice|sellprice|netprice|taxbase|discount|p_discount|discount_sub|nodiscount_sub|paid|subtotal|total|tax)_\d+$/ } keys(%{$form})));
+
+ reformat_numbers($output_numberformat, undef,
+ qw(qty price_factor),
+ grep({ /^qty_\d+$/
+ } keys(%{$form})));
+
+ my ($cvar_date_fields, $cvar_number_fields) = CVar->get_field_format_list('module' => 'CT', 'prefix' => 'vc_');
+
+ if (scalar @{ $cvar_date_fields }) {
+ format_dates($output_dateformat, $output_longdates, @{ $cvar_date_fields });
+ }
+
+ while (my ($precision, $field_list) = each %{ $cvar_number_fields }) {
+ reformat_numbers($output_numberformat, $precision, @{ $field_list });
+ }
+
+ my $extension = 'html';
+ if ($form->{format} eq 'postscript') {
+ $form->{postscript} = 1;
+ $extension = 'tex';
+
+ } elsif ($form->{"format"} =~ /pdf/) {
+ $form->{pdf} = 1;
+ $extension = $form->{'format'} =~ m/opendocument/i ? 'odt' : 'tex';
+
+ } elsif ($form->{"format"} =~ /opendocument/) {
+ $form->{opendocument} = 1;
+ $extension = 'odt';
+ } elsif ($form->{"format"} =~ /excel/) {
+ $form->{excel} = 1;
+ $extension = 'xls';
+ }
+
+ # search for the template
+ my ($template_file, @template_files) = SL::Helper::CreatePDF->find_template(
+ name => $form->{formname},
+ email => $form->{media} eq 'email',
+ language_id => $form->{language_id},
+ printer_id => $form->{printer_id},
+ extension => $extension,
+ );
+
+ if (!defined $template_file) {
+ $::form->error($::locale->text('Cannot find matching template for this print request. Please contact your template maintainer. I tried these: #1.', join ', ', map { "'$_'"} @template_files));
+ }
+
+ $form->{IN} = $template_file;
+
+ delete $form->{OUT};
+
+ if ($form->{media} eq 'printer') {
+ $form->{OUT} = $form->{printer_command};
+ $form->{OUT_MODE} = '|-';
+ $form->{printed} .= " $form->{formname}";
+ $form->{printed} =~ s/^ //;
+ }
+ my $printed = $form->{printed};
+
+ if ($form->{media} eq 'email') {
+ $form->{subject} = qq|$form->{label} $form->{"${inv}number"}|
+ unless $form->{subject};
+
+ $form->{emailed} .= " $form->{formname}";
+ $form->{emailed} =~ s/^ //;
+ $form->{addition} = "MAILED";
+ }
+ my $emailed = $form->{emailed};
+
+ if ($form->{media} eq 'queue') {
+ my %queued = map { s|.*[/\\]||; $_ } split / /, $form->{queued};
+
+ my $filename;
+ my $suffix = ($form->{postscript}) ? '.ps' : '.pdf';
+ if ($filename = $queued{ $form->{formname} }) {
+ unlink $::lx_office_conf{paths}->{spool} . "/$filename";
+ delete $queued{ $form->{formname} };
+
+ $form->{queued} = join ' ', %queued;
+ $filename =~ s/\..*$//g;
+ $filename .= $suffix;
+ $form->{OUT} = $::lx_office_conf{paths}->{spool} . "/$filename";
+ $form->{OUT_MODE} = '>';
+
+ } else {
+ my $temp_fh;
+ ($temp_fh, $filename) = File::Temp::tempfile(
+ 'kivitendo-spoolXXXXXX',
+ SUFFIX => "$suffix",
+ DIR => $::lx_office_conf{paths}->{spool},
+ UNLINK => 0,
+ );
+ close $temp_fh;
+ $form->{OUT} = "$filename";
+ # use >> for OUT_MODE because file is already created by File::Temp
+ $form->{OUT_MODE} = '>>';
+ # strip directory so that only filename is stored in table status
+ ($filename) = $filename =~ /^$::lx_office_conf{paths}->{spool}\/(.*)/;
+ }
+
+ # add type
+ $form->{queued} .= " $form->{formname} $filename";
+ $form->{queued} =~ s/^ //;
+ }
+ my $queued = $form->{queued};
+
+# saving the history
+ if(!exists $form->{addition}) {
+ $form->{snumbers} = "${inv}number" . "_" . $form->{"${inv}number"};
+ if($form->{media} =~ /printer/) {
+ $form->{addition} = "PRINTED";
+ }
+ elsif($form->{media} =~ /email/) {
+ $form->{addition} = "MAILED";
+ }
+ elsif($form->{media} =~ /queue/) {
+ $form->{addition} = "QUEUED";
+ }
+ elsif($form->{media} =~ /screen/) {
+ $form->{addition} = "SCREENED";
+ }
+ $form->save_history;
+ }
+ # /saving the history
+
+ # prepare meta information for template introspection
+ $form->{template_meta} = {
+ formname => $form->{formname},
+ language => SL::DB::Manager::Language->find_by_or_create(id => $form->{language_id} || undef),
+ format => $form->{format},
+ media => $form->{media},
+ extension => $extension,
+ printer => SL::DB::Manager::Printer->find_by_or_create(id => $form->{printer_id} || undef),
+ today => DateTime->today,
+ };
+
+ $form->parse_template(\%myconfig);
+
+ $form->{callback} = "";
+
+ if ($form->{media} eq 'email') {
+ $form->{message} = $locale->text('sent') unless $form->{message};
+ }
+ my $message = $form->{message};
+
+ # if we got back here restore the previous form
+ if ($form->{media} =~ /(printer|email|queue)/) {
+
+ $form->update_status(\%myconfig)
+ if ($form->{media} eq 'queue' && $form->{id});
+
+ return $main::lxdebug->leave_sub() if ($old_form eq "return");
+
+ if ($old_form) {
+
+ $old_form->{"${inv}number"} = $form->{"${inv}number"};
+
+ # restore and display form
+ map { $form->{$_} = $old_form->{$_} } keys %$old_form;
+
+ $form->{queued} = $queued;
+ $form->{printed} = $printed;
+ $form->{emailed} = $emailed;
+ $form->{message} = $message;
+
+ $form->{rowcount}--;
+ map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
+ qw(exchangerate creditlimit creditremaining);
+
+ for my $i (1 .. $form->{paidaccounts}) {
+ map {
+ $form->{"${_}_$i"} =
+ $form->parse_amount(\%myconfig, $form->{"${_}_$i"})
+ } qw(paid exchangerate);
+ }
+
+ call_sub($display_form);
+ $::dispatcher->end_request;
+ }
+
+ my $msg =
+ ($form->{media} eq 'printer')
+ ? $locale->text('sent to printer')
+ : $locale->text('emailed to') . " $form->{email}";
+
+ if (!$params{no_redirect}) {
+ $form->redirect(qq|$form->{label} $form->{"${inv}number"} $msg|);
+ }
+ }
+ if ($form->{printing}) {
+ call_sub($display_form);
+ $::dispatcher->end_request;
+ }
+
+ $main::lxdebug->leave_sub();
+}
+
+sub customer_details {
+ $main::lxdebug->enter_sub();
+
+ my $form = $main::form;
+ my %myconfig = %main::myconfig;
+
+ IS->customer_details(\%myconfig, \%$form, @_);
+
+ $main::lxdebug->leave_sub();
+}
+
+sub vendor_details {
+ $main::lxdebug->enter_sub();
+
+ my $form = $main::form;
+ my %myconfig = %main::myconfig;
+
+ IR->vendor_details(\%myconfig, \%$form, @_);
+
+ $main::lxdebug->leave_sub();
+}
+
+sub post_as_new {
+ $main::lxdebug->enter_sub();
+
+ my $form = $main::form;
+
+ _check_io_auth();
+
+ $form->{postasnew} = 1;
+ map { delete $form->{$_} } qw(printed emailed queued);
+
+ &post;
+
+ $main::lxdebug->leave_sub();
+}
+
+sub relink_accounts {
+ $main::lxdebug->enter_sub();
+
+ my $form = $main::form;
+ my %myconfig = %main::myconfig;
+
+ _check_io_auth();
+
+ $form->{"taxaccounts"} =~ s/\s*$//;
+ $form->{"taxaccounts"} =~ s/^\s*//;
+ foreach my $accno (split(/\s*/, $form->{"taxaccounts"})) {
+ map({ delete($form->{"${accno}_${_}"}); } qw(rate description taxnumber));
+ }
+ $form->{"taxaccounts"} = "";
+
+ IC->retrieve_accounts(\%myconfig, $form, map { $_ => $form->{"id_$_"} } 1 .. $form->{rowcount});
+
+ $main::lxdebug->leave_sub();
+}
+
+sub get_payment_terms_for_invoice {
+ my $terms = $::form->{payment_id} ? SL::DB::PaymentTerm->new(id => $::form->{payment_id}) ->load
+ : $::form->{customer_id} ? SL::DB::Customer ->new(id => $::form->{customer_id})->load->payment
+ : $::form->{vendor_id} ? SL::DB::Vendor ->new(id => $::form->{vendor_id}) ->load->payment
+ : undef;
+
+ return $terms;
+}
+
+sub set_duedate {
+ _check_io_auth();
+
+ my $js = SL::ClientJS->new(controller => SL::Controller::Base->new);
+ my $terms = get_payment_terms_for_invoice();
+ my $invdate = $::form->{invdate} eq 'undefined' ? DateTime->today_local : DateTime->from_kivitendo($::form->{invdate});
+ my $duedate = $terms ? $terms->calc_date(reference_date => $invdate, due_date => $::form->{duedate})->to_kivitendo : ($::form->{duedate} || $invdate->to_kivitendo);
+
+ if ($terms && $terms->auto_calculation) {
+ $js->hide('#duedate_container')
+ ->show('#duedate_fixed')
+ ->html('#duedate_fixed', $duedate);