feat(cc-053): GoalsController — CRUD pentru obiective OKR
This commit is contained in:
parent
871dac9f0a
commit
04f142e7ea
1 changed files with 65 additions and 23 deletions
|
|
@ -1,42 +1,84 @@
|
|||
import { BadRequestException, Body, Controller, Delete, Get, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common';
|
||||
import { IsOptional, IsString } from 'class-validator';
|
||||
import { and, desc, eq, isNull, or, inArray } from 'drizzle-orm';
|
||||
import { CurrentSession } from '../auth/session.decorator';
|
||||
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
||||
import { CreateGoalDto, GOAL_STATUSES, UpdateGoalDto, type GoalStatusValue } from './dto';
|
||||
import { GoalsService } from './goals.service';
|
||||
import { db } from '../db/client';
|
||||
import { goals } from '../db/schema';
|
||||
|
||||
class CreateGoalDto {
|
||||
@IsString() horizon: string;
|
||||
@IsString() metric: string;
|
||||
@IsString() target: string;
|
||||
@IsOptional() @IsString() workspaceId?: string;
|
||||
}
|
||||
|
||||
class UpdateGoalDto {
|
||||
@IsOptional() @IsString() status?: string;
|
||||
@IsOptional() milestones?: unknown[];
|
||||
@IsOptional() @IsString() target?: string;
|
||||
}
|
||||
|
||||
@Controller('goals')
|
||||
export class GoalsController {
|
||||
constructor(private readonly goalsService: GoalsService) {}
|
||||
|
||||
@Get()
|
||||
list(@CurrentSession() session: AuthenticatedSession, @Query('status') status?: string) {
|
||||
if (status && !GOAL_STATUSES.includes(status as GoalStatusValue)) {
|
||||
throw new BadRequestException(`status must be one of: ${GOAL_STATUSES.join(', ')}`);
|
||||
}
|
||||
return this.goalsService.list(session, status as GoalStatusValue | undefined);
|
||||
async list(@CurrentSession() session: AuthenticatedSession) {
|
||||
return db.query.goals.findMany({
|
||||
where: and(eq(goals.tenantId, session.tenantId), isNull(goals.deletedAt)),
|
||||
orderBy: [desc(goals.createdAt)],
|
||||
limit: 100,
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
getById(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.goalsService.getById(session, id);
|
||||
@Get('at-risk')
|
||||
async atRisk(@CurrentSession() session: AuthenticatedSession) {
|
||||
return db.query.goals.findMany({
|
||||
where: and(
|
||||
eq(goals.tenantId, session.tenantId),
|
||||
isNull(goals.deletedAt),
|
||||
inArray(goals.status, ['at_risk', 'not_started']),
|
||||
),
|
||||
orderBy: [desc(goals.createdAt)],
|
||||
limit: 20,
|
||||
});
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateGoalDto) {
|
||||
return this.goalsService.create(session, dto);
|
||||
async create(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Body() dto: CreateGoalDto,
|
||||
) {
|
||||
const [created] = await db
|
||||
.insert(goals)
|
||||
.values({
|
||||
tenantId: session.tenantId,
|
||||
workspaceId: dto.workspaceId ?? null,
|
||||
ownerUserId: session.userId,
|
||||
horizon: dto.horizon,
|
||||
metric: dto.metric,
|
||||
target: dto.target,
|
||||
})
|
||||
.returning();
|
||||
return created;
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update(
|
||||
async update(
|
||||
@CurrentSession() session: AuthenticatedSession,
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@Param('id') id: string,
|
||||
@Body() dto: UpdateGoalDto,
|
||||
) {
|
||||
return this.goalsService.update(session, id, dto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
softDelete(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.goalsService.softDelete(session, id);
|
||||
const [updated] = await db
|
||||
.update(goals)
|
||||
.set({
|
||||
...(dto.status !== undefined ? { status: dto.status as any } : {}),
|
||||
...(dto.milestones !== undefined ? { milestones: dto.milestones } : {}),
|
||||
...(dto.target !== undefined ? { target: dto.target } : {}),
|
||||
updatedAt: new Date(),
|
||||
version: db.$count(goals, eq(goals.id, id)),
|
||||
})
|
||||
.where(and(eq(goals.id, id), eq(goals.tenantId, session.tenantId)))
|
||||
.returning();
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue