Kunden/Lieferanten: UStId/Steuernr. eindeutig: Prüfung im Controller
authorBernd Bleßmann <bernd@kivitendo-premium.de>
Tue, 5 Jan 2021 16:15:22 +0000 (17:15 +0100)
committerBernd Bleßmann <bernd@kivitendo-premium.de>
Mon, 11 Jan 2021 10:06:32 +0000 (11:06 +0100)
SL/Controller/CustomerVendor.pm
locale/de/all
locale/en/all

index 6106a4a..5470284 100644 (file)
@@ -10,6 +10,7 @@ use SL::DBUtils;
 use SL::Helper::Flash;
 use SL::Locale::String;
 use SL::Util qw(trim);
+use SL::VATIDNr;
 use SL::Webdav;
 use SL::ZUGFeRD;
 use SL::Controller::Helper::GetModels;
@@ -132,6 +133,62 @@ sub action_show {
   }
 }
 
+sub _check_ustid_taxnumber_unique {
+  my ($self) = @_;
+
+  my %cfg;
+  if ($self->is_vendor()) {
+    %cfg = (should_check  => $::instance_conf->get_vendor_ustid_taxnummer_unique,
+            manager_class => 'SL::DB::Manager::Vendor',
+            err_ustid     => t8('A vendor with the same VAT ID already exists.'),
+            err_taxnumber => t8('A vendor with the same taxnumber already exists.'),
+    );
+
+  } elsif ($self->is_customer()) {
+    %cfg = (should_check  => $::instance_conf->get_customer_ustid_taxnummer_unique,
+            manager_class => 'SL::DB::Manager::Customer',
+            err_ustid     => t8('A customer with the same VAT ID already exists.'),
+            err_taxnumber => t8('A customer with the same taxnumber already exists.'),
+    );
+
+  } else {
+    return;
+  }
+
+  my @errors;
+
+  if ($cfg{should_check}) {
+    my $do_clean_taxnumber = sub { my $n = $_[0]; $n //= ''; $n =~ s{[[:space:].-]+}{}g; return $n};
+
+    my $clean_ustid     = SL::VATIDNr->clean($self->{cv}->ustid);
+    my $clean_taxnumber = $do_clean_taxnumber->($self->{cv}->taxnumber);
+
+    if (!($clean_ustid || $clean_taxnumber)) {
+      return t8('VAT ID and/or taxnumber must be given.');
+
+    } else {
+      my $clean_number = $clean_ustid;
+      if ($clean_number) {
+        my $entries = $cfg{manager_class}->get_all(query => ['!id' => $self->{cv}->id, '!ustid' => undef, '!ustid' => ''], select => ['ustid'], distinct => 1);
+        if (any { $clean_number eq SL::VATIDNr->clean($_->ustid) } @$entries) {
+          push @errors, $cfg{err_ustid};
+        }
+      }
+
+      $clean_number = $clean_taxnumber;
+      if ($clean_number) {
+        my $entries = $cfg{manager_class}->get_all(query => ['!id' => $self->{cv}->id, '!taxnumber' => undef, '!taxnumber' => ''], select => ['taxnumber'], distinct => 1);
+        if (any { $clean_number eq $do_clean_taxnumber->($_->taxnumber) } @$entries) {
+          push @errors, $cfg{err_taxnumber};
+        }
+      }
+    }
+  }
+
+  return join "\n", @errors if @errors;
+  return;
+}
+
 sub _save {
   my ($self) = @_;
 
@@ -185,6 +242,9 @@ sub _save {
       }
     }
 
+    my $ustid_taxnumber_error = $self->_check_ustid_taxnumber_unique;
+    $::form->error($ustid_taxnumber_error) if $ustid_taxnumber_error;
+
     $self->{cv}->save(cascade => 1);
 
     SL::DB::Greeting->new(description => $self->{cv}->greeting)->save if $save_greeting;
index 60fccd6..0bcdf63 100755 (executable)
@@ -55,6 +55,8 @@ $self->{texts} = {
   'A canceled general ledger transaction cannot be deleted.' => 'Eine stornierte Dialogbuchung kann nicht gelöscht werden.',
   'A canceled general ledger transaction cannot be posted.' => 'Eine stornierte Dialogbuchung kann nicht mehr gebucht werden.',
   'A canceled invoice cannot be posted.' => 'Eine stornierte Rechnung kann nicht mehr gebucht werden.',
+  'A customer with the same VAT ID already exists.' => 'Ein Kunde mit der gleichen USt-IdNr. existiert bereits.',
+  'A customer with the same taxnumber already exists.' => 'Ein Kunde mit der gleichen Steuernummer existiert bereits.',
   'A digit is required.'        => 'Eine Ziffer ist vorgeschrieben.',
   'A directory with the name for the new print templates exists already.' => 'Ein Verzeichnis mit dem selben Namen wie die neuen Druckvorlagen existiert bereits.',
   'A lot of the usability of kivitendo has been enhanced with javascript. Although it is currently possible to use every aspect of kivitendo without javascript, we strongly recommend it. In a future version this may change and javascript may be necessary to access advanced features.' => 'Die Bedienung von kivitendo wurde an vielen Stellen mit Javascript verbessert. Obwohl es derzeit möglich ist, jeden Aspekt von kivitendo auch ohne Javascript zu benutzen, empfehlen wir es. In einer zukünftigen Version wird Javascript eventuell notwendig sein um weitergehende Features zu benutzen.',
@@ -67,6 +69,8 @@ $self->{texts} = {
   'A valid taxkey is missing!'  => 'Ein gültiger Steuerschlüssel fehlt!',
   'A variable marked as \'Deactivate by default\' isn\'t automatically added to all articles, and has to be explicitly added for each desired article in its master data tab. Only then can the variable be used for that article in the records.' => 'Eine als \'Deaktiviert als Voreinstellung\' markierte Variable wird nicht automatisch bei allen Artikeln hinzugefügt, sondern muß explizit für jeden gewünschten Artikel in den Stammdaten aktiviert werden. Erst danach ist die Variable für den Artikel in Belegen bearbeitbar.',
   'A variable marked as \'editable\' can be changed in each quotation, order, invoice etc.' => 'Eine als \'editierbar\' markierte Variable kann in jedem Angebot, Auftrag, jeder Rechnung etc für jede Position geändert werden.',
+  'A vendor with the same VAT ID already exists.' => 'Ein Lieferant mit der gleichen USt-IdNr. existiert bereits.',
+  'A vendor with the same taxnumber already exists.' => 'Ein Lieferant mit der gleichen Steuernummer existiert bereits.',
   'ADDED'                       => 'Hinzugefügt',
   'AP'                          => 'Einkauf',
   'AP Aging'                    => 'Offene Verbindlichkeiten',
@@ -3924,6 +3928,7 @@ $self->{texts} = {
   'Usually the delivery date of an order is the next working day. If a value is set here this value will be added to the delivery date of the sales order. The resulting date will be adjusted to the next working day if it ends up on a weekend.' => 'Standardmäßig ist das vorausgewählte Lieferdatum der nächste Arbeitstag. Falls hier ein Wert gesetzt ist, wird dieser zum eigentlichen Lieferdatum hinzuaddiert. Fällt das daraus resultierende Datum auf ein Wochenende, so wird der nächste Werktag genommen.',
   'Usually the sales quotation is valid until the next working day. If a value is set here then the quotation will be valid for at least that many days. The resulting date will be adjusted to the next working day if it ends up on a weekend.' => 'Standardmäßig ist ein Verkaufsangebot bis zum nächsten Werktag gültig. Ist hier ein Wert angegeben, so ist ein Angebot mindestens so viele Tage gültig. Sollte das dabei herauskommende Datum auf ein Wochenende fallen, so wird statt dessen der nachfolgende Arbeitstag genommen.',
   'VAT ID'                      => 'USt-IdNr.',
+  'VAT ID and/or taxnumber must be given.' => 'UStId und/oder Steuernummer muss angegeben werden.',
   'VN'                          => 'Kred.-Nr.',
   'Valid'                       => 'Gültig',
   'Valid from'                  => 'Gültig ab',
index 680427c..6035ebd 100644 (file)
@@ -55,6 +55,8 @@ $self->{texts} = {
   'A canceled general ledger transaction cannot be deleted.' => '',
   'A canceled general ledger transaction cannot be posted.' => '',
   'A canceled invoice cannot be posted.' => '',
+  'A customer with the same VAT ID already exists.' => '',
+  'A customer with the same taxnumber already exists.' => '',
   'A digit is required.'        => '',
   'A directory with the name for the new print templates exists already.' => '',
   'A lot of the usability of kivitendo has been enhanced with javascript. Although it is currently possible to use every aspect of kivitendo without javascript, we strongly recommend it. In a future version this may change and javascript may be necessary to access advanced features.' => '',
@@ -67,6 +69,8 @@ $self->{texts} = {
   'A valid taxkey is missing!'  => '',
   'A variable marked as \'Deactivate by default\' isn\'t automatically added to all articles, and has to be explicitly added for each desired article in its master data tab. Only then can the variable be used for that article in the records.' => '',
   'A variable marked as \'editable\' can be changed in each quotation, order, invoice etc.' => '',
+  'A vendor with the same VAT ID already exists.' => '',
+  'A vendor with the same taxnumber already exists.' => '',
   'ADDED'                       => '',
   'AP'                          => 'Purchases',
   'AP Aging'                    => 'Creditor Aging',
@@ -3923,6 +3927,7 @@ $self->{texts} = {
   'Usually the delivery date of an order is the next working day. If a value is set here this value will be added to the delivery date of the sales order. The resulting date will be adjusted to the next working day if it ends up on a weekend.' => '',
   'Usually the sales quotation is valid until the next working day. If a value is set here then the quotation will be valid for at least that many days. The resulting date will be adjusted to the next working day if it ends up on a weekend.' => '',
   'VAT ID'                      => '',
+  'VAT ID and/or taxnumber must be given.' => '',
   'VN'                          => '',
   'Valid'                       => '',
   'Valid from'                  => '',