feat(akquise): Papierkorb fuer geloeschte Eintraege
Loeschen in der Akquise war ein echtes DELETE: der Eintrag stand danach in keiner Liste, auch nicht im Archiv, und war nicht zurueckholbar. Jetzt setzt es `deleted_at`/`deleted_by`, die Zeile bleibt 90 Tage stehen. Der Papierkorb ist die eine Ausnahme von der Regel, dass diese Tabelle keinen Zustand fuehrt: Loeschen von Hand ist eine Entscheidung, kein Ablauf. Was dort liegt, blenden alle anderen Abfragen ueber NOT_DELETED aus - Eingang, Archiv, Menuezahlen und Dashboard. Der Aufraeumlauf ueber `found_at` laesst geloeschte Zeilen ausdruecklich liegen, sonst waere ein alter Fund im Papierkorb sofort weg; der Papierkorb raeumt ab `deleted_at`. Zwei Rueckwege, deshalb zwei Routen. `/reopen` (bisher `/restore`) holt aus dem Archiv in den Eingang und setzt das Funddatum auf heute. `/restore` holt aus dem Papierkorb zurueck und laesst das Funddatum in Ruhe - der Eintrag soll dort auftauchen, wo er hingehoert, also im Archiv, wenn er alt ist. Die Meldung nennt das Ziel. Dazu `DELETE /:id/permanent` und `POST /trash/empty`. Im Papierkorb wird nicht gepflegt: Bearbeiten und Uebernehmen antworten 409. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f319b8207b
commit
6e66bd39d7
+21
-4
@@ -246,6 +246,7 @@ export const dashboardApi = {
|
||||
*/
|
||||
export interface SidebarBadges {
|
||||
acquisition_archive: number;
|
||||
acquisition_trash: number;
|
||||
opportunity_trash: number;
|
||||
mail_trash: number;
|
||||
scanner_rejected: number | null;
|
||||
@@ -283,7 +284,7 @@ export type AcquisitionInput = Partial<
|
||||
fixed_price?: string | number | null;
|
||||
};
|
||||
|
||||
export type AcquisitionView = 'eingang' | 'archiv' | 'alle';
|
||||
export type AcquisitionView = 'eingang' | 'archiv' | 'papierkorb' | 'alle';
|
||||
|
||||
export const acquisitionsApi = {
|
||||
list: (view: AcquisitionView = 'eingang') =>
|
||||
@@ -292,16 +293,32 @@ export const acquisitionsApi = {
|
||||
request<Acquisition>('/acquisitions', { method: 'POST', body: JSON.stringify(input) }),
|
||||
update: (id: number, input: AcquisitionInput) =>
|
||||
request<Acquisition>(`/acquisitions/${id}`, { method: 'PATCH', body: JSON.stringify(input) }),
|
||||
/** Legt den Eintrag in den Papierkorb - endgueltig loeschen tut `purge`. */
|
||||
remove: (id: number) => request<{ ok: true }>(`/acquisitions/${id}`, { method: 'DELETE' }),
|
||||
|
||||
/**
|
||||
* Zurueck in den Eingang: Funddatum auf heute, und bei einem Rueckfaeller
|
||||
* wird die Uebernahme geloest (der Verweis auf die geloeschte Opportunity
|
||||
* faellt weg).
|
||||
* Aus dem Archiv zurueck in den Eingang: Funddatum auf heute, und bei einem
|
||||
* Rueckfaeller wird die Uebernahme geloest (der Verweis auf die geloeschte
|
||||
* Opportunity faellt weg). Nicht der Papierkorb - der ist `restore`.
|
||||
*/
|
||||
reopen: (id: number) =>
|
||||
request<Acquisition>(`/acquisitions/${id}/reopen`, { method: 'POST' }),
|
||||
|
||||
/**
|
||||
* Aus dem Papierkorb zurueckholen. Das Funddatum bleibt - der Eintrag landet
|
||||
* wieder dort, wo er hingehoert: im Eingang, wenn er jung ist, sonst im Archiv.
|
||||
*/
|
||||
restore: (id: number) =>
|
||||
request<Acquisition>(`/acquisitions/${id}/restore`, { method: 'POST' }),
|
||||
|
||||
/** Endgueltig loeschen; geht nur aus dem Papierkorb heraus. */
|
||||
purge: (id: number) =>
|
||||
request<{ ok: true }>(`/acquisitions/${id}/permanent`, { method: 'DELETE' }),
|
||||
|
||||
/** Papierkorb in einem Zug leeren. */
|
||||
emptyTrash: () =>
|
||||
request<{ ok: true; purged: number }>('/acquisitions/trash/empty', { method: 'POST' }),
|
||||
|
||||
/** Legt die Opportunity an und vermerkt den Eintrag als uebernommen. */
|
||||
toOpportunity: (id: number) =>
|
||||
request<{ ok: true; opportunity_id: number }>(`/acquisitions/${id}/opportunity`, {
|
||||
|
||||
Reference in New Issue
Block a user