Files
Christoph Schwörer f045b99a25 Codebasis als Dateien ins Arbeitsrepo statt als Gitlink
QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142)
getrackt, ohne .gitmodules und ohne erreichbares Remote. Der
Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar
gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege
der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen.

Umstellung:
- Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert
  (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6)
- Gitlink aus dem Index entfernt
- Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB

Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte
bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
2026-08-26 07:43:51 +02:00

422 lines
24 KiB
Markdown

# 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 |