feat(CC-066): add ActionPlansController (CRUD)
This commit is contained in:
parent
f3278d8264
commit
9a67e49605
1 changed files with 91 additions and 0 deletions
91
src/action-plans/action-plans.controller.ts
Normal file
91
src/action-plans/action-plans.controller.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
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, isNull } from 'drizzle-orm';
|
||||
import { CurrentSession } from '../auth/session.decorator';
|
||||
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
||||
import { db } from '../db/client';
|
||||
import { actionPlans } from '../db/schema';
|
||||
|
||||
class CreateActionPlanDto {
|
||||
@IsString() title!: string;
|
||||
@IsOptional() @IsString() description?: string;
|
||||
@IsOptional() @IsIn(['draft','active','completed','cancelled']) status?: string;
|
||||
@IsOptional() @IsIn(['low','medium','high','critical']) priority?: string;
|
||||
@IsOptional() @IsString() owner?: string;
|
||||
@IsOptional() @IsString() dueDate?: string;
|
||||
@IsOptional() @IsUUID() decisionId?: string;
|
||||
@IsOptional() @IsUUID() goalId?: string;
|
||||
@IsOptional() @IsUUID() projectId?: string;
|
||||
}
|
||||
|
||||
class UpdateActionPlanDto {
|
||||
@IsOptional() @IsString() title?: string;
|
||||
@IsOptional() @IsString() description?: string;
|
||||
@IsOptional() @IsIn(['draft','active','completed','cancelled']) status?: string;
|
||||
@IsOptional() @IsIn(['low','medium','high','critical']) priority?: string;
|
||||
@IsOptional() @IsString() owner?: string;
|
||||
@IsOptional() @IsString() dueDate?: string;
|
||||
}
|
||||
|
||||
@Controller('action-plans')
|
||||
export class ActionPlansController {
|
||||
@Get()
|
||||
async list(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Query('status') status?: string,
|
||||
) {
|
||||
const tid = session.tenantId;
|
||||
const where = status
|
||||
? and(eq(actionPlans.tenantId, tid), isNull(actionPlans.deletedAt), eq(actionPlans.status, status))
|
||||
: and(eq(actionPlans.tenantId, tid), isNull(actionPlans.deletedAt));
|
||||
return db.query.actionPlans.findMany({ where, orderBy: [desc(actionPlans.createdAt)], limit: 200 });
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateActionPlanDto) {
|
||||
const [row] = await db.insert(actionPlans).values({
|
||||
tenantId: session.tenantId,
|
||||
title: dto.title,
|
||||
description: dto.description,
|
||||
status: dto.status ?? 'draft',
|
||||
priority: dto.priority ?? 'medium',
|
||||
owner: dto.owner,
|
||||
dueDate: dto.dueDate ?? null,
|
||||
decisionId: dto.decisionId ?? null,
|
||||
goalId: dto.goalId ?? null,
|
||||
projectId: dto.projectId ?? null,
|
||||
}).returning();
|
||||
return row;
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Body() dto: UpdateActionPlanDto,
|
||||
) {
|
||||
const updates: Record<string, unknown> = { updatedAt: new Date() };
|
||||
if (dto.title !== undefined) updates.title = dto.title;
|
||||
if (dto.description !== undefined) updates.description = dto.description;
|
||||
if (dto.status !== undefined) {
|
||||
updates.status = dto.status;
|
||||
if (dto.status === 'completed') updates.completedAt = new Date();
|
||||
}
|
||||
if (dto.priority !== undefined) updates.priority = dto.priority;
|
||||
if (dto.owner !== undefined) updates.owner = dto.owner;
|
||||
if (dto.dueDate !== undefined) updates.dueDate = dto.dueDate;
|
||||
const [row] = await db.update(actionPlans)
|
||||
.set(updates)
|
||||
.where(and(eq(actionPlans.id, id), eq(actionPlans.tenantId, session.tenantId)))
|
||||
.returning();
|
||||
return row;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async remove(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||
await db.update(actionPlans)
|
||||
.set({ deletedAt: new Date() })
|
||||
.where(and(eq(actionPlans.id, id), eq(actionPlans.tenantId, session.tenantId)));
|
||||
return { deleted: true };
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue