# Prüfregeln von `erechnung-core.js`

Diese Datei listet genau die Regeln auf, die `check(xml)` auswertet und melden kann.

**Wichtig:** Das ist eine dokumentierte **Teilmenge** der Geschäftsregeln aus EN 16931 und XRechnung 3.0. Es ist **nicht** der KoSIT-Validator und ersetzt ihn nicht. Es findet keine XSD-Schemaprüfung und keine vollständige Schematron-Prüfung statt. Eine Datei ohne Meldungen hier kann im KoSIT-Validator oder beim Empfänger trotzdem abgelehnt werden.

Werkzeug, keine Steuer- oder Rechtsberatung; keine Garantie für Konformität; Prüfung durch Steuerberater/Empfänger empfohlen.

Den Validator und seine Konfiguration veröffentlicht die KoSIT: [KoSIT-Validator](https://github.com/itplr-kosit/validator) und [Validator-Konfiguration XRechnung](https://github.com/itplr-kosit/validator-configuration-xrechnung).

## Unterstützte Syntaxen

- UBL 2.1 `Invoice` und `CreditNote`
- UN/CEFACT CII `CrossIndustryInvoice`

`detectSyntax(xml)` liefert `UBL`, `CII` oder `unknown`.

## Technische Meldungen (eigene IDs, nicht aus EN 16931 oder XRechnung)

| ID | Stufe | Bedeutung |
|---|---|---|
| `XML-WELLFORMED` | Fehler | Die Datei ist kein wohlgeformtes XML (eigener kleiner Parser; DOCTYPE wird abgelehnt). |
| `SYNTAX-UNKNOWN` | Fehler | Wurzelelement ist weder UBL Invoice/CreditNote noch CII CrossIndustryInvoice. |

## Pflichtangaben (EN 16931)

| ID | Geprüft wird |
|---|---|
| `BR-01` | Spezifikationskennung (BT-24) vorhanden |
| `BR-02` | Rechnungsnummer (BT-1) vorhanden |
| `BR-03` | Rechnungsdatum (BT-2) vorhanden |
| `BR-04` | Rechnungsart-Code (BT-3) vorhanden |
| `BR-05` | Währungscode (BT-5) vorhanden |
| `BR-06` | Name des Verkäufers (BT-27) vorhanden |
| `BR-07` | Name des Käufers (BT-44) vorhanden |
| `BR-08` | Postanschrift des Verkäufers (BG-5) vorhanden |
| `BR-09` | Ländercode des Verkäufers (BT-40) vorhanden |
| `BR-10` | Postanschrift des Käufers (BG-8) vorhanden |
| `BR-11` | Ländercode des Käufers (BT-55) vorhanden |
| `BR-12` | Summe der Positionsnettobeträge (BT-106) vorhanden |
| `BR-13` | Gesamtbetrag ohne Umsatzsteuer (BT-109) vorhanden |
| `BR-14` | Gesamtbetrag mit Umsatzsteuer (BT-112) vorhanden |
| `BR-15` | Zahlbetrag (BT-115) vorhanden |
| `BR-16` | Mindestens eine Rechnungsposition (BG-25) |
| `BR-21` | Positionsnummer (BT-126) vorhanden |
| `BR-22` | Menge (BT-129) vorhanden |
| `BR-23` | Mengeneinheit (BT-130) vorhanden |
| `BR-24` | Nettobetrag der Position (BT-131) vorhanden |
| `BR-25` | Artikelname (BT-153) vorhanden |
| `BR-26` | Nettopreis des Artikels (BT-146) vorhanden |
| `BR-27` | Nettopreis des Artikels (BT-146) nicht negativ |

Geprüft wird nur das Vorhandensein eines nicht leeren Wertes, nicht das Format (Datumsformat, Codelisten, Währungscodes werden nicht geprüft).

## Rechenregeln (EN 16931)

Beträge werden auf Cent genau verglichen.

| ID | Geprüft wird |
|---|---|
| `BR-CO-10` | BT-106 = Summe aller Positionsnettobeträge (BT-131) |
| `BR-CO-13` | BT-109 = BT-106 − BT-107 + BT-108 |
| `BR-CO-14` | BT-110 = Summe der Steuerbeträge je Kategorie (BT-117) |
| `BR-CO-15` | BT-112 = BT-109 + BT-110 |
| `BR-CO-16` | BT-115 = BT-112 − BT-113 + BT-114 |
| `BR-CO-17` | BT-117 = BT-116 × BT-119 / 100. Als Fehler gilt erst eine Abweichung ab 1,00 (wie die Toleranz der Regel in EN 16931); kleinere Abweichungen über 0,01 erzeugen die Warnung `AUGEO-W-VAT-CALC`. |
| `BR-CO-18` | Mindestens eine Umsatzsteueraufschlüsselung (BG-23) |

## Umsatzsteuerkategorien (EN 16931)

| ID | Geprüft wird |
|---|---|
| `BR-S-05` | Position mit Kategorie S: Steuersatz (BT-152) größer als 0 |
| `BR-E-01` | Position mit Kategorie E: genau eine Aufschlüsselung (BG-23) mit Kategorie E |
| `BR-E-05` | Position mit Kategorie E: Steuersatz (BT-152) ist 0 |
| `BR-E-09` | Aufschlüsselung mit Kategorie E: Steuerbetrag (BT-117) ist 0 |
| `BR-E-10` | Aufschlüsselung mit Kategorie E: Befreiungsgrund als Text (BT-120) oder Code (BT-121) vorhanden |

Nur Positionen und Aufschlüsselungen werden betrachtet; Zu- und Abschläge auf Dokumentenebene (BG-20, BG-21) werden bei den Kategorieregeln nicht ausgewertet. Andere Kategorien (Z, AE, K, G, O, L, M) haben keine eigenen Regeln in dieser Teilmenge.

## Deutsche Regeln (XRechnung 3.0)

| ID | Geprüft wird |
|---|---|
| `BR-DE-1` | Datengruppe BG-16 mit Zahlungsart-Code vorhanden |
| `BR-DE-2` | Kontaktangaben des Verkäufers (BG-6) vorhanden |
| `BR-DE-3` | Ort des Verkäufers (BT-37) vorhanden |
| `BR-DE-4` | Postleitzahl des Verkäufers (BT-38) vorhanden |
| `BR-DE-5` | Ansprechpartner des Verkäufers (BT-41) vorhanden |
| `BR-DE-6` | Telefonnummer des Verkäufers (BT-42) vorhanden |
| `BR-DE-7` | E-Mail-Adresse des Verkäufers (BT-43) vorhanden |
| `BR-DE-8` | Ort des Käufers (BT-52) vorhanden |
| `BR-DE-9` | Postleitzahl des Käufers (BT-53) vorhanden |
| `BR-DE-15` | Käuferreferenz / Leitweg-ID (BT-10) vorhanden |
| `BR-DE-16` | Bei den Kategorien S, Z, E, AE, K, G, L, M: Umsatzsteuer-ID (BT-31), Steuernummer (BT-32) oder Steuervertreter (BG-11) des Verkäufers vorhanden |

## Eigene Warnungen (eigene IDs, nicht aus EN 16931 oder XRechnung)

| ID | Bedeutung |
|---|---|
| `AUGEO-W-SPEC` | BT-24 beginnt nicht mit der Kennung von XRechnung 3.0 (`urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0`). |
| `AUGEO-W-LINE-CALC` | Menge × Nettopreis weicht um mehr als 0,01 vom Nettobetrag der Position ab. Wird nur bewertet, wenn die Position keine Zu-/Abschläge und keine Preisbasismenge hat. |
| `AUGEO-W-VAT-CALC` | Steuerbetrag weicht um mehr als 0,01, aber weniger als 1,00 vom rechnerischen Wert ab. |

## Nicht geprüft (Auswahl)

XSD-Schema, Codelisten (Länder, Währungen, Einheiten, Rechnungsarten, VATEX), Datumsformate, IBAN- und Leitweg-ID-Format, elektronische Adressen (BT-34, BT-49), Lieferangaben (BR-DE-10, BR-DE-11), Skonto-Syntax, Zahlungsarten-Regeln (BR-DE-19 bis BR-DE-25 und folgende), Zu- und Abschläge, Anhänge, Extension-Profil, Regeln der Kategorien außer S und E, alle übrigen BR-, BR-CO- und BR-DE-Regeln.

## Erzeugung (`buildUBL`, `buildCII`)

- Spezifikationskennung: `urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0`
- Kleinunternehmer-Modus (`kleinunternehmer: true`): Kategorie `E`, Steuersatz 0, Befreiungsgrund „Kein Ausweis von Umsatzsteuer, da Kleinunternehmer gemäß § 19 UStG“.
- Standard-Modus: Kategorie `S` mit dem Steuersatz je Position (z. B. 19 oder 7); Steuer je Satz = Summe der Nettobeträge × Satz, kaufmännisch auf Cent gerundet.
- Positionsnetto = Menge × Einzelpreis, auf Cent gerundet. Keine Zu-/Abschläge, kein Skonto, keine Anzahlungen.
- BT-81 Zahlungsart-Code (BG-16): 58, wenn das freiwillige Feld BT-84 der eigenen Rechnung ausgefüllt ist, sonst 1. Sind BT-9 (Fälligkeitsdatum) und BT-20 (Zahlungsbedingungen, Freitext der Rechnung) beide leer, steht in BT-20 der Text „Ohne gesonderte Angabe.“.
- XML-Leser: Numerische Zeichenreferenzen (`&#252;`, `&#xFC;`) werden für U+0020 bis U+007E, U+00A0 bis U+00FF und einige weitere Zeichen (unter anderem €, „ “, –) aufgelöst; Referenzen auf andere Zeichen bleiben im Text so stehen, wie sie geschrieben sind.
- Elektronische Adressen (BT-34, BT-49) werden aus den E-Mail-Adressen mit Schema `EM` gebildet.
- `validateInvoice(invoice)` liefert die Liste fehlender Pflichtangaben; die Erzeugung bricht mit einer Fehlermeldung ab, wenn sie nicht leer ist.

## CSV-Stapel (`parseCsvBatch(text, defaults)`)

Eine CSV-Zeile ist eine Rechnungsposition. Zeilen mit derselben Rechnungsnummer bilden eine Rechnung. Trennzeichen `;` oder `,` (aus der Kopfzeile erkannt), Felder optional in `"…"`. Zahlen mit deutschem Dezimalkomma (`1.250,50`) oder Punkt (`1250.50`). Datum als `TT.MM.JJJJ` oder `JJJJ-MM-TT`. Verkäuferdaten, Kleinunternehmer-Modus, Währung und der Standardwert für BT-20 kommen aus `defaults` (`seller`, `kleinunternehmer`, `currency`, `payment_terms`).

| Spalte | Alternative Kopfzeile | Pflicht | Inhalt |
|---|---|---|---|
| `invoice_number` | Rechnungsnummer | ja | Rechnungsnummer (BT-1) |
| `issue_date` | Rechnungsdatum | ja | Rechnungsdatum (BT-2) |
| `due_date` | Fälligkeitsdatum | nein | Fälligkeitsdatum (BT-9) |
| `delivery_date` | Leistungsdatum, Lieferdatum | nein | Liefer-/Leistungsdatum (BT-72) |
| `buyer_reference` | Leitweg-ID, Käuferreferenz | ja | Käuferreferenz (BT-10) |
| `buyer_name` | Kunde, Kunde_Name | ja | Name des Käufers (BT-44) |
| `buyer_street` | Kunde_Strasse | nein | Straße und Hausnummer (BT-50) |
| `buyer_postcode` | Kunde_PLZ | ja | Postleitzahl (BT-53) |
| `buyer_city` | Kunde_Ort | ja | Ort (BT-52) |
| `buyer_country` | Kunde_Land | nein | Ländercode, Standard `DE` (BT-55) |
| `buyer_email` | Kunde_Email | ja | Elektronische Adresse des Käufers (BT-49) |
| `buyer_vat_id` | Kunde_UStID | nein | Umsatzsteuer-ID des Käufers (BT-48) |
| `item_name` | Bezeichnung, Artikel | ja | Artikelname (BT-153) |
| `item_description` | Beschreibung | nein | Artikelbeschreibung (BT-154) |
| `quantity` | Menge | ja | Menge (BT-129) |
| `unit` | Einheit | nein | Einheitencode nach UN/ECE Rec 20, Standard `C62` (Stück); `HUR` = Stunde |
| `unit_price` | Einzelpreis, Preis | ja | Nettopreis je Einheit (BT-146) |
| `vat_rate` | Steuersatz, USt | im Standard-Modus | Steuersatz in Prozent; im Kleinunternehmer-Modus immer 0 |
| `note` | Hinweis, Bemerkung | nein | Freitext zur Rechnung (BT-22) |
| `payment_terms` | Zahlungsbedingungen | nein | BT-20 Zahlungsbedingungen (Freitext der Rechnung) |

Kopfzeilen werden ohne Beachtung der Groß-/Kleinschreibung gelesen. Kopfdaten einer Rechnung (Datum, Käufer) werden aus ihrer ersten Zeile genommen.

## Tests

`tests/run_fixtures.js` (nicht Teil der veröffentlichten Seite) prüft Parser, Erzeugung, sechs absichtlich fehlerhafte Varianten je Syntax und den CSV-Stapel. Der Lauf gegen die Beispieldateien der KoSIT-Testsuite ist Pflichtteil dieses Skripts: Es schlägt fehl, solange die Dateien nicht bytegleich unter `tests/fixtures/kosit/` liegen oder eine davon eine Fehlermeldung auslöst. Den Stand dazu nennt `tests/fixtures/SOURCE.md`; bis dort ein bestandener Lauf vermerkt ist, gilt die Prüfung gegen die KoSIT-Dateien als nicht erbracht.
