feat: implement two-step Freigabe→Zahlung workflow

Adds a payment step after document approval: PM_Freigabe approves
(Field 15 = "freigegeben"), then PM_Zahlung can mark as paid (Field 16).

- Backend: VIEW_ZAHLUNG permission mapped to PM_Zahlung OIDC group
- Backend: ZahlungModule with endpoints to list documents by filter
  (ausstehend/freigegeben/alle), set Field 16, fetch options from Paperless
- Backend: setZahlung() throws ForbiddenException if Field 15 ≠ "freigegeben"
- Frontend: /zahlung route with 3-way filter, two status columns (Freigabe + Zahlung)
- Frontend: "Zahlung verbuchen" button disabled with tooltip for non-approved docs
- Frontend: Zahlung menu item with EuroOutlined icon

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
bjoernpoettkerandClaude Sonnet 4.6 committed 2026-06-18 21:29:50 +02:00
1 parent 969f0ae0b1
commit 4d05a94681
10 files changed
+471

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
import api from './client';
export type ZahlungFilter = 'ausstehend' | 'freigegeben' | 'alle';
export interface ZahlungDocument {
id: number;
title: string;
created: string;
created_date: string;
correspondent: number | null;
document_type: number | null;
archive_serial_number: number | null;
tags: number[];
custom_fields: { field: number; value: any }[];
}
export interface ZahlungOption {
id: string;
label: string;
}
export interface ZahlungResult {
count: number;
results: ZahlungDocument[];
}
export const zahlungApi = {
getDocuments: (page = 1, pageSize = 25, filter: ZahlungFilter = 'ausstehend') =>
api
.get<ZahlungResult>('/api/zahlung/documents', { params: { page, pageSize, filter } })
.then((r) => r.data),
setZahlung: (docId: number, value: string | null) =>
api
.put<{ success: boolean }>(`/api/zahlung/documents/${docId}/zahlung`, { value })
.then((r) => r.data),
getOptions: () =>
api.get<ZahlungOption[]>('/api/zahlung/options').then((r) => r.data),
};