feat(backend): reactivate endpoint for dissolved colonies and inactive apiaries
Da fachliche Objekte nie hart geloescht werden (nur status + deactivatedAt), fehlte bisher ein Weg, ein versehentlich aufgeloestes Volk oder deaktivierten Bienenstand wieder zu aktivieren. Neue POST :id/reactivate-Endpunkte setzen status zurueck auf ACTIVE und loeschen deactivatedAt; ConflictException wenn bereits aktiv.
This commit is contained in:
1 parent
4a9fdd5c71
commit
6346bfab1d
8 files changed
+144
-2
No files matched your search
@@ -97,4 +97,10 @@ export class ColoniesController {
|
||||
dissolve(@Param('id') id: string, @CurrentUser() actor: AuthenticatedUser) {
|
||||
return this.coloniesService.dissolve(id, actor.id);
|
||||
}
|
||||
|
||||
@Roles(Role.ADMIN, Role.BEEKEEPER)
|
||||
@Post(':id/reactivate')
|
||||
reactivate(@Param('id') id: string, @CurrentUser() actor: AuthenticatedUser) {
|
||||
return this.coloniesService.reactivate(id, actor.id);
|
||||
}
|
||||
}
|
||||
@@ -170,4 +170,35 @@ describe('ColoniesService', () => {
|
||||
expect.objectContaining({ action: 'DEACTIVATE' }),
|
||||
);
|
||||
});
|
||||
|
||||
it('reactivate throws ConflictException when already active', async () => {
|
||||
prisma.colony.findUnique.mockResolvedValue(parentColony);
|
||||
await expect(
|
||||
service.reactivate('colony-1', 'user-1'),
|
||||
).rejects.toBeInstanceOf(ConflictException);
|
||||
});
|
||||
|
||||
it('reactivate sets status ACTIVE and clears deactivatedAt', async () => {
|
||||
prisma.colony.findUnique.mockResolvedValue({
|
||||
...parentColony,
|
||||
status: 'DISSOLVED',
|
||||
deactivatedAt: new Date(),
|
||||
});
|
||||
prisma.colony.update.mockResolvedValue({
|
||||
...parentColony,
|
||||
status: 'ACTIVE',
|
||||
deactivatedAt: null,
|
||||
});
|
||||
|
||||
const result = await service.reactivate('colony-1', 'user-1');
|
||||
|
||||
expect(result.status).toBe('ACTIVE');
|
||||
expect(prisma.colony.update).toHaveBeenCalledWith({
|
||||
where: { id: 'colony-1' },
|
||||
data: { status: 'ACTIVE', deactivatedAt: null },
|
||||
});
|
||||
expect(auditLog.record).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ action: 'UPDATE' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -212,6 +212,26 @@ export class ColoniesService {
|
||||
return colony;
|
||||
}
|
||||
|
||||
async reactivate(id: string, actingUserId: string): Promise<Colony> {
|
||||
const before = await this.findById(id);
|
||||
if (before.status === 'ACTIVE') {
|
||||
throw new ConflictException('Colony is already active');
|
||||
}
|
||||
const colony = await this.prisma.colony.update({
|
||||
where: { id },
|
||||
data: { status: 'ACTIVE', deactivatedAt: null },
|
||||
});
|
||||
await this.auditLog.record({
|
||||
entityType: 'Colony',
|
||||
entityId: id,
|
||||
action: 'UPDATE',
|
||||
userId: actingUserId,
|
||||
beforeData: before,
|
||||
afterData: colony,
|
||||
});
|
||||
return colony;
|
||||
}
|
||||
|
||||
async getHistory(id: string) {
|
||||
await this.findById(id);
|
||||
const [apiaryHistory, queenHistory, lineageAsSource, lineageAsResult] =
|
||||
|
||||
Reference in new issue
Block a user