markAsDuplicate function

ReceiptLayout markAsDuplicate(
  1. ReceiptLayout layout, {
  2. required DateTime printedAt,
})

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);
}