markAsDuplicate function
Kennzeichnet einen Nachdruck als Belegduplikat (Zwilling von
markAsDuplicate in @kreiseck/kasseneck-api/receipt).
Registrierkassen-Erlass BMF-AV Nr. 2/2026, Abschnitt 4.5.6: „Ein
Belegduplikat ist als solches zu bezeichnen, nicht nochmals zu signieren,
nicht neuerlich im Datenerfassungsprotokoll aufzunehmen und darf zu keiner
Veränderung des Umsatzzählers führen.“ Signatur, DEP und Zähler bleiben
ohnehin unberührt, weil ein Nachdruck den gespeicherten Beleg druckt; diese
Funktion liefert die Bezeichnung.
Die Kasse ruft sie bei jedem Nachdruck und bei „Kopie drucken“ mit dem
Zeitpunkt des Drucks auf, nie beim Erstdruck und nie für Mail, Link oder
PDF, und gibt das Ergebnis an denselben Druckweg
(PrintPaper.setReceiptSheet, receiptSheet, KeckReceiptSheetWidget).
Neu ist genau eine Zeile im Kennungsblock, direkt unter Beleg-ID:, in
der Spaltenform von Datum: (nicht fett, Wert rechtsbündig):
Beleg-ID: AT0-KASSE1-42
Duplikat am: 24.10.2026 14:10:05
printedAt ist ein Zeitpunkt (UTC oder lokal, gleich); gedruckt wird er
in Wiener Zeit (Sommerzeit nach EU-Regel), nie in der Zeitzone des Geräts.
Ohne Spaltenzeile Beleg-ID: (Schicht-Bons) steht die Zeile ganz oben.
Alles andere bleibt Zeile für Zeile wie beim Erstdruck.
Reine Funktion: die Eingabe bleibt unangetastet, das Ergebnis trägt eine
eigene Zeilenliste und je Spaltenzeile eine eigene Spaltenliste (wie im
npm-Paket); wer am Duplikat dreht, dreht nie am Erstdruck. Trägt das
Layout schon eine Zeile Duplikat am:, bekommt nur sie die neue Zeit (der
letzte Nachdruck gilt); es bleibt bei einer Zeile.
Implementation
ReceiptLayout markAsDuplicate(ReceiptLayout layout, {required DateTime printedAt}) {
final neu = LayoutColumnsLine([
const LayoutColumn(text: _duplikatAm, width: _duplikatLinks),
LayoutColumn(text: _wienerZeit(printedAt), width: _duplikatRechts, align: LayoutAlign.right),
]);
final vorhanden = layout.lines.indexWhere((z) => _istZeile(z, _duplikatAm));
final lines = [
for (final z in layout.lines)
if (!_istZeile(z, _duplikatAm)) z is LayoutColumnsLine ? LayoutColumnsLine([...z.columns], bold: z.bold) : z,
];
final stelle = vorhanden >= 0 ? vorhanden : lines.indexWhere((z) => _istZeile(z, 'Beleg-ID:')) + 1;
lines.insert(stelle, neu);
return ReceiptLayout(lines: lines, paperSize: layout.paperSize, ruleset: layout.ruleset);
}