Factur-X/ZUGFeRD: UStID-Nr des Kunden nur ausgeben, wenn tatsächlich angegeben
[kivitendo-erp.git] / SL / DB / Helper / ZUGFeRD.pm
index 0511256..5455398 100644 (file)
@@ -13,6 +13,7 @@ use SL::DB::TaxKey;
 use SL::Helper::ISO3166;
 use SL::Helper::ISO4217;
 use SL::Helper::UNECERecommendation20;
+use SL::VATIDNr;
 
 use Carp;
 use Encode qw(encode);
@@ -213,7 +214,6 @@ sub _taxes {
     $info->{taxkey}    //= SL::DB::TaxKey->load_cached($item->{taxkey_id});
     $info->{tax}       //= SL::DB::Tax->load_cached($info->{taxkey}->tax_id);
     $info->{linetotal}  += $item->{linetotal};
-    $info->{tax_amount} += $item->{tax_amount};
   }
 
   foreach my $taxkey_id (sort keys %taxkey_info) {
@@ -222,7 +222,7 @@ sub _taxes {
 
     #     <ram:ApplicableTradeTax>
     $params{xml}->startTag("ram:ApplicableTradeTax");
-    $params{xml}->dataElement("ram:CalculatedAmount",      _r2($params{ptc_data}->{taxes}->{$info->{tax}->{chart_id}}));
+    $params{xml}->dataElement("ram:CalculatedAmount",      _r2($params{ptc_data}->{taxes_by_tax_id}->{$info->{taxkey}->tax_id}));
     $params{xml}->dataElement("ram:TypeCode",              "VAT");
     $params{xml}->dataElement("ram:BasisAmount",           _r2($info->{linetotal}));
     $params{xml}->dataElement("ram:CategoryCode",          $tax_info{code});
@@ -325,7 +325,7 @@ sub _totals {
 
   $params{xml}->dataElement("ram:LineTotalAmount",     _r2($self->netamount));
   $params{xml}->dataElement("ram:TaxBasisTotalAmount", _r2($self->netamount));
-  $params{xml}->dataElement("ram:TaxTotalAmount",      _r2(sum(values %{ $params{ptc_data}->{taxes} })), currencyID => "EUR");
+  $params{xml}->dataElement("ram:TaxTotalAmount",      _r2(sum(values %{ $params{ptc_data}->{taxes_by_tax_id} })), currencyID => "EUR");
   $params{xml}->dataElement("ram:GrandTotalAmount",    _r2($self->amount));
   $params{xml}->dataElement("ram:TotalPrepaidAmount",  _r2($self->paid));
   $params{xml}->dataElement("ram:DuePayableAmount",    _r2($self->amount - $self->paid));
@@ -409,13 +409,9 @@ sub _exchanged_document {
 sub _specified_tax_registration {
   my ($ustid_nr, %params) = @_;
 
-  return unless $ustid_nr;
-
-  $ustid_nr = "DE$ustid_nr" unless $ustid_nr =~ m{^[A-Z]{2}};
-
   #         <ram:SpecifiedTaxRegistration>
   $params{xml}->startTag("ram:SpecifiedTaxRegistration");
-  $params{xml}->dataElement("ram:ID", _u8($ustid_nr), schemeID => "VA");
+  $params{xml}->dataElement("ram:ID", _u8(SL::VATIDNr->normalize($ustid_nr)), schemeID => "VA");
   $params{xml}->endTag;
   #         </ram:SpecifiedTaxRegistration>
 }
@@ -439,7 +435,7 @@ sub _seller_trade_party {
   #         <ram:DefinedTradeContact>
   $params{xml}->startTag("ram:DefinedTradeContact");
 
-  $params{xml}->dataElement("ram:PersonName", _u8($sales_person_cfg{name} || $sales_person_cfg{login}));
+  $params{xml}->dataElement("ram:PersonName", _u8($sales_person->safe_name));
 
   if ($sales_person_cfg{tel}) {
     $params{xml}->startTag("ram:TelephoneUniversalCommunication");
@@ -481,7 +477,7 @@ sub _buyer_trade_party {
   $params{xml}->dataElement("ram:Name", _u8($self->customer->name));
 
   _customer_postal_trade_address(%params, customer => $self->customer);
-  _specified_tax_registration($self->customer->ustid, %params);
+  _specified_tax_registration($self->customer->ustid, %params) if $self->customer->ustid;
 
   $params{xml}->endTag;
   #       </ram:BuyerTradeParty>
@@ -577,6 +573,10 @@ sub _validate_data {
     SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('The VAT registration number is missing in the client configuration.'));
   }
 
+  if (!SL::VATIDNr->validate($::instance_conf->get_co_ustid)) {
+    SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text("The VAT ID number in the client configuration is invalid."));
+  }
+
   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.'));
   }