feat(akquise): Archiv bearbeiten und wiederherstellen
Im Archiv setzte der Stift nur `editing` - das Formular stand dort nicht, also passierte sichtbar nichts. Es wird jetzt auch im Archiv gezeigt, aber nur beim Bearbeiten: eingetragen wird weiterhin im Eingang. Dazu ein Weg zurueck. `POST /api/acquisitions/:id/restore` setzt `found_at` auf heute und leert `converted_at` samt `opportunity_id` - ohne Letzteres haelt die Uebernahme einen Rueckfaeller im Archiv fest, gleich welches Datum er traegt. Eine Spalte "wiederhergestellt" gibt es bewusst nicht; die Tabelle fuehrt keinen Zustand. Der Pfeil erscheint nur im Archiv. Ein nie uebernommener Eintrag wird ohne Rueckfrage zurueckgeholt, ein Rueckfaeller mit - dabei faellt der Verweis auf die geloeschte Opportunity weg. Fuer diese Rueckfrage kennt `ConfirmDialog` jetzt `tone="neutral"`: ein roter Knopf an einer harmlosen Stelle nimmt der Farbe ihre Bedeutung. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ea886e4d1b
commit
f319b8207b
@@ -606,6 +606,53 @@ router.patch('/:id', async (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* POST /api/acquisitions/:id/restore
|
||||
*
|
||||
* Zurueck in den Eingang. Eingang und Archiv trennt allein das Funddatum -
|
||||
* deshalb setzt das Wiederherstellen es auf heute. Eine eigene Spalte
|
||||
* "wiederhergestellt" waere ein zweiter Zustand, der zum Datum driften kann.
|
||||
*
|
||||
* Bei einem Rueckfaeller (uebernommen, Opportunity weg) wird zusaetzlich die
|
||||
* Uebernahme geloest: sonst haelt `converted_at` den Eintrag im Archiv fest,
|
||||
* egal welches Datum er traegt. Der Verweis auf die Opportunity geht dabei
|
||||
* verloren - sie ist geloescht oder im Papierkorb, und der Eintrag ist wieder
|
||||
* das Original.
|
||||
*/
|
||||
router.post('/:id/restore', async (req, res, next) => {
|
||||
const id = Number(req.params.id);
|
||||
if (!Number.isInteger(id)) return res.status(400).json({ error: 'Ungültige Akquise-ID.' });
|
||||
|
||||
try {
|
||||
const [rows] = await pool.query('SELECT * FROM crm_acquisitions WHERE id = ? LIMIT 1', [id]);
|
||||
const existing = rows[0];
|
||||
if (!existing) return res.status(404).json({ error: 'Eintrag nicht gefunden.' });
|
||||
if (!mayModify(req.user, existing)) {
|
||||
return res.status(403).json({
|
||||
error:
|
||||
'Diesen Eintrag darf nur wiederherstellen, wer ihn angelegt hat, oder ein Administrator.',
|
||||
});
|
||||
}
|
||||
// Lebt die Opportunity noch, gehoert der Eintrag zu ihr und steht ohnehin
|
||||
// in keiner der beiden Listen - dann gibt es nichts wiederherzustellen.
|
||||
if (existing.converted_at !== null && !(await opportunityGone(existing.opportunity_id))) {
|
||||
return res
|
||||
.status(409)
|
||||
.json({ error: 'Der Eintrag gehört zu einer bestehenden Opportunity.' });
|
||||
}
|
||||
|
||||
await pool.query(
|
||||
`UPDATE crm_acquisitions
|
||||
SET found_at = CURDATE(), converted_at = NULL, opportunity_id = NULL
|
||||
WHERE id = ?`,
|
||||
[id]
|
||||
);
|
||||
res.json(await fetchAcquisition(id));
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/acquisitions/:id
|
||||
router.delete('/:id', async (req, res, next) => {
|
||||
const id = Number(req.params.id);
|
||||
|
||||
Reference in New Issue
Block a user