feat(CC-067): add AssumptionsController (CRUD with confidence + status)
This commit is contained in:
parent
cbeb3b35a9
commit
f80f8e6c48
1 changed files with 82 additions and 0 deletions
82
src/assumptions/assumptions.controller.ts
Normal file
82
src/assumptions/assumptions.controller.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { Body, Controller, Delete, Get, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||
import { IsIn, IsOptional, IsString, IsUUID } from 'class-validator';
|
||||
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 { assumptions } from '../db/schema';
|
||||
|
||||
class CreateAssumptionDto {
|
||||
@IsString() statement!: string;
|
||||
@IsOptional() @IsUUID() decisionId?: string;
|
||||
@IsOptional() @IsString() source?: string;
|
||||
@IsOptional() @IsIn(['low','medium','high']) confidence?: string;
|
||||
@IsOptional() @IsString() reviewDate?: string;
|
||||
@IsOptional() @IsString() notes?: string;
|
||||
}
|
||||
|
||||
class UpdateAssumptionDto {
|
||||
@IsOptional() @IsString() statement?: string;
|
||||
@IsOptional() @IsIn(['low','medium','high']) confidence?: string;
|
||||
@IsOptional() @IsIn(['unverified','confirmed','refuted','pending_review']) status?: string;
|
||||
@IsOptional() @IsString() evidenceUrl?: string;
|
||||
@IsOptional() @IsString() notes?: string;
|
||||
@IsOptional() @IsString() reviewDate?: string;
|
||||
}
|
||||
|
||||
@Controller('assumptions')
|
||||
export class AssumptionsController {
|
||||
@Get()
|
||||
async list(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Query('decisionId') decisionId?: string,
|
||||
@Query('status') status?: string,
|
||||
) {
|
||||
const tid = session.tenantId;
|
||||
let where = eq(assumptions.tenantId, tid) as ReturnType<typeof eq>;
|
||||
if (decisionId) where = and(where, eq(assumptions.decisionId, decisionId)) as typeof where;
|
||||
if (status) where = and(where, eq(assumptions.status, status)) as typeof where;
|
||||
return db.query.assumptions.findMany({ where, orderBy: [desc(assumptions.createdAt)], limit: 300 });
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateAssumptionDto) {
|
||||
const [row] = await db.insert(assumptions).values({
|
||||
tenantId: session.tenantId,
|
||||
statement: dto.statement,
|
||||
decisionId: dto.decisionId ?? null,
|
||||
source: dto.source,
|
||||
confidence: dto.confidence ?? 'medium',
|
||||
reviewDate: dto.reviewDate ?? null,
|
||||
notes: dto.notes,
|
||||
}).returning();
|
||||
return row;
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: UpdateAssumptionDto,
|
||||
) {
|
||||
const upd: Record<string, unknown> = { updatedAt: new Date() };
|
||||
if (dto.statement !== undefined) upd.statement = dto.statement;
|
||||
if (dto.confidence !== undefined) upd.confidence = dto.confidence;
|
||||
if (dto.status !== undefined) upd.status = dto.status;
|
||||
if (dto.evidenceUrl !== undefined) upd.evidenceUrl = dto.evidenceUrl;
|
||||
if (dto.notes !== undefined) upd.notes = dto.notes;
|
||||
if (dto.reviewDate !== undefined) upd.reviewDate = dto.reviewDate;
|
||||
const [row] = await db.update(assumptions)
|
||||
.set(upd)
|
||||
.where(and(eq(assumptions.id, id), eq(assumptions.tenantId, session.tenantId)))
|
||||
.returning();
|
||||
return row;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async remove(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||
await db.delete(assumptions)
|
||||
.where(and(eq(assumptions.id, id), eq(assumptions.tenantId, session.tenantId)));
|
||||
return { deleted: true };
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue