From 1758150cebe874a93f15c27d331df097e3c1166a Mon Sep 17 00:00:00 2001 From: admin-valentin Date: Sat, 1 Aug 2026 21:24:22 +0000 Subject: [PATCH] feat(CC-064): add ObligationsController (deadlines & obligations with risk level) --- src/obligations/obligations.controller.ts | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/obligations/obligations.controller.ts diff --git a/src/obligations/obligations.controller.ts b/src/obligations/obligations.controller.ts new file mode 100644 index 0000000..7a7f5ea --- /dev/null +++ b/src/obligations/obligations.controller.ts @@ -0,0 +1,51 @@ +import { Body, Controller, Get, IsOptional, IsString, NotFoundException, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common'; +import { and, desc, eq } from 'drizzle-orm'; +import { CurrentSession } from '../auth/session.decorator'; +import type { AuthenticatedSession } from '../auth/tenant.guard'; +import { db } from '../db/client'; +import { obligations } from '../db/schema'; + +class CreateObligationDto { + @IsString() title!: string; + @IsOptional() @IsString() description?: string; + @IsOptional() @IsString() category?: string; + @IsOptional() @IsString() dueDate?: string; + @IsOptional() @IsString() owner?: string; + @IsOptional() @IsString() contractId?: string; + @IsOptional() @IsString() riskLevel?: string; +} + +class UpdateObligationDto { + @IsOptional() @IsString() title?: string; + @IsOptional() @IsString() description?: string; + @IsOptional() @IsString() status?: string; + @IsOptional() @IsString() dueDate?: string; + @IsOptional() @IsString() owner?: string; + @IsOptional() @IsString() evidenceUrl?: string; + @IsOptional() @IsString() riskLevel?: string; +} + +@Controller('obligations') +export class ObligationsController { + @Get() + async list(@CurrentSession() session: AuthenticatedSession, @Query('status') status?: string) { + const where = status + ? and(eq(obligations.tenantId, session.tenantId), eq(obligations.status, status)) + : eq(obligations.tenantId, session.tenantId); + return db.query.obligations.findMany({ where, orderBy: desc(obligations.createdAt), limit: 200 }); + } + + @Post() + async create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateObligationDto) { + const [obligation] = await db.insert(obligations).values({ ...dto, tenantId: session.tenantId }).returning(); + return obligation; + } + + @Patch(':id') + async update(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateObligationDto) { + const [updated] = await db.update(obligations).set({ ...dto, updatedAt: new Date() }) + .where(and(eq(obligations.id, id), eq(obligations.tenantId, session.tenantId))).returning(); + if (!updated) throw new NotFoundException('Obligation not found'); + return updated; + } +}