diff --git a/paperless-backend/src/inbox-postprocessor/inbox-postprocessor.service.ts b/paperless-backend/src/inbox-postprocessor/inbox-postprocessor.service.ts index c93bd88..567bc90 100644 --- a/paperless-backend/src/inbox-postprocessor/inbox-postprocessor.service.ts +++ b/paperless-backend/src/inbox-postprocessor/inbox-postprocessor.service.ts @@ -56,6 +56,8 @@ export interface ActionResult { duplikatKandidaten?: number[]; /** Der Benutzer hat das Duplikat verworfen */ verworfen?: boolean; + /** Aufgelöste interne Belegnummer (bei Duplikaten) */ + belegnummer?: string; } export interface RunForDocumentResult { @@ -69,6 +71,7 @@ interface PaperlessRunResult { duplicateOfDocumentId?: number; versionMoeglich?: boolean; duplikatKandidaten?: number[]; + belegnummer?: string; } @Injectable() @@ -302,6 +305,7 @@ export class InboxPostprocessorService { duplicateOfDocumentId: res.duplicateOfDocumentId, versionMoeglich: res.versionMoeglich, duplikatKandidaten: res.duplikatKandidaten, + belegnummer: res.belegnummer, }); if (res.skipped) { abortProcessing = true; @@ -490,6 +494,7 @@ export class InboxPostprocessorService { duplicateOfDocumentId: pruefung.documentId ?? pruefung.kandidaten[0], versionMoeglich: pruefung.status === 'eindeutig', duplikatKandidaten: pruefung.kandidaten, + belegnummer: interneBelegnummer, }; } @@ -506,6 +511,7 @@ export class InboxPostprocessorService { message: `Duplikat – Belegnummer ${interneBelegnummer} bereits vorhanden`, duplicateOfDocumentId: existingTask.PaperlessDocumentID ?? undefined, versionMoeglich: false, + belegnummer: interneBelegnummer, }; } diff --git a/paperless-frontend/src/api/inbox.ts b/paperless-frontend/src/api/inbox.ts index b6a3277..5502357 100644 --- a/paperless-frontend/src/api/inbox.ts +++ b/paperless-frontend/src/api/inbox.ts @@ -147,6 +147,7 @@ export interface PostprocessActionResult { versionMoeglich?: boolean; duplikatKandidaten?: number[]; verworfen?: boolean; + belegnummer?: string; } export const clientsApi = { diff --git a/paperless-frontend/src/components/DuplikatVergleichModal.tsx b/paperless-frontend/src/components/DuplikatVergleichModal.tsx new file mode 100644 index 0000000..c9fffaa --- /dev/null +++ b/paperless-frontend/src/components/DuplikatVergleichModal.tsx @@ -0,0 +1,173 @@ +import { useEffect, useState, type ReactNode } from 'react'; +import { Alert, Button, Modal, Space, Spin, Tag, Typography, message } from 'antd'; +import { paperlessApi, type BelegnummerPruefung, type VergleichKennzahlen } from '../api/paperless'; +import { useIsMobile } from '../hooks/useIsMobile'; + +export interface DuplikatVergleichModalProps { + open: boolean; + belegnummer: string; + /** eindeutig → Version möglich; mehrdeutig → nur Verwerfen */ + pruefung: BelegnummerPruefung | null; + /** Vorhandenes Dokument (linke Seite) */ + paperlessDocumentId: number | null; + /** Neuer Beleg (rechte Seite) */ + ladeNeuesPdf: () => Promise; + ladeKennzahlen: () => Promise; + onVersion: () => void; + onVerwerfen: () => void; + onClose: () => void; +} + +function KennzahlZeile({ label, vorhanden, neu }: { label: string; vorhanden: number | null; neu: number | null }) { + const anzeige = (wert: number | null) => (wert === null ? 'nicht ermittelbar' : String(wert)); + const vergleichbar = vorhanden !== null && neu !== null; + const abweichung = vergleichbar && vorhanden !== neu; + return ( +
+ {label}: {anzeige(vorhanden)} (vorhanden) → {anzeige(neu)} (neu){' '} + {abweichung && abweichend} + {!vergleichbar && nicht vergleichbar} +
+ ); +} + +function PdfSpalte({ titel, url, loading }: { titel: string; url: string | null; loading: boolean }) { + return ( +
+ + {titel} + +
+ {loading || !url ? ( +
+ +
+ ) : ( +