Skip to content

Commit 449d5cb

Browse files
implement SellerTaxRepresentativeTradeParty
some fixes for null values enhance #SKONTO output in XRechnung profile
1 parent 0584b1b commit 449d5cb

6 files changed

+62
-25
lines changed

intf.ZUGFeRDInvoiceDescriptor.pas

+19
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ TZUGFeRDInvoiceDescriptor = class
9797
FSellerContact: TZUGFeRDContact;
9898
FSellerTaxRegistration: TObjectList<TZUGFeRDTaxRegistration>;
9999
FSellerElectronicAddress: TZUGFeRDElectronicAddress;
100+
FSellerTaxRepresentative: TZUGFeRDParty;
101+
FSellerTaxRepresentativeTaxRegistration: TObjectList<TZUGFeRDTaxRegistration>;
100102
FInvoicee: TZUGFeRDParty;
101103
FInvoiceeTaxRegistration: TObjectList<TZUGFeRDTaxRegistration>;
102104
FShipTo: TZUGFeRDParty;
@@ -242,6 +244,9 @@ TZUGFeRDInvoiceDescriptor = class
242244
property SellerTaxRegistration: TObjectList<TZUGFeRDTaxRegistration> read FSellerTaxRegistration;
243245
property SellerElectronicAddress : TZUGFeRDElectronicAddress read FSellerElectronicAddress;
244246

247+
property SellerTaxRepresentative: TZUGFeRDParty read FSellerTaxRepresentative write FSellerTaxRepresentative;
248+
property SellerTaxRepresentativeTaxRegistration: TObjectList<TZUGFeRDTaxRegistration> read FSellerTaxRepresentativeTaxRegistration;
249+
245250
/// <summary>
246251
/// Given seller reference number for routing purposes after biliteral agreement
247252
///
@@ -589,6 +594,8 @@ TZUGFeRDInvoiceDescriptor = class
589594

590595
procedure AddSellerTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
591596

597+
procedure AddSellerTaxRepresentativeTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
598+
592599
procedure AddInvoiceeTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
593600

