feat: add Agrarmonitor correspondent sync
Build and Push Multi-Platform Images / build-and-push (push) Successful in 39s

- Extract getOrCreateCorrespondent helper to deduplicate logic
- Add syncCorrespondentIds to match Paperless correspondents to
  Agrarmonitor IDs via Lieferantennummer and persist in CorrespondentSetting
- New POST /api/agrarmonitor/sync-correspondents endpoint
- "Agrarmonitor-Abgleich" button in Correspondents settings tab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 14:01:33 +02:00
parent bbdaf19fff
commit b4fe5a336c
5 changed files with 103 additions and 39 deletions
+2
View File
@@ -225,4 +225,6 @@ export const agrarmonitorApi = {
api.post<AgrarmonitorPollingResult>('/api/agrarmonitor/run-polling').then((r) => r.data),
processUploads: () =>
api.post<AgrarmonitorPollingResult>('/api/agrarmonitor/process-uploads').then((r) => r.data),
syncCorrespondents: () =>
api.post<{ total: number; matched: number; unmatched: number }>('/api/agrarmonitor/sync-correspondents').then((r) => r.data),
};
+22 -3
View File
@@ -1408,6 +1408,7 @@ function CorrespondentsTab() {
const [pageSize, setPageSize] = useState(50);
const [searchText, setSearchText] = useState('');
const [createModalOpen, setCreateModalOpen] = useState(false);
const [syncLoading, setSyncLoading] = useState(false);
const [form] = Form.useForm();
const load = useCallback(async (page: number, size: number, search?: string) => {
@@ -1440,6 +1441,19 @@ function CorrespondentsTab() {
}
};
const handleSync = async () => {
setSyncLoading(true);
try {
const result = await agrarmonitorApi.syncCorrespondents();
message.success(`Abgleich abgeschlossen: ${result.matched} zugeordnet, ${result.unmatched} ohne Treffer (${result.total} gesamt)`);
load(currentPage, pageSize, searchText);
} catch (err) {
message.error('Fehler beim Agrarmonitor-Abgleich');
} finally {
setSyncLoading(false);
}
};
const updateAgrarmonitorId = async (id: number, val: number | null) => {
try {
await settingsApi.updateCorrespondentSetting(id, val);
@@ -1497,9 +1511,14 @@ function CorrespondentsTab() {
onSearch={(v) => { setSearchText(v); setCurrentPage(1); }}
style={{ width: 300 }}
/>
<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateModalOpen(true)}>
Neuen Korrespondenten anlegen
</Button>
<Space>
<Button icon={<GlobalOutlined />} loading={syncLoading} onClick={handleSync}>
Agrarmonitor-Abgleich
</Button>
<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateModalOpen(true)}>
Neuen Korrespondenten anlegen
</Button>
</Space>
</Space>
</div>