fix(queens): verlorene, eingegangene, ersetzte und verkaufte Königinnen ins Archiv
Backend E2E / e2e (push) Successful in 6m11s
Backend Image / build-and-push (push) Successful in 5m17s
Frontend Image / build-and-push (push) Successful in 15m8s

Die Königinnen-Liste trennt Aktiv und Historie über deactivatedAt, das
Backend setzte das Feld aber nie. Jetzt stempelt ein Statuswechsel auf
LOST, DECEASED, REPLACED oder SOLD das Datum (update und updateStatusIn),
ein korrigierter Status nimmt es wieder weg. Die Migration
20261021100000_queen_deactivated_backfill trägt das Datum für bestehende
Königinnen nach (Ende der letzten Volkszuordnung, sonst updatedAt).
Auch die Lebensdauer in der Statistik rechnet damit wieder.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick.RosenloecherandClaude Opus 5.5 committed 2026-10-19 16:48:25 +02:00
1 parent 39eee3cdb1
commit 1688e77a89
5 files changed
+227 -3

No files matched your search

+51
View File
@@ -26,6 +26,7 @@ describe('Queens (e2e)', () => {
let daughterQueenId: string;
let secondColonyId: string;
let subscriptionId: string;
let retiredQueenId: string;
beforeAll(async () => {
app = await createTestApp();
@@ -104,6 +105,9 @@ describe('Queens (e2e)', () => {
data: { currentQueenId: null },
});
}
if (retiredQueenId) {
await prisma.queen.delete({ where: { id: retiredQueenId } });
}
if (daughterQueenId) {
await prisma.queen.delete({ where: { id: daughterQueenId } });
}
@@ -307,4 +311,51 @@ describe('Queens (e2e)', () => {
expect(daughterBody.queen.mother?.id).toBe(queenId);
expect(daughterBody.descendants).toHaveLength(0);
});
it('moves a queen into the history when she dies and back when the status is corrected', async () => {
const created = await request(app.getHttpServer())
.post('/api/v1/queens')
.set('Authorization', `Bearer ${beekeeperToken}`)
.send({ code: `Q-retired-${Date.now()}` })
.expect(201);
retiredQueenId = (created.body as QueenBody).id;
expect(
(created.body as { deactivatedAt: string | null }).deactivatedAt,
).toBeNull();
const deceased = await request(app.getHttpServer())
.patch(`/api/v1/queens/${retiredQueenId}`)
.set('Authorization', `Bearer ${beekeeperToken}`)
.send({ status: 'DECEASED' })
.expect(200);
expect(
(deceased.body as { deactivatedAt: string | null }).deactivatedAt,
).toEqual(expect.any(String));
const list = await request(app.getHttpServer())
.get('/api/v1/queens')
.set('Authorization', `Bearer ${beekeeperToken}`)
.expect(200);
const listed = (
list.body as { id: string; deactivatedAt: string | null }[]
).find((queen) => queen.id === retiredQueenId);
expect(listed?.deactivatedAt).toEqual(expect.any(String));
const corrected = await request(app.getHttpServer())
.patch(`/api/v1/queens/${retiredQueenId}`)
.set('Authorization', `Bearer ${beekeeperToken}`)
.send({ status: 'ACTIVE' })
.expect(200);
expect(
(corrected.body as { deactivatedAt: string | null }).deactivatedAt,
).toBeNull();
});
it('does not let a client set deactivatedAt directly', () => {
return request(app.getHttpServer())
.patch(`/api/v1/queens/${queenId}`)
.set('Authorization', `Bearer ${beekeeperToken}`)
.send({ deactivatedAt: new Date().toISOString() })
.expect(400);
});
});