]> wagnertech.de Git - kivitendo-erp.git/commitdiff
ZUGFeRD: Validierung diverser nötiger Parameter
authorMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 28 Feb 2020 16:13:34 +0000 (17:13 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 28 Feb 2020 16:24:00 +0000 (17:24 +0100)
SL/DB/Helper/ZUGFeRD.pm
SL/X.pm
bin/mozilla/io.pl
locale/de/all

index 5cee13a3e36ea9b07366bede9e877b00ffa22e76..b129de4fe4fa1726e002070d85e21a920718245a 100644 (file)
@@ -15,7 +15,7 @@ use SL::Helper::UNECERecommendation20;
 
 use Carp;
 use Encode qw(encode);
-use List::MoreUtils qw(pairwise);
+use List::MoreUtils qw(any pairwise);
 use List::Util qw(first sum);
 use Template;
 use XML::Writer;
@@ -515,9 +515,42 @@ sub _supply_chain_trade_transaction {
   #   </rsm:SupplyChainTradeTransaction>
 }
 
+sub _validate_data {
+  my ($self) = @_;
+
+  my $prefix = $::locale->text('The ZUGFeRD invoice data cannot be generated because the data validation failed.') . ' ';
+
+  if (!$::instance_conf->get_co_ustid) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The VAT registration number is missing in the client configuration.'));
+  }
+
+  if (!$::instance_conf->get_company || any { my $get = "get_address_$_"; !$::instance_conf->$get } qw(street1 zipcode city)) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The company\'s address information is incomplete in the client configuration.'));
+  }
+
+  if ($::instance_conf->get_address_country && !SL::Helper::ISO3166::map_name_to_alpha_2_code($::instance_conf->get_address_country)) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The country from the company\'s address in the client configuration cannot be mapped to an ISO 3166-1 alpha 2 code.'));
+  }
+
+  if ($self->customer->country && !SL::Helper::ISO3166::map_name_to_alpha_2_code($self->customer->country)) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The country from the customer\'s address cannot be mapped to an ISO 3166-1 alpha 2 code.'));
+  }
+
+  if (!SL::Helper::ISO4217::map_currency_name_to_code($self->currency->name)) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The currency "#1" cannot be mapped to an ISO 4217 currency code.', $self->currency->name));
+  }
+
+  my $failed_unit = first { !SL::Helper::UNECERecommendation20::map_name_to_code($_) } map { $_->unit } @{ $self->items };
+  if ($failed_unit) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('One of the units used (#1) cannot be mapped to a known unit code from the UN/ECE Recommendation 20 list.', $failed_unit));
+  }
+}
+
 sub create_zugferd_data {
   my ($self) = @_;
 
+  _validate_data($self);
+
   my %ptc_data = $self->calculate_prices_and_taxes;
   my $output   = '';
   my $xml      = XML::Writer->new(
diff --git a/SL/X.pm b/SL/X.pm
index 756793b90d6e7cb403f88f43d81651e86f9150d2..b8ae60ac632d36d45975c46c691ae026cb8a6c6a 100644 (file)
--- a/SL/X.pm
+++ b/SL/X.pm
@@ -27,6 +27,9 @@ use Exception::Class (
   'SL::X::DBUtilsError' => {
     isa                 => 'SL::X::DBError',
   },
+  'SL::X::ZUGFeRDValidation' => {
+    isa                 => 'SL::X::Base',
+  },
 );
 
 1;
index 1ee0d2c090ff61bf1d7ce80f4f8dedb6fe846a18..0cde59cec08488435662692efba1846a271afd84 100644 (file)
@@ -2122,17 +2122,23 @@ sub _maybe_attach_zugferd_data {
 
   return if !$record || !$record->can('create_pdf_a_print_options') || !$record->can('create_zugferd_data');
 
-  my $xmlfile = File::Temp->new;
-  $xmlfile->print($record->create_zugferd_data);
-  $xmlfile->close;
-
-  $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_a}           = $record->create_pdf_a_print_options(zugferd_xmp_data => $record->create_zugferd_xmp_data);
-  $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_attachments} = [
-    { source       => $xmlfile,
-      name         => 'ZUGFeRD-invoice.xml',
-      description  => $::locale->text('ZUGFeRD invoice'),
-      relationship => '/Alternative',
-      mime_type    => 'text/xml',
-    }
-  ];
+  eval {
+    my $xmlfile = File::Temp->new;
+    $xmlfile->print($record->create_zugferd_data);
+    $xmlfile->close;
+
+    $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_a}           = $record->create_pdf_a_print_options(zugferd_xmp_data => $record->create_zugferd_xmp_data);
+    $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_attachments} = [
+      { source       => $xmlfile,
+        name         => 'ZUGFeRD-invoice.xml',
+        description  => $::locale->text('ZUGFeRD invoice'),
+        relationship => '/Alternative',
+        mime_type    => 'text/xml',
+      }
+    ];
+  };
+
+  if (my $e = SL::X::ZUGFeRDValidation->caught) {
+    $::form->error($e->message);
+  }
 }