594601
procedure AddShipToTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
@@ -902,6 +909,8 @@ constructor TZUGFeRDInvoiceDescriptor.Create;
902909
FSellerContact := nil;//TZUGFeRDContact.Create;
903910
FSellerTaxRegistration := TObjectList<TZUGFeRDTaxRegistration>.Create;
904911
FSellerElectronicAddress := TZUGFeRDElectronicAddress.Create;
912+
FSellerTaxRepresentative := nil;//TZUGFeRDParty.Create;
913+
FSellerTaxRepresentativeTaxRegistration := TObjectList<TZUGFeRDTaxRegistration>.Create;
905914
FInvoicee := nil;//TZUGFeRDParty.Create;
906915
FInvoiceeTaxRegistration := TObjectList<TZUGFeRDTaxRegistration>.Create;
907916
FInvoicer := nil;//TZUGFeRDParty.Create;
@@ -941,6 +950,8 @@ destructor TZUGFeRDInvoiceDescriptor.Destroy;
941950
if Assigned(FSellerContact ) then begin FSellerContact.Free; FSellerContact := nil; end;
942951
if Assigned(FSellerTaxRegistration ) then begin FSellerTaxRegistration.Free; FSellerTaxRegistration := nil; end;
943952
if Assigned(FSellerElectronicAddress ) then begin FSellerElectronicAddress.Free; FSellerElectronicAddress := nil; end;
953+
if Assigned(FSellerTaxRepresentative ) then begin FSellerTaxRepresentative.Free; FSellerTaxRepresentative := nil; end;
954+
if Assigned(FSellerTaxRepresentativeTaxRegistration ) then begin FSellerTaxRepresentativeTaxRegistration.Free; FSellerTaxRepresentativeTaxRegistration := nil; end;
944955
if Assigned(FInvoicee ) then begin FInvoicee.Free; FInvoicee := nil; end;
945956
if Assigned(FInvoiceeTaxRegistration ) then begin FInvoiceeTaxRegistration.Free; FInvoiceeTaxRegistration := nil; end;
946957
if Assigned(FInvoicer ) then begin FInvoicer.Free; FInvoicer := nil; end;
@@ -1364,6 +1375,13 @@ procedure TZUGFeRDInvoiceDescriptor.AddSellerTaxRegistration(const no: string; c
13641375
FSellerTaxRegistration[SellerTaxRegistration.Count - 1].SchemeID := schemeID;
13651376
end;
13661377

1378+
procedure TZUGFeRDInvoiceDescriptor.AddSellerTaxRepresentativeTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
1379+
begin
1380+
FSellerTaxRepresentativeTaxRegistration.Add(TZUGFeRDTaxRegistration.Create);
1381+
FSellerTaxRepresentativeTaxRegistration[SellerTaxRepresentativeTaxRegistration.Count - 1].No := no;
1382+
FSellerTaxRepresentativeTaxRegistration[SellerTaxRepresentativeTaxRegistration.Count - 1].SchemeID := schemeID;
1383+
end;
1384+
13671385
procedure TZUGFeRDInvoiceDescriptor.AddInvoiceeTaxRegistration(const no: string; const schemeID: TZUGFeRDTaxRegistrationSchemeID);
13681386
begin
13691387
FInvoiceeTaxRegistration.Add(TZUGFeRDTaxRegistration.Create);
@@ -1548,6 +1566,7 @@ procedure TZUGFeRDInvoiceDescriptor.AddApplicableTradeTax(const calculatedAmount
15481566
tax.LineTotalBasisAmount := lineTotalBasisAmount;
15491567
tax.ExemptionReasonCode := exemptionReasonCode;
15501568
tax.ExemptionReason := exemptionReason;
1569+
tax.TaxPointDate := taxPointDate;
15511570
tax.DueDateTypeCode := dueDateTypeCode;
15521571

15531572
if (categoryCode <> TZUGFeRDTaxCategoryCodes.Unknown) then

intf.ZUGFeRDInvoiceDescriptor1Writer.pas

+3-2
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ procedure TZUGFeRDInvoiceDescriptor1Writer.Save(
372372
Writer.WriteElementString('udt:Indicator', ifthen(tradeAllowanceCharge.ChargeIndicator,'true','false'));
373373
Writer.WriteEndElement(); // !ram:ChargeIndicator
374374

375-
if tradeAllowanceCharge.BasisAmount <> 0.0 then
375+
if tradeAllowanceCharge.BasisAmount.HasValue then
376376
begin
377377
Writer.WriteStartElement('ram:BasisAmount', [TZUGFeRDProfile.Extended]);
378378
Writer.WriteAttributeString('currencyID', TZUGFeRDCurrencyCodesExtensions.EnumToString(tradeAllowanceCharge.Currency));
@@ -876,7 +876,8 @@ procedure TZUGFeRDInvoiceDescriptor1Writer._writeOptionalParty(
876876
_writer.WriteOptionalElementString('ram:LineTwo', Party.Street);
877877
end;
878878
_writer.WriteOptionalElementString('ram:CityName', Party.City);
879-
_writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(Party.Country));
879+
if party.Country<>TZUGFeRDCountryCodes.Unknown then
880+
writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(party.Country)); //buyer: BT-55
880881
_writer.WriteEndElement(); // !PostalTradeAddress
881882

882883
if (TaxRegistrations <> nil) then

intf.ZUGFeRDInvoiceDescriptor20Writer.pas

+3-4
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ procedure TZUGFeRDInvoiceDescriptor20Writer.Save(
752752
Writer.WriteElementString('udt:Indicator', ifthen(tradeAllowanceCharge.ChargeIndicator,'true','false'));
753753
Writer.WriteEndElement(); // !ram:ChargeIndicator
754754

755-
if tradeAllowanceCharge.BasisAmount <> 0.0 then
755+
if tradeAllowanceCharge.BasisAmount.HasValue then
756756
begin
757757
Writer.WriteStartElement('ram:BasisAmount');
758758
Writer.WriteValue(_formatDecimal(tradeAllowanceCharge.BasisAmount));
@@ -1097,12 +1097,11 @@ procedure TZUGFeRDInvoiceDescriptor20Writer._writeOptionalParty(
10971097
_writer.WriteOptionalElementString('ram:PostcodeCode', Party.Postcode);
10981098
_writer.WriteOptionalElementString('ram:LineOne', ifthen(Party.ContactName = '', Party.Street,Party.ContactName));
10991099
if (Party.ContactName <> '') then
1100-
begin
11011100
_writer.WriteOptionalElementString('ram:LineTwo', Party.Street);
1102-
end;
11031101
_writer.WriteOptionalElementString('ram:LineThree', Party.AddressLine3); // BT-163
11041102
_writer.WriteOptionalElementString('ram:CityName', Party.City);
1105-
_writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(Party.Country));
1103+
if party.Country<>TZUGFeRDCountryCodes.Unknown then
1104+
writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(party.Country)); //buyer: BT-55
11061105
_writer.WriteOptionalElementString('ram:CountrySubDivisionName', Party.CountrySubdivisionName); // BT-79
11071106
_writer.WriteEndElement(); // !PostalTradeAddress
11081107

intf.ZUGFeRDInvoiceDescriptor23CIIReader.pas

+10
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,16 @@ function TZUGFeRDInvoiceDescriptor23CIIReader.Load(xmldocument : IXMLDocument):
323323
);
324324
end;
325325

326+
Result.SellerTaxRepresentative := _nodeAsParty(doc.DocumentElement, '//ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty');
327+
nodes := doc.selectNodes('//ram:ApplicableHeaderTradeAgreement/ram:SellerTaxRepresentativeTradeParty/ram:SpecifiedTaxRegistration');
328+
for i := 0 to nodes.length-1 do
329+
begin
330+
var id : String := TZUGFeRDXmlUtils.NodeAsString(nodes[i], './/ram:ID');
331+
var schemeID : String := TZUGFeRDXmlUtils.NodeAsString(nodes[i], './/ram:ID/@schemeID');
332+
Result.AddSellerTaxRepresentativeTaxRegistration(id, TZUGFeRDTaxRegistrationSchemeIDExtensions.FromString(schemeID));
333+
end;
334+
335+
326336
//Get all referenced and embedded documents (BG-24)
327337
nodes := doc.SelectNodes('.//ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument');
328338
for i := 0 to nodes.length-1 do

intf.ZUGFeRDInvoiceDescriptor23CIIWriter.pas

+25-18
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter.Save(
591591
//#endregion
592592

593593
//#region ChargePercentage
594-
if (specifiedTradeAllowanceCharge.ChargePercentage <> 0.0) then
594+
if (specifiedTradeAllowanceCharge.ChargePercentage.HasValue) then
595595
begin
596596
Writer.WriteStartElement('ram:CalculationPercent');
597597
Writer.WriteValue(_formatDecimal(specifiedTradeAllowanceCharge.ChargePercentage, 2));
@@ -600,7 +600,7 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter.Save(
600600
//#endregion
601601

602602
//#region BasisAmount
603-
if (specifiedTradeAllowanceCharge.BasisAmount <> 0.0) then
603+
if (specifiedTradeAllowanceCharge.BasisAmount.HasValue) then
604604
begin
605605
// according to CII-SR-123 not in XRechnung for *Applied*TradeAllowanceCharge but valid for *Specified*TradeAllowanceCharge!
606606
Writer.WriteStartElement('ram:BasisAmount', ALL_PROFILES-[TZUGFeRDProfile.Basic]); // BT-137, BT-142
@@ -725,8 +725,10 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter.Save(
725725
_writeOptionalParty(Writer, TZUGFeRDPartyTypes.BuyerTradeParty, Descriptor.Buyer, Descriptor.BuyerContact, Descriptor.BuyerElectronicAddress, Descriptor.BuyerTaxRegistration);
726726
//#endregion
727727

728-
// TODO: implement SellerTaxRepresentativeTradeParty
728+
//region SellerTaxRepresentativeTradeParty
729729
// BT-63: the tax registration of the SellerTaxRepresentativeTradeParty
730+
_writeOptionalParty(Writer, TZUGFeRDPartyTypes.SellerTaxRepresentativeTradeParty, Descriptor.SellerTaxRepresentative, Nil, Nil, Descriptor.SellerTaxRepresentativeTaxRegistration);
731+
//#endregion
730732

731733
//#region SellerOrderReferencedDocument (BT-14: Comfort, Extended)
732734
if (Descriptor.SellerOrderReferencedDocument <> nil) then
@@ -1048,14 +1050,14 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter.Save(
10481050
Writer.WriteElementString('udt:Indicator', ifthen(tradeAllowanceCharge.ChargeIndicator,'true','false'));
10491051
Writer.WriteEndElement(); // !ram:ChargeIndicator
10501052

1051-
if (tradeAllowanceCharge.ChargePercentage <> 0.0) then
1053+
if (tradeAllowanceCharge.ChargePercentage.HasValue) then
10521054
begin
10531055
Writer.WriteStartElement('ram:CalculationPercent');
10541056
Writer.WriteValue(_formatDecimal(tradeAllowanceCharge.ChargePercentage, 2));
10551057
Writer.WriteEndElement();
10561058
end;
10571059

1058-
if (tradeAllowanceCharge.BasisAmount <> 0.0) then
1060+
if (tradeAllowanceCharge.BasisAmount.HasValue) then
10591061
begin
10601062
Writer.WriteStartElement('ram:BasisAmount'); // BT-100
10611063
Writer.WriteValue(_formatDecimal(tradeAllowanceCharge.BasisAmount));
@@ -1131,7 +1133,7 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter.Save(
11311133
PaymentNote:= System.StrUtils.ReplaceText(Trim(PaymentTerms.Description),'#',' '); // make sure no # is present
11321134
if PaymentNote<>'' then
11331135
PaymentNote:= PaymentNote+#13#10;
1134-
if PaymentTerms.PaymentTermsType.HasValue then
1136+
if PaymentTerms.PaymentTermsType.HasValue and PaymentTerms.DueDays.HasValue and PaymentTerms.Percentage.HasValue then
11351137
begin
11361138
var formatSettings: TFormatSettings;
11371139
formatSettings.DecimalSeparator := '.';
@@ -1516,6 +1518,8 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter._writeOptionalParty(
15161518
writer.WriteStartElement('ram:InvoiceeTradeParty', [Descriptor.Profile]);
15171519
TZUGFeRDPartyTypes.PayeeTradeParty:
15181520
writer.WriteStartElement('ram:PayeeTradeParty', [Descriptor.Profile]);
1521+
TZUGFeRDPartyTypes.PayerTradeParty:
1522+
writer.WriteStartElement('ram:PayerTradeParty', [Descriptor.Profile]);
15191523
TZUGFeRDPartyTypes.SalesAgentTradeParty:
15201524
writer.WriteStartElement('ram:SalesAgentTradeParty', [Descriptor.Profile]);
15211525
TZUGFeRDPartyTypes.BuyerTaxRepresentativeTradeParty:
@@ -1526,8 +1530,8 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter._writeOptionalParty(
15261530
writer.WriteStartElement('ram:BuyerAgentTradeParty', [Descriptor.Profile]);
15271531
TZUGFeRDPartyTypes.InvoicerTradeParty:
15281532
writer.WriteStartElement('ram:InvoicerTradeParty', [Descriptor.Profile]);
1529-
TZUGFeRDPartyTypes.PayerTradeParty:
1530-
writer.WriteStartElement('ram:PayerTradeParty', [Descriptor.Profile]);
1533+
TZUGFeRDPartyTypes.SellerTaxRepresentativeTradeParty:
1534+
writer.WriteStartElement('ram:SellerTaxRepresentativeTradeParty', [Descriptor.Profile]);
15311535
else
15321536
exit;
15331537
end;
@@ -1563,19 +1567,22 @@ procedure TZUGFeRDInvoiceDescriptor23CIIWriter._writeOptionalParty(
15631567
_writeOptionalLegalOrganization(writer, 'ram:SpecifiedLegalOrganization', party.SpecifiedLegalOrganization, partyType);
15641568
_writeOptionalContact(writer, 'ram:DefinedTradeContact', contact, [TZUGFeRDProfile.Comfort,TZUGFeRDProfile.Extended,TZUGFeRDProfile.XRechnung1,TZUGFeRDProfile.XRechnung]);
15651569

1566-
writer.WriteStartElement('ram:PostalTradeAddress');
1567-
writer.WriteOptionalElementString('ram:PostcodeCode', party.Postcode); //buyer: BT-53
1568-
writer.WriteOptionalElementString('ram:LineOne', ifthen(party.ContactName='',party.Street,party.ContactName)); //buyer: BT-50
1569-
if (party.ContactName<>'')then
1570+
// spec 2.3 says: Minimum/BuyerTradeParty does not include PostalTradeAddress
1571+
if (Descriptor.Profile = TZUGFeRDProfile.Extended) or (partyType In [TZUGFeRDPartyTypes.BuyerTradeParty, TZUGFeRDPartyTypes.SellerTradeParty, TZUGFeRDPartyTypes.SellerTaxRepresentativeTradeParty, TZUGFeRDPartyTypes.BuyerTaxRepresentativeTradeParty, TZUGFeRDPartyTypes.ShipToTradeParty, TZUGFeRDPartyTypes.ShipToTradeParty, TZUGFeRDPartyTypes.UltimateShipToTradeParty, TZUGFeRDPartyTypes.SalesAgentTradeParty]) then
15701572
begin
1573+
writer.WriteStartElement('ram:PostalTradeAddress');
1574+
writer.WriteOptionalElementString('ram:PostcodeCode', party.Postcode); //buyer: BT-53
1575+
writer.WriteOptionalElementString('ram:LineOne', ifthen(party.ContactName='',party.Street,party.ContactName)); //buyer: BT-50
1576+
if (party.ContactName<>'') then
15711577
writer.WriteOptionalElementString('ram:LineTwo', party.Street); //buyer: BT-51
1572-
end;
15731578

1574-
writer.WriteOptionalElementString('ram:LineThree', party.AddressLine3); //buyer: BT-163
1575-
writer.WriteOptionalElementString('ram:CityName', party.City); //buyer: BT-52
1576-
writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(party.Country)); //buyer: BT-55
1577-
writer.WriteOptionalElementString('ram:CountrySubDivisionName', party.CountrySubdivisionName); // BT-79
1578-
writer.WriteEndElement(); // !PostalTradeAddress
1579+
writer.WriteOptionalElementString('ram:LineThree', party.AddressLine3); //buyer: BT-163
1580+
writer.WriteOptionalElementString('ram:CityName', party.City); //buyer: BT-52
1581+
if party.Country<>TZUGFeRDCountryCodes.Unknown then
1582+
writer.WriteElementString('ram:CountryID', TZUGFeRDCountryCodesExtensions.EnumToString(party.Country)); //buyer: BT-55
1583+
writer.WriteOptionalElementString('ram:CountrySubDivisionName', party.CountrySubdivisionName); // BT-79
1584+
writer.WriteEndElement(); // !PostalTradeAddress
1585+
end;
15791586

15801587
if (electronicAddress <> nil) then
15811588
begin

intf.ZUGFeRDPartyTypes.pas

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ interface
3434
ProductEndUserTradeParty,
3535
BuyerAgentTradeParty,
3636
InvoicerTradeParty,
37-
PayerTradeParty
37+
PayerTradeParty,
38+
SellerTaxRepresentativeTradeParty
3839
);
3940

4041
implementation

0 commit comments

Comments
 (0)