feat(posteingang): Duplikat als neue Version oder verwerfen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bjoernpoettkerandClaude Opus 5.5 committed 2026-11-02 13:58:31 +01:00
1 parent 170eb72c70
commit bdc85f5f1f
6 files changed
+166 -74

No files matched your search

+8 -1
View File
@@ -87,7 +87,7 @@ export const inboxApi = {
postprocess: (
id: string,
opts?: { sectionOffset?: number; processOnlyOne?: boolean; replaceDuplicate?: boolean },
opts?: { sectionOffset?: number; processOnlyOne?: boolean; entscheidung?: PaperlessEntscheidung },
) =>
api
.post<{ results: PostprocessActionResult[]; totalSections: number }>(
@@ -132,6 +132,9 @@ export const inboxApi = {
api.post(`/api/inbox/${encodeURIComponent(id)}/send-email`, body).then(() => {}),
};
/** Entscheidung des Benutzers zu einem Duplikat bei „An Paperless senden“ */
export type PaperlessEntscheidung = { aktion: 'version'; documentId: number } | { aktion: 'verwerfen' };
export interface PostprocessActionResult {
sectionIndex: number;
actionId: number;
@@ -140,6 +143,10 @@ export interface PostprocessActionResult {
skipped?: boolean;
message?: string;
duplicateOfDocumentId?: number;
/** Duplikat mit genau einem Stammdokument → neue Version möglich */
versionMoeglich?: boolean;
duplikatKandidaten?: number[];
verworfen?: boolean;
}
export const clientsApi = {
@@ -22,7 +22,7 @@ import {
ZoomInOutlined,
ZoomOutOutlined,
} from '@ant-design/icons';
import { inboxApi, type InboxBarcode, type InboxFile, type PostprocessActionResult } from '../api/inbox';
import { inboxApi, type InboxBarcode, type InboxFile, type PaperlessEntscheidung, type PostprocessActionResult } from '../api/inbox';
import { paperlessApi } from '../api/paperless';
import { userSettingsApi, type SenderOption } from '../api/userSettings';
import { useIsMobile } from '../hooks/useIsMobile';
@@ -259,7 +259,7 @@ function PostprocessWizardModal({
setSteps((prev) => prev.map((s, i) => (i === idx ? { ...s, ...patch } as WizardStep : s)));
};
const processSection = async (idx: number, replaceDuplicate = false) => {
const processSection = async (idx: number, entscheidung?: PaperlessEntscheidung) => {
if (!documentId) return;
setBusy(true);
setStepAt(idx, { status: 'processing', message: undefined });
@@ -267,7 +267,7 @@ function PostprocessWizardModal({
const { results } = await inboxApi.postprocess(documentId, {
sectionOffset: idx,
processOnlyOne: true,
replaceDuplicate,
entscheidung,
});
const skipped = results.find((r) => r.skipped);
const failed = results.filter((r) => !r.ok);
@@ -304,8 +304,10 @@ function PostprocessWizardModal({
}, [open, currentSection, awaitingDecision, finished, busy, sectionCount]);
const handleReplace = () => {
const documentId = steps[currentSection]?.results?.find((r) => r.versionMoeglich)?.duplicateOfDocumentId;
if (documentId === undefined) return;
setAwaitingDecision(false);
void processSection(currentSection, true);
void processSection(currentSection, { aktion: 'version', documentId });
};
const handleSkip = () => {