feat(CC-067): add OutcomeReviewsController (list, create, patch with rating/lessons)
This commit is contained in:
parent
a171888ae3
commit
c2a070b33f
1 changed files with 80 additions and 0 deletions
80
src/outcome-reviews/outcome-reviews.controller.ts
Normal file
80
src/outcome-reviews/outcome-reviews.controller.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||
import { IsBoolean, IsIn, IsInt, IsOptional, IsString, IsUUID, Max, Min } from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
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 { outcomeReviews } from '../db/schema';
|
||||
|
||||
class CreateOutcomeReviewDto {
|
||||
@IsString() title!: string;
|
||||
@IsOptional() @IsUUID() decisionId?: string;
|
||||
@IsOptional() @IsString() periodStart?: string;
|
||||
@IsOptional() @IsString() periodEnd?: string;
|
||||
@IsOptional() @IsString() actualOutcome?: string;
|
||||
@IsOptional() @IsBoolean() @Type(() => Boolean) wasSuccessful?: boolean;
|
||||
@IsOptional() @IsString() lessonsLearned?: string;
|
||||
@IsOptional() @IsString() nextSteps?: string;
|
||||
@IsOptional() @IsInt() @Min(1) @Max(10) @Type(() => Number) rating?: number;
|
||||
}
|
||||
|
||||
class UpdateOutcomeReviewDto {
|
||||
@IsOptional() @IsString() title?: string;
|
||||
@IsOptional() @IsString() actualOutcome?: string;
|
||||
@IsOptional() @IsBoolean() @Type(() => Boolean) wasSuccessful?: boolean;
|
||||
@IsOptional() @IsString() lessonsLearned?: string;
|
||||
@IsOptional() @IsString() nextSteps?: string;
|
||||
@IsOptional() @IsInt() @Min(1) @Max(10) @Type(() => Number) rating?: number;
|
||||
}
|
||||
|
||||
@Controller('outcome-reviews')
|
||||
export class OutcomeReviewsController {
|
||||
@Get()
|
||||
async list(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Query('decisionId') decisionId?: string,
|
||||
) {
|
||||
const tid = session.tenantId;
|
||||
let where = eq(outcomeReviews.tenantId, tid) as ReturnType<typeof eq>;
|
||||
if (decisionId) where = and(where, eq(outcomeReviews.decisionId, decisionId)) as typeof where;
|
||||
return db.query.outcomeReviews.findMany({ where, orderBy: [desc(outcomeReviews.createdAt)], limit: 200 });
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateOutcomeReviewDto) {
|
||||
const [row] = await db.insert(outcomeReviews).values({
|
||||
tenantId: session.tenantId,
|
||||
title: dto.title,
|
||||
decisionId: dto.decisionId ?? null,
|
||||
periodStart: dto.periodStart ?? null,
|
||||
periodEnd: dto.periodEnd ?? null,
|
||||
actualOutcome: dto.actualOutcome,
|
||||
wasSuccessful: dto.wasSuccessful ?? null,
|
||||
lessonsLearned: dto.lessonsLearned,
|
||||
nextSteps: dto.nextSteps,
|
||||
rating: dto.rating ?? null,
|
||||
}).returning();
|
||||
return row;
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: UpdateOutcomeReviewDto,
|
||||
) {
|
||||
const upd: Record<string, unknown> = { updatedAt: new Date() };
|
||||
if (dto.title !== undefined) upd.title = dto.title;
|
||||
if (dto.actualOutcome !== undefined) upd.actualOutcome = dto.actualOutcome;
|
||||
if (dto.wasSuccessful !== undefined) upd.wasSuccessful = dto.wasSuccessful;
|
||||
if (dto.lessonsLearned !== undefined) upd.lessonsLearned = dto.lessonsLearned;
|
||||
if (dto.nextSteps !== undefined) upd.nextSteps = dto.nextSteps;
|
||||
if (dto.rating !== undefined) upd.rating = dto.rating;
|
||||
const [row] = await db.update(outcomeReviews)
|
||||
.set(upd)
|
||||
.where(and(eq(outcomeReviews.id, id), eq(outcomeReviews.tenantId, session.tenantId)))
|
||||
.returning();
|
||||
return row;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue