# ZUGFeRD XML Field Mapping This document describes the complete mapping between ZUGFeRD XML nodes and c-entron database fields/entities. ## Overview The ZUGFeRD XML generation is implemented in `InvoiceZugferdBL.cs` and supports multiple ZUGFeRD versions: - ZUGFeRD 1.0 (legacy) - ZUGFeRD 2.0 / XRechnung 1.2 - ZUGFeRD 2.1 / XRechnung 2.0, 2.2, 2.3.1 - ZUGFeRD 2.1 / XRechnung 3.0.1 (current) The main data flow is: 1. Load receipt data from `BookKeepingExportBL.LoadReceipt()` → returns `IBookKeepingReceipt` 2. Convert to `ZugferdExportItem` in `GetZugferdExportItem()` 3. Generate XML document with `DoGenerateZugferdXRechnungXmlDocument()` --- ## Document Context & Header ### ExchangedDocumentContext XML structure related to document context and format identification. | XML Node | c-entron Source | Description | |----------|----------------|-------------| | `rsm:GuidelineSpecifiedDocumentContextParameter/ram:ID` | Derived from `ZugferdKind` enum | Format identifier (e.g., "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0") | | `ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID` | Static value | For v3.0.1: "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0" | ### ExchangedDocument Basic invoice/credit voucher information. | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ID` | `Number` | `IBookKeepingReceipt` | Invoice/receipt number | | `ram:TypeCode` | Derived from `Type` | `IBookKeepingReceipt` | "380" = Invoice, "381" = Credit voucher | | `ram:IssueDateTime/udt:DateTimeString` | `Date` | `IBookKeepingReceipt` | Receipt date (format: yyyyMMdd) | | `ram:IncludedNote` | `PaymentConditionsText` | `IBookKeepingReceipt` | Payment text/notes | | `ram:IncludedNote[@SubjectCode="REG"]` | Composed string | Multiple sources | Seller information text (Name, address, CEO, HRB) | | `ram:IncludedNote[@SubjectCode="ABT"]` | `PayeeAssignmentNotice` | Bank info via settings | Assignment notice for bank transfer | --- ## Seller Trade Party (Own Company) The seller represents the own company (Mandator) or branch. | XML Node | c-entron Field | Table/Entity | Path in Code | |----------|----------------|--------------|--------------| | `ram:SellerTradeParty/ram:ID` | `OwnSupplierNumber` | `IBookKeepingReceipt` | Customer's supplier number for own company | | `ram:SellerTradeParty/ram:Name` | `Name` or `Name` | `Branch` or `Mandator` | Branch name (or Mandator if setting/no branch) | | `ram:SellerTradeParty/ram:SpecifiedLegalOrganization/ram:ID` | `HRB` | `Mandator` | Commercial register number | | `ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName` | `CEO` | `Mandator` | Managing director name | | `ram:SellerTradeParty/ram:DefinedTradeContact/ram:DepartmentName` | `Department.Department` | `ContactPerson` via `Branch` or `Mandator` | Department name | | `ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber` | `PhoneNumber` or `Phone` | `Branch` or `Mandator` | Phone number | | `ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID` | `EMail` | `Branch` or `Mandator` | Email address | | `ram:SellerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode` | `ZipCode` or `PostCode` | `Branch` or `Mandator` | ZIP code | | `ram:SellerTradeParty/ram:PostalTradeAddress/ram:LineOne` | `Street` | `Branch` or `Mandator` | Street address | | `ram:SellerTradeParty/ram:PostalTradeAddress/ram:CityName` | `City` | `Branch` or `Mandator` | City | | `ram:SellerTradeParty/ram:PostalTradeAddress/ram:CountryID` | `CountryCode` | `Country` | Country code (ISO 2-letter) | | `ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID[@schemeID="EM"]` | `EMail` | `Branch` or `Mandator` | Email (duplicate for compatibility) | | `ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID="VA"]` | `TaxIDNumber` | `Mandator` | Tax identification number | **Internal Fields (not exported to XML):** - `OwnCountryCode`: Country code of seller (used for trade type determination: inland/EU/export) **Data Sources:** - If `BranchI3D` is set: Load from `Branch` table - Otherwise: Load from `Mandator` table (default mandator) - Country: From `Branch.CountryI3D` or `Mandator.Country` or default country (default: "DE") --- ## Buyer Trade Party (Customer) The buyer represents the customer/recipient. | XML Node | c-entron Field | Table/Entity | Path in Code | |----------|----------------|--------------|--------------| | `ram:BuyerTradeParty/ram:ID` | `AddressNumber` | `IBookKeepingReceipt` | Customer number | | `ram:BuyerTradeParty/ram:Name` | `CompanyName` or fallback to `AddressName` | `ReceiptReceiver` or `IBookKeepingReceipt` | Recipient name | | `ram:BuyerTradeParty/ram:DefinedTradeContact/ram:PersonName` | `ContactName` | `ReceiptReceiver` | Contact person name | | `ram:BuyerTradeParty/ram:DefinedTradeContact/ram:DepartmentName` | `ContactDepartment` | `ReceiptReceiver` | Contact department | | `ram:BuyerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber` | `ContactPhone` | `IBookKeepingReceipt` | Phone number | | `ram:BuyerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID` | `ContactEMail` | `IBookKeepingReceipt` | Email address | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:PostcodeCode` | `Zip` | `ReceiptReceiver` | ZIP code | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineOne` | Structured from `ReceiptReceiver` | `ReceiptReceiver` | First address line (see below) | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineTwo` | Structured from `ReceiptReceiver` | `ReceiptReceiver` | Second address line (see below) | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:LineThree` | Structured from `ReceiptReceiver` | `ReceiptReceiver` | Third address line (see below) | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CityName` | `City` | `ReceiptReceiver` | City | | `ram:BuyerTradeParty/ram:PostalTradeAddress/ram:CountryID` | `CountryCode` | `Country` via `ReceiptReceiver.CountryI3D` | Country code (ISO 2-letter) | | `ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID[@schemeID="EM"]` | `ContactEMail` | `IBookKeepingReceipt` | Email (duplicate for compatibility) | | `ram:BuyerTradeParty/ram:SpecifiedTaxRegistration/ram:ID[@schemeID="VA"]` | `SalesTaxIdentificationNumber` | `IBookKeepingReceipt` | VAT identification number | **Internal Fields (not exported to XML):** - `OwnCountryCode`: Country code of buyer (used for trade type determination: inland/EU/export) - `IsEUTrade`: Flag indicating if buyer country is EU member **Structured Address Line Building:** The system intelligently builds address lines from `ReceiptReceiver` with a maximum of 3 lines: 1. **CompanyName** - Company name (first priority if available) 2. **AdditionalAddressSupplement** - Additional address supplement 3. **Department/ContactDepartment** - Department information (order configurable via `ReceiverContactDepartmentFirst` setting) 4. **ContactName** - Contact person name 5. **Street/HouseNumber or PostOfficeBox** - Either street address or P.O. Box (formatted as shown in PostOfficeBox) The first item becomes the `Name`, subsequent items fill `AddressLine1`, `AddressLine2`, and `AddressLine3` (maximum 3 lines). **Special Handling:** - Post office box: If `HasPostOfficeBox` is true, uses `PostOfficeBox` instead of street address - Street formatting: Combines `Street` and `HouseNumber` with proper trimming - Department order: Configurable via `ReceiverContactDepartmentFirst` setting (ApplicationSettingID 10370) - Invoice address: If alternative invoice address is used (`UsedAlternativeInvoiceAddress`), name is loaded from `Kunden` table - Fallback: If `ReceiptReceiver` is null, falls back to legacy `IBookKeepingReceipt` fields --- ## Header Trade Agreement Purchase order and party references. | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ApplicableHeaderTradeAgreement/ram:BuyerReference` | `ExternalPurchaseOrderNumber` or `leitwegID` parameter | `IBookKeepingReceipt` | Leitweg-ID for XRechnung, otherwise purchase order number | | `ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID` | `ExternalPurchaseOrderNumber` | `IBookKeepingReceipt` | Purchase order number (only if not XInvoice) | --- ## Header Trade Delivery Delivery information. | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString` | `DeliveryDate` or `Date` | `IBookKeepingReceipt` | Delivery date (fallback to receipt date if not set) | --- ## Header Trade Settlement Payment, banking, and monetary information. ### Banking & SEPA | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID` | `SepaIdentificationNumber` | `Mandator` | SEPA creditor reference ID (only for direct debit) | | `ram:ApplicableHeaderTradeSettlement/ram:InvoiceCurrencyCode` | `CurrencyISOCode` | `IBookKeepingReceipt` | Currency code (e.g., "EUR") | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode` | `Untdid4461` or "ZZZ" | `IBookKeepingReceipt` | Payment means type code (UN/EDIFACT 4461) | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:Information` | `PaymentConditionsText` | `IBookKeepingReceipt` | Payment information text | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:PayerPartyDebtorFinancialAccount/ram:IBANID` | `Iban` | `BankAccount` via `BankAccountI3D` | Debtor IBAN (for direct debit) | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:IBANID` | Selected bank IBAN | `Mandator` bank info (Bank1-4) | Creditor IBAN (for bank transfer) | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount/ram:AccountName` | Selected bank holder or `Name` | `Mandator` bank info or `Mandator` | Account holder name | | `ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution/ram:BICID` | Selected bank BIC | `Mandator` bank info (Bank1-4) | Bank BIC code | **Bank Selection Logic:** 1. Check `ReceiptInvoiceSettings.UseMandatorBankForInvoice` (1-4) 2. For customer receipts, check `AccountCustomer.MandatorBank` override 3. Load bank details from `Mandator` (Bank1Iban/Bic, Bank2Iban/Bic, Bank3Iban/Bic, Bank4Iban/Bic) ### Tax Information | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ApplicableTradeTax/ram:CalculatedAmount` | Calculated from positions | `BookKeepingReceiptItem` | Tax amount per tax rate | | `ram:ApplicableTradeTax/ram:TypeCode` | Static "VAT" | - | Tax type | | `ram:ApplicableTradeTax/ram:ExemptionReason` | Derived from tax scenario | Logic | Tax exemption reason text | | `ram:ApplicableTradeTax/ram:BasisAmount` | Calculated from positions | `BookKeepingReceiptItem` | Net basis amount for tax | | `ram:ApplicableTradeTax/ram:CategoryCode` | Derived from tax scenario | Logic | Tax category (S, E, K, G, AE) | | `ram:ApplicableTradeTax/ram:RateApplicablePercent` | Grouped tax rates | `BookKeepingReceiptItem.TaxRate` | VAT percentage | **Tax Category Codes:** - `S` (Standard): Normal VAT rate - `E` (Exempt): 0% VAT for domestic tax-free transactions - `K` (Intra-community): 0% VAT for EU intra-community supply - `G` (Export): 0% VAT for export outside EU - `AE` (Reverse charge): Reverse charge scenario (`IsReverseCharge = true`) **Tax Exemption Reasons:** - Reverse charge: "Steuerschuldnerschaft des Leistungsempfängers gem. §13B Abs 2 Nr. 10 UStG." - Tax-free domestic: "Steuerfrei" - Intra-community: "Kein Ausweis der Umsatzsteuer bei innergemeinschaftlichen Lieferungen" - Export: "Steuer nicht erhoben aufgrund von Export außerhalb der EU" ### Billing Period | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString` | Min of position billing periods | `ContractBillingInfo` | Earliest billing start date | | `ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString` | Max of position billing periods | `ContractBillingInfo` | Latest billing end date | ### Payment Terms | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:SpecifiedTradePaymentTerms/ram:Description` | `PaymentConditionFull` + Skonto info | `IBookKeepingReceipt` + derived | Full payment condition text with line breaks | | `ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime/udt:DateTimeString` | `DueDate` or `Date` | `IBookKeepingReceipt` | Payment due date | | `ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID` | `AuthorizationNumber` | `BankAccount` via `BankAccountI3D` | SEPA mandate ID (only for direct debit) | **Skonto Information (BR-DE-18):** - Generated via `AssetConditionBL.GetPaymentConditionSkontoInBR_DE_18Format()` - Appended to description with proper XML line breaks (` `) ### Monetary Summation | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:LineTotalAmount` | `NetPriceFCComplete` | `IBookKeepingReceipt` | Total net amount | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:ChargeTotalAmount` | Static 0 | - | Total charges | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:AllowanceTotalAmount` | Static 0 | - | Total allowances | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxBasisTotalAmount` | `NetPriceFCComplete` | `IBookKeepingReceipt` | Tax basis total | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount[@currencyID]` | `TaxPriceFCComplete` | `IBookKeepingReceipt` | Total tax amount | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:GrandTotalAmount` | Net + Tax | Calculated | Gross total | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TotalPrepaidAmount` | Static 0 | - | Prepaid amount | | `ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount` | Net + Tax | Calculated | Due payable amount | **Validation:** - System validates that sum of position net prices equals header net price (tolerance: ±3.00) - System validates that sum of position gross prices equals header gross price (tolerance: ±3.00) - Warnings are logged if differences are within tolerance, errors if exceeding ### Invoice Referenced Document (Credit Vouchers Only) | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:InvoiceReferencedDocument/ram:IssuerAssignedID` | `Number` | `ReceiptInvoice` (origin) | Original invoice number | | `ram:InvoiceReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString` | `Date` | `ReceiptInvoice` (origin) | Original invoice date | **Logic:** - Only for credit vouchers (`Type = CreditVoucher`) - Only if exactly one origin invoice exists - Loaded via `ReceiptItem.OriginReceiptI3D` where `OriginKind = Invoice` --- ## Line Items (Positions) Each invoice/credit voucher position. ### Line Item Document | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:AssociatedDocumentLineDocument/ram:LineID` | Sequential counter | Generated | Position number (1, 2, 3, ...) | ### Trade Product | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:SpecifiedTradeProduct/ram:GlobalID[@schemeID="0160"]` | `EANCode` | `BookKeepingReceiptItem` | EAN/GTIN barcode (if not disabled in settings) | | `ram:SpecifiedTradeProduct/ram:SellerAssignedID` | `Articlecode` | `BookKeepingReceiptItem` | Article code (if not disabled in settings) | | `ram:SpecifiedTradeProduct/ram:Name` | `Text` | `BookKeepingReceiptItem` (via compact entity) | Position text/description | | `ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic/ram:Description` | Static "Seriennummer {index}" | Generated | Serial number label (1, 2, 3, ...) | | `ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic/ram:Value` | `Barcodes[i]` | `IReceiptItemWithBarcodes` | Barcode value (serial number) | **Barcode Handling:** - Barcodes are loaded from receipt items that implement `IReceiptItemWithBarcodes` - Multiple barcodes per position are supported (indexed sequentially) - For title positions, barcodes from child items are aggregated into the parent position - Each barcode is exported as a separate `ApplicableProductCharacteristic` node - Code reference: `InvoiceZugferdBL.cs:625-626` (loading), `InvoiceZugferdBL.cs:648-651` (title aggregation), `InvoiceZugferdBL.cs:881-898` (XML export) **Settings Flags:** - `ReceiptInvoiceSettings.ZugferdExportDontExportEanCode`: Suppresses EAN export - `ReceiptInvoiceSettings.ZugferdExportDontExportArticleCode`: Suppresses article code export ### Line Trade Agreement | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:NetPriceProductTradePrice/ram:ChargeAmount` | `NetPrice` | `InvoiceItemCompact` or `CreditVoucherItemCompact` | Unit net price (always positive) | **Note:** If `NetPrice` is negative, the price is made positive and quantity is negated. ### Line Trade Delivery | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:BilledQuantity[@unitCode]` | `QuantityComplete` | `InvoiceItemCompact` or `CreditVoucherItemCompact` | Quantity (negated if price was negative) | | `@unitCode` | `UNECECode` | `Article.ArticleUnit` | UN/ECE unit code (default: "C62" = piece) | **UN/ECE Code Logic:** - Only for article items (`Kind = Article` and `ArticleI3D` is set) - Loaded from `Article.ArticleUnit.UNECECode` - Fallback: "C62" (one/piece) ### Line Trade Settlement | XML Node | c-entron Field | Table/Entity | Description | |----------|----------------|--------------|-------------| | `ram:ApplicableTradeTax/ram:TypeCode` | Static "VAT" | - | Tax type | | `ram:ApplicableTradeTax/ram:CategoryCode` | Derived from tax scenario | Logic | Tax category code (see header tax) | | `ram:ApplicableTradeTax/ram:RateApplicablePercent` | `TaxRate` or 0 | `InvoiceItemCompact`/`CreditVoucherItemCompact` | VAT percentage (0 if `ExclusiveOfVAT`) | | `ram:SpecifiedTradeSettlementLineMonetarySummation/ram:LineTotalAmount` | `NetPriceTotalFCComplete` | `BookKeepingReceiptItem` | Line net total amount | **Title Position Handling:** - Title positions (`Kind = TitlePosition`, `Expanded = false`) are exported as collapsed items - Child items (`Visible != Visible` or `Indent > 0`) are aggregated into parent title position - Title position quantity is always 1 - Title position net price equals net total - Mixed tax rates in title positions cause error **Item Filtering:** - Only exports: `Article`, `CustomerDiscount`, or collapsed `TitlePosition` items - Must be `Visible = Visible` or `Indent = 0` - Ordered by `InternalPosition` --- ## Data Sources Summary ### Primary Tables | Table/Entity | Purpose | Key Fields | |--------------|---------|------------| | `IBookKeepingReceipt` | Receipt header | Number, Date, AddressNumber, DueDate, CurrencyISOCode, NetPriceFCComplete, TaxPriceFCComplete | | `ReceiptReceiver` | Structured receiver address | CompanyName, AdditionalAddressSupplement, Department, ContactDepartment, ContactName, Street, HouseNumber, PostOfficeBox, Zip, City, CountryI3D | | `BookKeepingReceiptItem` | Receipt line items | Position, Text, Articlecode, EANCode, NetPrice, QuantityComplete, TaxRate | | `InvoiceItemCompact` | Invoice item details | NetPrice, NetPriceTotalFCComplete, TaxPriceTotalFCComplete, VATRate, QuantityComplete | | `CreditVoucherItemCompact` | Credit voucher item details | NetPrice, NetPriceTotalFC, TaxPriceTotalFC, VATRate, QuantityComplete | | `Mandator` | Own company | Name, CEO, TaxIDNumber, HRB, Street, City, PostCode, Phone, EMail, SepaIdentificationNumber | | `Branch` | Own branch | Name, Street, City, ZipCode, PhoneNumber, EMail, CountryI3D | | `Country` | Country data | CountryCode, EUMember | | `BankAccount` | Bank account | Iban, AuthorizationNumber | | `Article` | Article master data | ArticleUnit (for UN/ECE code) | | `ReceiptInvoice` | Invoice entity | For credit voucher references | | `ReceiptCreditVoucher` | Credit voucher entity | For origin tracking | ### Derived/Calculated Fields | Concept | Calculation | Source | |---------|-------------|--------| | Tax category codes | Based on tax rate, reverse charge, country flags | Logic in `GetTaxCategoryCode()` | | Tax exemption reasons | Based on tax scenario | Logic in `GetTaxExemptionReason()` | | Structured address lines | Intelligent building from ReceiptReceiver | Logic in receiver address building (max 3 lines) | | OwnCountryCode | Country code for trade type | Loaded from `Country` via `CountryI3D` (default: "DE") | | Billing period | Min/Max from contract billing info | `ContractBL.GetContractBillingPeriodForInvoiceItem()` | | Bank selection | Settings + customer override | `ReceiptInvoiceSettings.UseMandatorBankForInvoice` + `AccountCustomer.MandatorBank` | | Skonto text | Payment condition formatting | `AssetConditionBL.GetPaymentConditionSkontoInBR_DE_18Format()` | | UN/ECE code | Article unit lookup | `Article.ArticleUnit.UNECECode` | --- ## Special Cases & Business Logic ### Structured Receiver Address The system uses the structured `ReceiptReceiver` entity to build multi-line addresses: - **Maximum 3 lines** for Name and AddressLine1-3 - **Intelligent building** based on available fields (CompanyName, AdditionalAddressSupplement, Department, ContactDepartment, ContactName, Street) - **Configurable department order** via `ReceiverContactDepartmentFirst` setting - **Post office box handling** with `HasPostOfficeBox` flag - **Fallback support** to legacy `IBookKeepingReceipt` fields if `ReceiptReceiver` is null ### Negative Prices ZUGFeRD does not support negative prices. The system: 1. Makes `NetPrice` positive 2. Negates `Quantity` instead 3. Maintains correct calculation ### Title Positions - Collapsed title positions are exported with aggregated child item values - Expanded title positions are not supported (error) - Mixed tax rates in title positions are not supported (error) - Default tax rate for title positions without items: 19% - Barcodes from child items are aggregated into the parent title position ### Payment Condition Determined by SEPA active status: - `IsSepaActive = true` → `DirectDebit` (BG-19) - `IsSepaActive = false` → `BankTransfer` (BG-17) ### Country Trade Flags Used for tax category determination: - `IsInlandTrade`: Buyer country = Seller country - `IsEUTrade`: Buyer country is EU member ### Validation Tolerances - Net price difference tolerance: ±3.00 (between header and sum of positions) - Gross price difference tolerance: ±3.00 - Within tolerance: Warning logged, value corrected - Exceeding tolerance: Error, export fails --- ## Implementation Notes ### File Encoding - XML files are generated with UTF-8 encoding - BOM (Byte Order Mark) is removed from export (first 3 bytes stripped) ### Date Formats - Standard date: `yyyyMMdd` (format code "102") - Long date: `yyyy-MM-ddThh:mm:ss` ### Amount Formatting - All amounts use "F2" format (2 decimal places) - Culture: en-US (decimal separator: dot) ### Namespace Prefixes - `rsm`: CrossIndustryInvoice - `ram`: ReusableAggregateBusinessInformationEntity - `udt`: UnqualifiedDataType - `qdt`: QualifiedDataType ### Code References - Main generator: `InvoiceZugferdBL.cs:117-158` (GenerateZugferdFile) - Export item builder: `InvoiceZugferdBL.cs:237-434` (GetZugferdExportItem) - XML document generator: `InvoiceZugferdBL.cs:727-750` (DoGenerateZugferdXRechnungXmlDocument) - Tax logic: `InvoiceZugferdBL.cs:1369-1400` (GetTaxCategoryCode, GetTaxExemptionReason) --- ## Version History | Version | Notes | |---------|-------| | 1.2 | Added: Structured `ReceiptReceiver` support for buyer address, `OwnCountryCode` for trade type determination | | 1.1 | Added: Barcode/serial number export in line items via `ApplicableProductCharacteristic` | | 1.0 | Initial documentation covering XRechnung 3.0.1 implementation |