feat(CC-064): add ContractsController (CRUD contracts with parties/status)
This commit is contained in:
parent
c3ecab8259
commit
76cf59d82e
1 changed files with 70 additions and 0 deletions
70
src/contracts/contracts.controller.ts
Normal file
70
src/contracts/contracts.controller.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Body, Controller, Get, HttpCode, IsArray, IsOptional, IsString, NotFoundException, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||||
|
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 { contracts } from '../db/schema';
|
||||||
|
|
||||||
|
class CreateContractDto {
|
||||||
|
@IsString() title!: string;
|
||||||
|
@IsOptional() @IsString() contractType?: string;
|
||||||
|
@IsOptional() @IsString() organizationId?: string;
|
||||||
|
@IsOptional() @IsArray() parties?: string[];
|
||||||
|
@IsOptional() @IsString() startDate?: string;
|
||||||
|
@IsOptional() @IsString() endDate?: string;
|
||||||
|
@IsOptional() @IsString() notes?: string;
|
||||||
|
@IsOptional() @IsArray() tags?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateContractDto {
|
||||||
|
@IsOptional() @IsString() title?: string;
|
||||||
|
@IsOptional() @IsString() status?: string;
|
||||||
|
@IsOptional() @IsString() contractType?: string;
|
||||||
|
@IsOptional() @IsArray() parties?: string[];
|
||||||
|
@IsOptional() @IsString() startDate?: string;
|
||||||
|
@IsOptional() @IsString() endDate?: string;
|
||||||
|
@IsOptional() @IsString() notes?: string;
|
||||||
|
@IsOptional() @IsArray() tags?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller('contracts')
|
||||||
|
export class ContractsController {
|
||||||
|
@Get()
|
||||||
|
async list(@CurrentSession() session: AuthenticatedSession, @Query('status') status?: string) {
|
||||||
|
const where = status
|
||||||
|
? and(eq(contracts.tenantId, session.tenantId), isNull(contracts.deletedAt), eq(contracts.status, status))
|
||||||
|
: and(eq(contracts.tenantId, session.tenantId), isNull(contracts.deletedAt));
|
||||||
|
return db.query.contracts.findMany({ where, orderBy: desc(contracts.createdAt), limit: 200 });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
async create(@CurrentSession() session: AuthenticatedSession, @Body() dto: CreateContractDto) {
|
||||||
|
const [contract] = await db.insert(contracts).values({
|
||||||
|
...dto, tenantId: session.tenantId, parties: dto.parties ?? [], tags: dto.tags ?? [],
|
||||||
|
}).returning();
|
||||||
|
return contract;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
async getOne(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||||
|
const contract = await db.query.contracts.findFirst({
|
||||||
|
where: and(eq(contracts.id, id), eq(contracts.tenantId, session.tenantId), isNull(contracts.deletedAt)),
|
||||||
|
});
|
||||||
|
if (!contract) throw new NotFoundException('Contract not found');
|
||||||
|
return contract;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(':id')
|
||||||
|
async update(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string, @Body() dto: UpdateContractDto) {
|
||||||
|
const [updated] = await db.update(contracts).set({ ...dto, updatedAt: new Date() })
|
||||||
|
.where(and(eq(contracts.id, id), eq(contracts.tenantId, session.tenantId))).returning();
|
||||||
|
if (!updated) throw new NotFoundException('Contract not found');
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HttpCode(204) @Post(':id/archive')
|
||||||
|
async archive(@CurrentSession() session: AuthenticatedSession, @Param('id', ParseUUIDPipe) id: string) {
|
||||||
|
await db.update(contracts).set({ deletedAt: new Date() })
|
||||||
|
.where(and(eq(contracts.id, id), eq(contracts.tenantId, session.tenantId)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue