feat: E-Rechnungs-Backend, Pflichtangaben-Validator, Nummern-Audit und DATEV-Export
Größerer Wurf rund um Rechnungen: das vollständige E-Rechnungs- und Lifecycle-Backend wird eingecheckt, die UI-seitige Rechnungserstellung wird zugunsten eines DATEV-Exports zurückgebaut, und die Test-Infrastruktur wird auf JDK 25 angehoben. E-Rechnung & Signatur - ZUGFeRD/Factur-X/XRechnung-Anreicherung via Mustang (EInvoiceService). - PAdES-Detached-Signatur via PDFBox + BouncyCastle, System- und Nutzer- Keystore-Pfad, Nutzer-Keystores AES-GCM-verschlüsselt (AesGcmCipher, SigningCredentialsService, UserSigningCredentials). - Konfiguration via EInvoiceProperties + EInvoiceSecurityInitializer. - Approval-Workflow für kritische Rechnungsvorgänge (Storno, Berichtigung): InvoiceApprovalService, InvoiceApprovalRequest, ApprovalsView, InvoicePermissionService, InvoiceRoles. Lifecycle & Audit - InvoiceStatus DRAFT/ISSUED/SENT/CANCELLED/CORRECTED, InvoiceType INVOICE/CORRECTION/CANCELLATION, PaymentStatus, lückenloser Audit-Trail via InvoiceAuditEntry/Action. - InvoiceLifecycleService verwaltet alle Übergänge inklusive Storno- und Berichtigungsbelegen mit Querverweis zur Originalrechnung. - InvoiceLifecycleMigration zieht Bestandsdaten in das neue Lifecycle-Modell. - InvoiceExportService bündelt Original + Folgebelege als ZIP für die Auslieferung an den Steuerberater. Pflichtangaben-Validator (§ 14 UStG) - InvoiceComplianceValidator + Exception sammeln alle Verstöße in einem Lauf (Pflichtfelder, Adressen, Steuernummer/USt-IdNr, Items, Betrags- konsistenz, Hinweispflicht bei 0 % USt). - Wird vor jedem DRAFT-→-ISSUED-Übergang im Lifecycle aufgerufen, sodass festgeschriebene Rechnungen keine Pflichtfeld-Lücken mehr haben können. Rechnungsnummer-Audit (§ 14 Abs. 4 Nr. 4 UStG / GoBD) - InvoiceNumberReservation + Status RESERVED/USED/VOIDED protokollieren jede aus dem Counter gezogene Nummer. - UserInvoiceDataService schreibt bei Vergabe ein RESERVED-Audit, der Lifecycle setzt nach Festschreiben USED bzw. nach Löschen eines Entwurfs VOIDED — Lücken im Nummernkreis sind dadurch erklärbar. - InvoiceNumberAuditService liefert markUsed/markVoided/findUnused für Folge-UI und Betriebsprüfungs-Reports. UI-Rückbau und DATEV-Export - Routen für CreateInvoiceView, InvoicesView, MyInvoicesView auskommentiert (Code bleibt erhalten, Reaktivierung dokumentiert). - Rechnungs-Buttons aus ShowJobsView entfernt, Nav-Eintrag „Rechnungen" durch „DATEV-Export" ersetzt. - DatevExportService erzeugt einen DATEV-EXTF-Buchungsstapel (Version 7, Windows-1252, CRLF) mit SKR03-Erlöskonten (8400/8300/8125), Sammel- debitor 10000 und korrektem S/H-Verhalten für Stornorechnungen. - DatevExportView mit Zeitraum-Picker und Auto-Download. - i18n-Keys (de/en) für nav.datev.export und datev.export.*. Tests & Build - EInvoiceServiceTest (Signatur-Pfade), EInvoiceServiceDssValidationTest (PAdES-Profil via EU DSS 6.2 — dokumentiert PKCS7-B als Ist-Stand), InvoiceComplianceValidatorTest (26 Cases als Spezifikation der Pflichtangaben), InvoiceNumberAuditServiceTest, DatevExportServiceTest. - Mockito 5.18 + ByteBuddy 1.17.5 in <dependencyManagement> gepinnt; die Spring-Boot-3.4.3-Defaults (Mockito 5.14.2 / ByteBuddy 1.15.11) konnten den Inline-Mock-Maker auf JDK 25 nicht laden, weshalb die beiden DemoModeServiceTests vorher rot waren. - DSS-Test-Dependencies (dss-pades-pdfbox, dss-validation, dss-utils-apache-commons, dss-crl-parser-x509crl 6.2) im Test-Scope. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,17 @@ nav.customers=Adressbuch
|
||||
nav.appusers=App-Nutzer
|
||||
nav.statistics=Statistiken
|
||||
nav.invoices=Rechnungen
|
||||
nav.datev.export=DATEV-Export
|
||||
nav.approvals=Freigaben
|
||||
datev.export.title=DATEV-Export
|
||||
datev.export.description=Lädt einen DATEV-kompatiblen Buchungsstapel mit allen festgeschriebenen Rechnungen des gewählten Zeitraums herunter. Die Datei kann in DATEV Unternehmen Online sowie in DATEV-importfähigen Drittprogrammen eingelesen werden.
|
||||
datev.export.from=Von
|
||||
datev.export.to=Bis
|
||||
datev.export.button=Rechnungen exportieren
|
||||
datev.export.success=Export erstellt: {0}
|
||||
datev.export.error.dates=Bitte Von- und Bis-Datum auswählen.
|
||||
datev.export.error.range=Das Bis-Datum darf nicht vor dem Von-Datum liegen.
|
||||
datev.export.error.user=Aktueller Nutzer konnte nicht ermittelt werden.
|
||||
nav.messages=Nachrichten
|
||||
nav.profile=Mein Profil
|
||||
nav.myinvoices=Rechnungen
|
||||
@@ -47,6 +58,36 @@ profile.settings.digitalprocess.info=Aufträge werden digital über die App abge
|
||||
profile.settings.locateappuser=App-Nutzer orten
|
||||
profile.settings.locateappuser.info=Standort der App-Nutzer wird regelmäßig übertragen
|
||||
profile.settings.vatrate=Umsatzsteuer
|
||||
profile.settings.einvoice=ZUGFeRD-E-Rechnung erstellen
|
||||
profile.settings.einvoice.helper=Erzeugt PDF/A-3 mit eingebettetem XRechnung/ZUGFeRD-XML (sofern systemweit aktiviert).
|
||||
profile.settings.signinvoices=Rechnungen digital signieren
|
||||
profile.settings.signinvoices.helper=Erzeugt eine PAdES-Signatur mit dem hinterlegten Zertifikat. Ohne aktives Zertifikat schlägt das Speichern fehl.
|
||||
profile.signing.title=Signatur-Zertifikat
|
||||
profile.signing.hint=Hinterlegen Sie Ihr eigenes PKCS#12-Zertifikat (.p12/.pfx), damit Ihre Rechnungen mit Ihrer Signatur erstellt werden. Der private Schlüssel wird verschlüsselt in der Datenbank gespeichert.
|
||||
profile.signing.masterkey.missing=Hinweis: Der Server-Master-Key ist nicht gesetzt. Bitten Sie Ihren Administrator, votianlt.einvoice.signing.master-key zu konfigurieren, bevor Sie ein Zertifikat hinterlegen.
|
||||
profile.signing.none=Es ist noch kein eigenes Signatur-Zertifikat hinterlegt. Beim Signieren wird der systemweit konfigurierte Schlüssel verwendet.
|
||||
profile.signing.metadata.alias=Alias
|
||||
profile.signing.metadata.subject=Inhaber
|
||||
profile.signing.metadata.issuer=Aussteller
|
||||
profile.signing.metadata.serial=Seriennummer
|
||||
profile.signing.metadata.validity=Gültig
|
||||
profile.signing.expired=Zertifikat abgelaufen
|
||||
profile.signing.expiring=Läuft in den nächsten 30 Tagen ab
|
||||
profile.signing.enabled=Eigenes Zertifikat zum Signieren verwenden
|
||||
profile.signing.toggle.saved=Einstellung gespeichert.
|
||||
profile.signing.delete=Zertifikat entfernen
|
||||
profile.signing.deleted=Signatur-Zertifikat entfernt.
|
||||
profile.signing.upload.title=Zertifikat hochladen
|
||||
profile.signing.upload.drop=PKCS#12-Datei hier ablegen oder klicken
|
||||
profile.signing.upload.received=Datei empfangen — bitte Alias und Passwort angeben.
|
||||
profile.signing.upload.required=Bitte zuerst eine Zertifikatsdatei hochladen.
|
||||
profile.signing.upload.save=Speichern
|
||||
profile.signing.alias=Schlüssel-Alias
|
||||
profile.signing.alias.required=Bitte den Alias des Schlüssels angeben.
|
||||
profile.signing.password=Keystore-Passwort
|
||||
profile.signing.password.required=Bitte das Keystore-Passwort angeben.
|
||||
profile.signing.saved=Signatur-Zertifikat gespeichert.
|
||||
profile.signing.error=Speichern fehlgeschlagen
|
||||
profile.account=Konto
|
||||
profile.security=Sicherheit
|
||||
profile.security.twofactor=Zwei-Faktor-Authentifizierung
|
||||
@@ -706,6 +747,96 @@ invoices.column.amount=Betrag
|
||||
invoices.column.description=Beschreibung
|
||||
invoices.empty=Es wurden noch keine Rechnungen erstellt.
|
||||
invoices.notification.pdf.missing=Für diese Rechnung ist kein PDF gespeichert.
|
||||
invoices.notification.pdf.error=Die PDF-Anzeige ist fehlgeschlagen: {0}
|
||||
invoices.column.status=Status
|
||||
invoices.column.type=Typ
|
||||
invoices.column.actions=Aktionen
|
||||
invoices.disclaimer=Hinweis: Die rechtliche Aufbewahrungspflicht liegt beim Aussteller. Eine bereits ausgestellte Rechnung wird nicht überschrieben — Korrekturen erfolgen über Berichtigung oder Stornorechnung mit eindeutigem Bezug.
|
||||
invoices.status.draft=Entwurf
|
||||
invoices.status.issued=Ausgestellt
|
||||
invoices.status.sent=Versendet
|
||||
invoices.status.cancelled=Storniert
|
||||
invoices.status.corrected=Berichtigt
|
||||
invoices.type.invoice=Rechnung
|
||||
invoices.type.cancellation=Stornorechnung
|
||||
invoices.type.correction=Berichtigung
|
||||
invoices.action.view=PDF anzeigen
|
||||
invoices.action.history=Historie
|
||||
invoices.action.marksent=Versendet markieren
|
||||
invoices.action.correct=Berichtigen
|
||||
invoices.action.cancel=Stornieren
|
||||
invoices.notification.sent=Rechnung als versendet markiert.
|
||||
invoices.notification.cancelled=Stornobeleg {0} erstellt.
|
||||
invoices.notification.corrected=Berichtigungsbeleg {0} erstellt.
|
||||
invoices.notification.error=Aktion fehlgeschlagen: {0}
|
||||
invoices.cancel.title=Rechnung {0} stornieren
|
||||
invoices.cancel.hint=Die Originalrechnung bleibt unverändert sichtbar. Es wird ein eigenständiger Stornobeleg mit eigener Belegnummer erstellt, der die Originalrechnung eindeutig referenziert.
|
||||
invoices.cancel.reason=Grund der Stornierung
|
||||
invoices.cancel.reason.required=Bitte einen Grund angeben.
|
||||
invoices.cancel.confirm=Stornobeleg erstellen
|
||||
invoices.correct.title=Rechnung {0} berichtigen
|
||||
invoices.correct.hint=Eine Berichtigung dient ausschließlich der Korrektur formaler Fehler (z.B. Adresse, Leistungsdatum). Die Originalrechnung bleibt sichtbar; der Berichtigungsbeleg verweist eindeutig auf sie.
|
||||
invoices.correct.fields=Berichtigte Angaben
|
||||
invoices.correct.fields.helper=Beschreiben Sie, welche Angaben ergänzt oder ersetzt werden.
|
||||
invoices.correct.fields.required=Bitte die berichtigten Angaben beschreiben.
|
||||
invoices.correct.reason=Grund der Berichtigung
|
||||
invoices.correct.confirm=Berichtigung erstellen
|
||||
invoices.history.title=Historie zu Rechnung {0}
|
||||
invoices.history.log=Änderungsprotokoll
|
||||
invoices.history.empty=Keine Einträge vorhanden.
|
||||
invoices.history.original=Originalrechnung
|
||||
invoices.history.cancellation=Stornobeleg
|
||||
invoices.history.correction=Berichtigungsbeleg
|
||||
invoices.history.replacement=Ersatzrechnung
|
||||
invoices.audit.action.created_draft=Entwurf erstellt
|
||||
invoices.audit.action.updated_draft=Entwurf geändert
|
||||
invoices.audit.action.issued=Ausgestellt
|
||||
invoices.audit.action.sent=Versendet
|
||||
invoices.audit.action.cancelled=Storniert
|
||||
invoices.audit.action.corrected=Berichtigt
|
||||
invoices.audit.action.replaced=Ersetzt durch neue Rechnung
|
||||
invoices.audit.action.deleted_draft=Entwurf gelöscht
|
||||
invoices.audit.action.payment_recorded=Zahlung erfasst
|
||||
invoices.audit.resulting=Erzeugter Folgebeleg: {0}
|
||||
invoices.column.payment=Zahlung
|
||||
invoices.column.outstanding=Offen
|
||||
invoices.payment.unpaid=Offen
|
||||
invoices.payment.partially_paid=Teilzahlung
|
||||
invoices.payment.paid=Bezahlt
|
||||
invoices.payment.overpaid=Überzahlung
|
||||
invoices.payment.refund_due=Erstattung offen
|
||||
invoices.action.payment=Zahlung erfassen
|
||||
invoices.action.export=Exportieren
|
||||
invoices.payment.title=Zahlung zu Rechnung {0}
|
||||
invoices.payment.hint=Offener Restbetrag: {0}. Negative Beträge können zur Korrektur erfasst werden.
|
||||
invoices.payment.amount=Zahlbetrag
|
||||
invoices.payment.amount.required=Bitte einen Betrag (ungleich 0) angeben.
|
||||
invoices.payment.reference=Zahlungsreferenz (z.B. Kontoauszug, Buchungs-Nr.)
|
||||
invoices.payment.reason=Anmerkung
|
||||
invoices.payment.confirm=Zahlung erfassen
|
||||
invoices.notification.payment=Zahlung erfasst.
|
||||
invoices.einvoice.tooltip=PDF/A-3 mit eingebettetem ZUGFeRD/XRechnung-XML
|
||||
invoices.einvoice.signed=Signiert
|
||||
invoices.action.cancel.request=Storno beantragen
|
||||
invoices.action.correct.request=Berichtigung beantragen
|
||||
invoices.notification.requested=Freigabe-Anfrage erstellt. Bitte auf Freigabe warten.
|
||||
approvals.title=Freigaben
|
||||
approvals.no.permission=Sie haben keine Berechtigung, Freigaben zu bearbeiten.
|
||||
approvals.column.requested=Beantragt am
|
||||
approvals.column.requester=Beantragt von
|
||||
approvals.column.invoice=Rechnung
|
||||
approvals.column.action=Aktion
|
||||
approvals.column.reason=Grund
|
||||
approvals.action.approve=Freigeben
|
||||
approvals.action.reject=Ablehnen
|
||||
approvals.confirm.approve.title=Anfrage zu Rechnung {0} freigeben
|
||||
approvals.confirm.reject.title=Anfrage zu Rechnung {0} ablehnen
|
||||
approvals.review.fields=Berichtigte Angaben
|
||||
approvals.review.reason=Grund
|
||||
approvals.review.comment=Kommentar (optional)
|
||||
approvals.notification.approved=Anfrage freigegeben — Folgebeleg wurde erstellt.
|
||||
approvals.notification.rejected=Anfrage abgelehnt.
|
||||
page.title.approvals=Freigaben
|
||||
|
||||
# My Invoices
|
||||
myinvoices.title=Rechnungen
|
||||
|
||||
Reference in New Issue
Block a user