docs(payments): add complete German payment guidance

This commit is contained in:
2026-08-23 01:54:19 +02:00
parent e08bc8b992
commit eb3a607a4f
6 changed files with 177 additions and 6 deletions
+2 -2
View File
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
[project]
name = "govoplan-payments"
version = "0.1.20"
version = "0.1.21"
description = "Replay-safe payment obligations and reconciliation evidence for GovOPlaN."
readme = "README.md"
requires-python = ">=3.12"
authors = [{ name = "GovOPlaN" }]
dependencies = ["govoplan-core>=0.1.18"]
dependencies = ["govoplan-core>=0.1.37"]
[tool.setuptools.packages.find]
where = ["src"]
+1 -1
View File
@@ -1,3 +1,3 @@
"""GovOPlaN Payments module."""
__version__ = "0.1.20"
__version__ = "0.1.21"
+141 -1
View File
@@ -8,6 +8,7 @@ from govoplan_core.core.module_guards import (
)
from govoplan_core.core.modules import (
CapabilityDocumentation,
DocumentationCondition,
DocumentationLink,
DocumentationTopic,
FrontendModule,
@@ -35,7 +36,7 @@ from govoplan_payments.backend.service import SqlPaymentRequestProvider
MODULE_ID = "payments"
MODULE_NAME = "Payments"
MODULE_VERSION = "0.1.20"
MODULE_VERSION = "0.1.21"
READ_SCOPE = "payments:payment:read"
WRITE_SCOPE = "payments:payment:write"
RECONCILE_SCOPE = "payments:payment:reconcile"
@@ -277,6 +278,7 @@ manifest = ModuleManifest(
audience=("data_subject", "operator", "auditor", "module_admin"),
related_modules=("core", "cases", "workflow_engine", "ledger"),
metadata={
"kind": "reference",
"help_contexts": [
"payments.workspace",
"payments.state.requested",
@@ -298,6 +300,48 @@ manifest = ModuleManifest(
),
},
},
translations={
"de": {
"title": "Datenschutzanfragen zu Zahlungen",
"summary": (
"Exakte Zahlungsverpflichtungen und Finanznachweise exportieren, ohne "
"Zahlungsbeschreibungen als Identitätssuchfläche zu verwenden."
),
"body": (
"Payments besitzt keine Spalte für Einwohner- oder Antragstelleridentitäten und "
"durchsucht weder Zahlungsbetreffe noch Kontext-JSON, Metadaten oder Quelldatensätze "
"nach einer Person. Eine vollständige Finanzauskunft erfordert deshalb eine exakte "
"Zahlungszeilenkennung, Zahlungskennung oder menschenlesbare Zahlungsreferenz, die als "
"verifizierte externe Betroffenenreferenz bereitgestellt wird. Das Auskunftspaket enthält "
"Verpflichtungsbetrag, Währung, Betreff, Status, Zeitpunkte, Quell- und begrenzte "
"Kontextreferenzen, Abstimmungsfakten, typisierte Nachweisreferenzen und Fakten zu "
"Lebenszyklusereignissen. Abstimmungsmetadaten, Ereignisinhalte, Prüfsummen, "
"Wiederholungsschlüssel, Anbieterdaten, Prüf-URLs und Zugangsdaten bleiben ausgeschlossen. "
"Eine Anfrage nur mit Konto-, Mitgliedschafts-, Identitäts- oder exakter Akteursreferenz "
"liefert minimierte Zuschreibungen zu Anforderung, Abstimmung und Ereignissen dieser "
"bearbeitenden Person; Zahlungsbetreffe werden nicht offengelegt. Jedes Ergebnis ist exakt "
"mandantenbegrenzt. Alle Löschaktionen sind reine Aufbewahrungsergebnisse und nicht "
"ausführbar, weil Verpflichtungen, Erfüllungen, Nachweisverknüpfungen und "
"Lebenszykluszuschreibungen gesteuerte finanzielle und gesetzliche Nachweise bleiben."
),
}
},
structured_translation_version="1",
structured_translations={
"de": {
"consequence_classes": {
"export_exact_payment": (
"Gibt Verpflichtung und begrenzte Finanznachweise für eine verifizierte exakte Zahlungskennung zurück."
),
"export_operator_attribution": (
"Gibt minimierte Finanzaktivität, aber niemals beliebige Zahlungsinhalte zurück."
),
"retain_payment_evidence": (
"Bewahrt Finanznachweise gemäß konfigurierter gesetzlicher Aufbewahrung und Sperre auf."
),
}
}
},
),
DocumentationTopic(
id="payments.requests-and-reconciliation",
@@ -313,6 +357,8 @@ manifest = ModuleManifest(
layer="configured",
documentation_types=("admin", "user"),
audience=("operator", "module_admin", "auditor", "product_owner"),
conditions=(DocumentationCondition(required_scopes=(READ_SCOPE,)),),
related_modules=("cases", "workflow_engine", "audit", "ledger"),
links=(
DocumentationLink(
label="Payments boundary and recovery",
@@ -321,6 +367,7 @@ manifest = ModuleManifest(
),
),
metadata={
"kind": "workflow",
"help_contexts": [
"payments.request",
"payments.workspace",
@@ -329,6 +376,26 @@ manifest = ModuleManifest(
"payments.state.requested",
"payments.state.paid",
],
"purpose": (
"Create an exact payment obligation and reconcile it as paid only against matching immutable evidence."
),
"prerequisites": [
"The actor can read Payments; creating and reconciling require their dedicated scopes.",
"The source procedure supplies a stable same-tenant reference and a replay-safe request key.",
"Manual reconciliation has a same-tenant versioned or checksum-bound evidence reference.",
],
"steps": [
"Create the amount, currency, source reference, due date, and human payment reference in the guided dialog.",
"Retain the returned payment ID in the calling Case or Workflow instead of writing Payments tables.",
"Reload the obligation before reconciliation when the workspace reports stale data.",
"Provide the external transaction reference, exact settlement time, and immutable evidence reference.",
"Confirm full amount and currency; any mismatch, duplicate, partial amount, or cross-tenant evidence fails closed.",
"Review the appended lifecycle and audit evidence after the obligation becomes paid.",
],
"limitations": [
"Only full manual reconciliation is supported; partial payment, refund, reversal, and correction need future governed flows.",
"Online checkout, callbacks, Ledger posting, XRechnung, and an applicant payment page are not implemented here.",
],
"privacy_notes": [
"Procedure context uses stable references; applicant names, bank account details, and submitted form values are not required.",
"The immutable evidence remains owned by its provider; Payments stores only the typed EvidenceReference.",
@@ -337,6 +404,79 @@ manifest = ModuleManifest(
"request_payment": "Creates a durable amount/currency obligation and a stable applicant payment reference.",
"reconcile_manual": "Marks the exact obligation paid and appends evidence; a future governed adjustment is required to reverse it.",
},
"verification": [
"The paid obligation retains the original amount, currency, payment ID, and human reference unchanged.",
"Reconciliation names the external transaction and immutable evidence reference.",
"Replay and duplicate checks prove that one external settlement did not create conflicting paid states.",
],
},
translations={
"de": {
"title": "Zahlungsanforderungen und manuelle Abstimmung",
"summary": (
"Eine exakte Verpflichtung anlegen und nur mit passendem unveränderlichem "
"Nachweis als bezahlt kennzeichnen."
),
"body": (
"Payments führt die mandantengebundene Zahlungskennung, die menschenlesbare "
"Zahlungsreferenz, angeforderten Betrag und Währung, Lebenszyklusereignisse und "
"Abstimmungsnachweise. Ein Case, Workflow oder anderes Verfahren ruft die Fähigkeit "
"payments.requests mit eigener Quellreferenz und Wiederholungsschlüssel auf und bewahrt "
"die zurückgegebene Zahlungskennung auf, statt Payments-Tabellen zu schreiben. Der "
"Arbeitsbereich zeigt angeforderte und bezahlte Verpflichtungen mit Quelle, Fälligkeit "
"oder Erfüllungszeit und Abstimmungsnachweis. Schreibberechtigte legen eine Anforderung im "
"geführten Dialog an. Abstimmungsberechtigte verwenden den getrennten folgenreichen Dialog, "
"der Betrag und Währung fixiert und eine externe Transaktionsreferenz sowie eine "
"mandantengleiche versionierte oder prüfsummengebundene EvidenceReference verlangt. Neu "
"laden erhält vorhandene Daten und kennzeichnet sie als veraltet, wenn die Aktualisierung "
"scheitert. Fehlende Anlege- oder Abstimmungsberechtigung bleibt mit erforderlicher "
"Berechtigung und zuständiger Administration sichtbar. Der erste unterstützte Zahlungseingang "
"ist die manuelle Abstimmung einer vollständigen Zahlung. Abweichung, doppelte Erfüllung unter "
"anderem Schlüssel, mandantenfremder Nachweis, Teilbetrag oder Zeitstempel ohne Zeitzone "
"scheitert geschlossen. Erfolgreiche Anforderungen und Abstimmungen fügen "
"Zahlungsereignisse an; API-Aktionen erzeugen bei installiertem Audit Nachweise. Es gibt keine "
"stille Korrektur: Storno, Erstattung, Teilzahlung, Online-Checkout, Anbieter-Callbacks, "
"Ledger-Buchung und XRechnung bleiben ausdrückliche zukünftige Abläufe."
),
}
},
structured_translation_version="1",
structured_translations={
"de": {
"purpose": (
"Eine exakte Zahlungsverpflichtung anlegen und nur anhand passender unveränderlicher Nachweise als bezahlt abstimmen."
),
"prerequisites": [
"Die handelnde Person darf Payments lesen; Anlegen und Abstimmen erfordern ihre jeweils eigenen Berechtigungen.",
"Das Quellverfahren liefert eine stabile mandantengleiche Referenz und einen wiederholungssicheren Anforderungsschlüssel.",
"Für die manuelle Abstimmung liegt eine mandantengleiche versionierte oder prüfsummengebundene Nachweisreferenz vor.",
],
"steps": [
"Betrag, Währung, Quellreferenz, Fälligkeit und menschenlesbare Zahlungsreferenz im geführten Dialog anlegen.",
"Die zurückgegebene Zahlungskennung im aufrufenden Case oder Workflow bewahren, statt Payments-Tabellen zu schreiben.",
"Die Verpflichtung vor der Abstimmung neu laden, wenn der Arbeitsbereich veraltete Daten meldet.",
"Externe Transaktionsreferenz, exakte Erfüllungszeit und unveränderliche Nachweisreferenz angeben.",
"Vollständigen Betrag und Währung bestätigen; Abweichung, Duplikat, Teilbetrag oder mandantenfremder Nachweis scheitert geschlossen.",
"Nach dem Wechsel auf bezahlt die angefügten Lebenszyklus- und Auditnachweise prüfen.",
],
"limitations": [
"Nur vollständige manuelle Abstimmung wird unterstützt; Teilzahlung, Erstattung, Storno und Korrektur benötigen zukünftige gesteuerte Abläufe.",
"Online-Checkout, Callbacks, Ledger-Buchung, XRechnung und eine Antragsteller-Zahlungsseite sind hier nicht implementiert.",
],
"privacy_notes": [
"Verfahrenskontext verwendet stabile Referenzen; Namen von Antragstellern, Bankverbindungen und übermittelte Formularwerte sind nicht erforderlich.",
"Der unveränderliche Nachweis bleibt Eigentum seines Anbieters; Payments speichert nur die typisierte EvidenceReference.",
],
"consequence_classes": {
"request_payment": "Erzeugt eine dauerhafte Betrags- und Währungsverpflichtung sowie eine stabile Zahlungsreferenz für Antragsteller.",
"reconcile_manual": "Kennzeichnet die exakte Verpflichtung als bezahlt und fügt Nachweise an; eine zukünftige gesteuerte Anpassung ist zur Umkehr erforderlich.",
},
"verification": [
"Die bezahlte Verpflichtung bewahrt ursprünglichen Betrag, Währung, Zahlungskennung und menschenlesbare Referenz unverändert.",
"Die Abstimmung nennt externe Transaktion und unveränderliche Nachweisreferenz.",
"Wiederholungs- und Duplikatprüfungen belegen, dass eine externe Erfüllung keine widersprüchlichen Bezahltzustände erzeugt hat.",
],
}
},
),
),
+31
View File
@@ -0,0 +1,31 @@
from __future__ import annotations
import unittest
from govoplan_core.core.modules import (
documentation_structured_translation_issues,
user_workflow_scope_condition_issues,
)
from govoplan_payments.backend.manifest import manifest
class PaymentsDocumentationTests(unittest.TestCase):
def test_public_topics_have_complete_german_reference_content(self) -> None:
self.assertEqual(2, len(manifest.documentation))
for topic in manifest.documentation:
translation = topic.translations.get("de", {})
self.assertTrue(
all(translation.get(key) for key in ("title", "summary", "body"))
)
self.assertEqual((), documentation_structured_translation_issues(topic))
def test_documentation_has_scope_conditioned_workflow_and_reference(self) -> None:
kinds = {topic.metadata.get("kind") for topic in manifest.documentation}
self.assertIn("workflow", kinds)
self.assertIn("reference", kinds)
for topic in manifest.documentation:
self.assertEqual((), user_workflow_scope_condition_issues(topic))
if __name__ == "__main__":
unittest.main()
+1 -1
View File
@@ -201,7 +201,7 @@ class PaymentTests(unittest.TestCase):
self.assertEqual((), self.provider.list_payments(self.session, tenant_id="tenant-2"))
def test_manifest_exposes_permission_bounded_operator_workspace(self) -> None:
self.assertEqual("0.1.20", manifest.version)
self.assertEqual("0.1.21", manifest.version)
self.assertIsNotNone(manifest.frontend)
assert manifest.frontend is not None
self.assertEqual("@govoplan/payments-webui", manifest.frontend.package_name)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@govoplan/payments-webui",
"version": "0.1.20",
"version": "0.1.21",
"private": true,
"type": "module",
"main": "src/index.ts",