Verkaufsrechnungen direkt als Factur-X/ZUGFeRD-XML exportieren können
[kivitendo-erp.git] / bin / mozilla / is.pl
index abbcef7..12deb26 100644 (file)
@@ -43,6 +43,7 @@ use List::Util qw(max sum);
 use List::UtilsBy qw(sort_by);
 use English qw(-no_match_vars);
 
+use SL::DB::BankTransactionAccTrans;
 use SL::DB::Default;
 use SL::DB::Customer;
 use SL::DB::Department;
@@ -96,7 +97,7 @@ sub add {
 
   $form->{callback} = "$form->{script}?action=add&type=$form->{type}" unless $form->{callback};
 
-  &invoice_links;
+  invoice_links(is_new => 1);
   &prepare_invoice;
   &display_form;
 
@@ -153,6 +154,7 @@ sub invoice_links {
   # Delay access check to after the invoice's been loaded so that
   # project-specific invoice rights can be evaluated.
 
+  my %params   = @_;
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
 
@@ -171,6 +173,8 @@ sub invoice_links {
 
   IS->get_customer(\%myconfig, \%$form);
 
+  $form->{billing_address_id} = $form->{default_billing_address_id} if $params{is_new};
+
   $form->restore_vars(qw(id));
 
   IS->retrieve_invoice(\%myconfig, \%$form);
@@ -272,13 +276,24 @@ sub prepare_invoice {
 }
 
 sub setup_is_action_bar {
+  my ($tmpl_var)              = @_;
   my $form                    = $::form;
   my $change_never            = $::instance_conf->get_is_changeable == 0;
   my $change_on_same_day_only = $::instance_conf->get_is_changeable == 2 && ($form->current_date(\%::myconfig) ne $form->{gldate});
   my $payments_balanced       = ($::form->{oldtotalpaid} == 0);
   my $has_storno              = ($::form->{storno} && !$::form->{storno_id});
   my $may_edit_create         = $::auth->assert('invoice_edit', 1);
+  my $factur_x_enabled        = $tmpl_var->{invoice_obj} && $tmpl_var->{invoice_obj}->customer->create_zugferd_invoices_for_this_customer;
+  my ($is_linked_bank_transaction, $warn_unlinked_delivery_order);
+    if ($::form->{id}
+        && SL::DB::Default->get->payments_changeable != 0
+        && SL::DB::Manager::BankTransactionAccTrans->find_by(ar_id => $::form->{id})) {
 
+      $is_linked_bank_transaction = 1;
+    }
+  if ($::instance_conf->get_warn_no_delivery_order_for_invoice && !$form->{id}) {
+    $warn_unlinked_delivery_order = 1 unless $form->{convert_from_do_ids};
+  }
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
       action => [
@@ -288,7 +303,6 @@ sub setup_is_action_bar {
                    : $form->{locked}   ? t8('The billing period has already been locked.')
                    :                     undef,
         id        => 'update_button',
-        checks    => [ 'kivi.validate_form' ],
         accesskey => 'enter',
       ],
 
@@ -297,20 +311,23 @@ sub setup_is_action_bar {
           t8('Post'),
           submit   => [ '#form', { action => "post" } ],
           checks   => [ 'kivi.validate_form' ],
+          confirm  => t8('The invoice is not linked with a sales delivery order. Post anyway?') x !!$warn_unlinked_delivery_order,
           disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
                     : $form->{locked}                           ? t8('The billing period has already been locked.')
                     : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
                     : ($form->{id} && $change_never)            ? t8('Changing invoices has been disabled in the configuration.')
                     : ($form->{id} && $change_on_same_day_only) ? t8('Invoices can only be changed on the day they are posted.')
+                    : $is_linked_bank_transaction               ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.')
                     :                                             undef,
         ],
         action => [
           t8('Post Payment'),
           submit   => [ '#form', { action => "post_payment" } ],
           checks   => [ 'kivi.validate_form' ],
-          disabled => !$may_edit_create ? t8('You must not change this invoice.')
-                    : !$form->{id}      ? t8('This invoice has not been posted yet.')
-                    :                     undef,
+          disabled => !$may_edit_create           ? t8('You must not change this invoice.')
+                    : !$form->{id}                ? t8('This invoice has not been posted yet.')
+                    : $is_linked_bank_transaction ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.')
+                    :                               undef,
         ],
         action => [ t8('Mark as paid'),
           submit   => [ '#form', { action => "mark_as_paid" } ],
@@ -329,6 +346,8 @@ sub setup_is_action_bar {
           checks   => [ 'kivi.validate_form' ],
           disabled => !$may_edit_create   ? t8('You must not change this invoice.')
                     : !$form->{id}        ? t8('This invoice has not been posted yet.')
+                    : $form->{storno}     ? t8('Cannot storno storno invoice!')
+                    : $form->{locked}     ? t8('The billing period has already been locked.')
                     : !$payments_balanced ? t8('Cancelling is disallowed. Either undo or balance the current payments until the open amount matches the invoice amount')
                     : undef,
         ],
@@ -365,6 +384,7 @@ sub setup_is_action_bar {
           disabled => !$may_edit_create              ? t8('You must not change this invoice.')
                     : $form->{type} eq "credit_note" ? t8('Credit notes cannot be converted into other credit notes.')
                     : !$form->{id}                   ? t8('This invoice has not been posted yet.')
+                    : $form->{storno}                ? t8('A canceled invoice cannot be used. Please undo the cancellation first.')
                     :                                  undef,
         ],
         action => [
@@ -386,19 +406,33 @@ sub setup_is_action_bar {
                     :                                   undef,
         ],
         action => [ t8('Print and Post'),
-          call     => [ 'kivi.SalesPurchase.show_print_dialog', $form->{id} ? 'print' : 'print_and_post' ],
+          call     => [ 'kivi.SalesPurchase.show_print_dialog', 'print_and_post' ],
           checks   => [ 'kivi.validate_form' ],
-          disabled => !$may_edit_create ? t8('You must not print this invoice.')
-                    : $form->{id}       ? t8('This invoice has already been posted.')
-                    :                     undef,,
+          confirm  => t8('The invoice is not linked with a sales delivery order. Post anyway?') x !!$warn_unlinked_delivery_order,
+          disabled => !$may_edit_create                         ? t8('You must not change this invoice.')
+                    : $form->{locked}                           ? t8('The billing period has already been locked.')
+                    : $form->{storno}                           ? t8('A canceled invoice cannot be posted.')
+                    : ($form->{id} && $change_never)            ? t8('Changing invoices has been disabled in the configuration.')
+                    : ($form->{id} && $change_on_same_day_only) ? t8('Invoices can only be changed on the day they are posted.')
+                    : $is_linked_bank_transaction               ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.')
+                    :                                             undef,
         ],
         action => [ t8('E Mail'),
           call     => [ 'kivi.SalesPurchase.show_email_dialog' ],
           checks   => [ 'kivi.validate_form' ],
-          disabled => !$may_edit_create ? t8('You must not print this invoice.')
-                    : !$form->{id}      ? t8('This invoice has not been posted yet.')
+          disabled => !$may_edit_create       ? t8('You must not print this invoice.')
+                    : !$form->{id}            ? t8('This invoice has not been posted yet.')
+                    : $form->{postal_invoice} ? t8('This customer wants a postal invoices.')
                     :                     undef,
         ],
+        action => [ t8('Factur-X/ZUGFeRD'),
+          submit   => [ '#form', { action => "download_factur_x_xml" } ],
+          checks   => [ 'kivi.validate_form' ],
+          disabled => !$may_edit_create  ? t8('You must not print this invoice.')
+                    : !$form->{id}       ? t8('This invoice has not been posted yet.')
+                    : !$factur_x_enabled ? t8('Creating Factur-X/ZUGFeRD invoices is not enabled for this customer.')
+                    :                      undef,
+        ],
       ], # end of combobox "Export"
 
       combobox => [
@@ -443,6 +477,9 @@ sub form_header {
   $TMPL_VAR{customer_obj} = SL::DB::Customer->load_cached($form->{customer_id}) if $form->{customer_id};
   $TMPL_VAR{invoice_obj}  = SL::DB::Invoice->load_cached($form->{id})           if $form->{id};
 
+  # only print, no mail
+  $form->{postal_invoice} = $TMPL_VAR{customer_obj}->postal_invoice if ref $TMPL_VAR{customer_obj} eq 'SL::DB::Customer';
+
   my $current_employee   = SL::DB::Manager::Employee->current;
   $form->{employee_id}   = $form->{old_employee_id} if $form->{old_employee_id};
   $form->{salesman_id}   = $form->{old_salesman_id} if $form->{old_salesman_id};
@@ -456,6 +493,7 @@ sub form_header {
                    "price_factors" => "ALL_PRICE_FACTORS");
 
   $form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted;
+  $form->{ALL_LANGUAGES}   = SL::DB::Manager::Language->get_all_sorted;
 
   # Projects
   my @old_project_ids = uniq grep { $_ } map { $_ * 1 } ($form->{"globalproject_id"}, map { $form->{"project_id_$_"} } 1..$form->{"rowcount"});
@@ -527,14 +565,14 @@ sub form_header {
     invoice_id
     show_details
   ), @custom_hiddens,
-  map { $_.'_rate', $_.'_description', $_.'_taxnumber' } split / /, $form->{taxaccounts}];
+  map { $_.'_rate', $_.'_description', $_.'_taxnumber', $_.'_tax_id' } split / /, $form->{taxaccounts}];
 
   $::request->{layout}->use_javascript(map { "${_}.js" } qw(kivi.Draft kivi.File kivi.SalesPurchase kivi.Part kivi.CustomerVendor kivi.Validator ckeditor/ckeditor ckeditor/adapters/jquery kivi.io client_js));
 
   $TMPL_VAR{payment_terms_obj} = get_payment_terms_for_invoice();
   $form->{duedate}             = $TMPL_VAR{payment_terms_obj}->calc_date(reference_date => $form->{invdate}, due_date => $form->{duedate})->to_kivitendo if $TMPL_VAR{payment_terms_obj};
 
-  setup_is_action_bar();
+  setup_is_action_bar(\%TMPL_VAR);
 
   $form->header();
 
@@ -573,12 +611,6 @@ sub form_footer {
 
   $form->{invtotal}    = $form->{invsubtotal};
 
-  # note rows
-  $form->{rows} = max 2,
-    $form->numtextrows($form->{notes},    26, 8),
-    $form->numtextrows($form->{intnotes}, 35, 8);
-
-
   # tax, total and subtotal calculations
   my ($tax, $subtotal);
   $form->{taxaccounts_array} = [ split(/ /, $form->{taxaccounts}) ];
@@ -712,6 +744,7 @@ sub update {
     $::form->{salesman_id} = SL::DB::Manager::Employee->current->id if exists $::form->{salesman_id};
 
     IS->get_customer(\%myconfig, $form);
+    $::form->{billing_address_id} = $::form->{default_billing_address_id};
   }
 
   $form->{taxincluded} ||= $taxincluded;
@@ -724,10 +757,7 @@ sub update {
 
   for my $i (1 .. $form->{paidaccounts}) {
     next unless $form->{"paid_$i"};
-    map { $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) } qw(paid exchangerate);
-    if (!$form->{"forex_$i"}) {   #read exchangerate from input field (not hidden)
-      $form->{exchangerate} = $form->{"exchangerate_$i"};
-    }
+    map { $form->{"${_}_$i"}   = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) } qw(paid exchangerate);
     $form->{"forex_$i"}        = $form->check_exchangerate(\%myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
     $form->{"exchangerate_$i"} = $form->{"forex_$i"} if $form->{"forex_$i"};
   }