index 143a02d01ef0df2a90c0896d736492b825cdbfdd..550a53e4a489dce5d849227bb9c51f82d5952014 100755 (executable)
@@ -2133,6 +2133,7 @@ $self->{texts} = {
   'On Order'                    => 'Ist bestellt',
   'On the next page the type of all variables can be set.' => 'Auf der folgenden Seite können die Typen aller Variablen gesetzt werden.',
   'One of the columns "qty" or "target_qty" must be given. If "target_qty" is given, the quantity to transfer for each transfer will be calculate, so that the quantity for this part, warehouse and bin will result in the given "target_qty" after each transfer.' => 'Eine der Spalten "qty" oder "target_qty" muss angegeben werden. Wird "target_qty" angegeben, so wird die zu bewegende Menge für jede Lagerbewegung so berechnet, dass die Lagermenge für diesen Artikel, Lager und Lagerplatz nach jeder Lagerbewegung der angegebenen Zielmenge entspricht.',
+  'One of the units used (#1) cannot be mapped to a known unit code from the UN/ECE Recommendation 20 list.' => 'Eine der verwendeten Einheiten (#1) kann keinem der bekannten Einheiten-Codes aus der Liste UN/ECE Recommendation 20 zugeordnet werden.',
   'One or more Perl modules missing' => 'Ein oder mehr Perl-Module fehlen',
   'Onhand only sets the quantity in master data, not in inventory. This is only a legacy info field and will be overwritten as soon as a inventory transfer happens.' => 'Das Import-Feld Auf Lager setzt nur die Menge in den Stammdaten, nicht im Lagerbereich. Dies ist historisch gewachsen nur ein Informationsfeld was mit dem tatsächlichen Wert überschrieben wird, sobald eine wirkliche Lagerbewegung stattfindet (DB-Trigger).',
   'Only Price'                  => 'Nur Preis',
@@ -3183,7 +3184,9 @@ $self->{texts} = {
   'The SQL query can be parameterized with variables named as follows: <%name%>.' => 'Die SQL-Abfrage kann mittels Variablen wie folgt parametrisiert werden: <%Variablenname%>.',
   'The SQL query does not contain any parameter that need to be configured.' => 'Die SQL-Abfrage enthält keine Parameter, die angegeben werden müssten.',
   'The URL is missing.'         => 'URL fehlt',
+  'The VAT registration number is missing in the client configuration.' => 'Die Umsatzsteuer-ID-Nummer fehlt in der Mandantenkonfiguration.',
   'The WebDAV feature has been used.' => 'Das WebDAV-Feature wurde benutzt.',
+  'The ZUGFeRD invoice data cannot be generated because the data validation failed.' => 'Die ZUGFeRD-Rechnungsdaten können nicht erzeugt werden, da die Validierung fehlschlug.',
   'The ZUGFeRD notes have been saved.' => 'Die ZUGFeRD-Notizen wurden gespeichert.',
   'The abbreviation is missing.' => 'Abkürzung fehlt',
   'The access rights a user has within a client instance is still governed by his group membership.' => 'Welche Zugriffsrechte ein Benutzer innerhalb eines Mandanten hat, wird weiterhin über Gruppenmitgliedschaften geregelt.',
@@ -3237,6 +3240,7 @@ $self->{texts} = {
   'The columns &quot;Dunning Duedate&quot;, &quot;Total Fees&quot; and &quot;Interest&quot; show data for the previous dunning created for this invoice.' => 'Die Spalten &quot;Zahlbar bis&quot;, &quot;Kumulierte Gebühren&quot; und &quot;Zinsen&quot; zeigen Daten der letzten für diese Rechnung erzeugten Mahnung.',
   'The combination of database host, port and name is not unique.' => 'Die Kombination aus Datenbankhost, -port und -name ist nicht eindeutig.',
   'The command is missing.'     => 'Der Befehl fehlt.',
+  'The company\'s address information is incomplete in the client configuration.' => 'Die Firmenadresse in der Mandantenkonfiguration ist unvollständig.',
   'The connection to the LDAP server cannot be encrypted (SSL/TLS startup failure). Please check config/kivitendo.conf.' => 'Die Verbindung zum LDAP-Server kann nicht verschlüsselt werden (Fehler bei SSL/TLS-Initialisierung). Bitte überprüfen Sie die Angaben in config/kivitendo.conf.',
   'The connection to the authentication database failed:' => 'Die Verbindung zur Authentifizierungsdatenbank schlug fehl:',
   'The connection to the configured client database "#1" on host "#2:#3" failed.' => 'Die Verbindung zur konfigurierten Datenbank "#1" auf Host "#2:#3" schlug fehl.',
@@ -3246,8 +3250,11 @@ $self->{texts} = {
   'The connection to the template database failed:' => 'Die Verbindung zur Vorlagendatenbank schlug fehl:',
   'The connection was established successfully.' => 'Die Verbindung zur Datenbank wurde erfolgreich hergestellt.',
   'The contact person attribute "birthday" is converted from a free-form text field into a date field.' => 'Das Kontaktpersonenfeld "Geburtstag" wird von einem freien Textfeld auf ein Datumsfeld umgestellt.',
+  'The country from the company\'s address in the client configuration cannot be mapped to an ISO 3166-1 alpha 2 code.' => 'Das Land der Firmenadresse in der Mandantenkonfiguration kann keinem der bekannten ISO 3166-1 Alpha 2-Codes zugeordnet werden.',
+  'The country from the customer\'s address cannot be mapped to an ISO 3166-1 alpha 2 code.' => 'Das Land aus der Kunden-Rechnungsadresse kann keinem der bekannten ISO 3166-1 Alpha 2-Codes zugeordnet werden.',
   'The creation of the authentication database failed:' => 'Das Anlegen der Authentifizierungsdatenbank schlug fehl:',
   'The credentials (username & password) for connecting database are wrong.' => 'Die Daten (Benutzername & Passwort) für das Login zur Datenbank sind falsch.',
+  'The currency "#1" cannot be mapped to an ISO 4217 currency code.' => 'Die Währung "#1" kann keinem der bekannten ISO 4217-Codes zugeordnet werden.',
   'The custom data export has been deleted.' => 'Der benutzerdefinierte Datenexport wurde gelöscht.',
   'The custom data export has been saved.' => 'Der benutzerdefinierte Datenexport wurde gespeichert.',
   'The custom variable has been created.' => 'Die benutzerdefinierte Variable wurde erfasst.',