feat(CC-061): add PATCH /ai-requests/:id/status and status filter on list endpoint
This commit is contained in:
parent
fe1bdbbbe0
commit
c5d256ea78
1 changed files with 37 additions and 2 deletions
|
|
@ -1,20 +1,30 @@
|
||||||
import { Controller, Get, NotFoundException, Param, ParseUUIDPipe, Query } from '@nestjs/common';
|
import { Body, Controller, Get, IsString, NotFoundException, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||||
import { and, desc, eq, sum, count } from 'drizzle-orm';
|
import { and, desc, eq, sum, count } from 'drizzle-orm';
|
||||||
|
import { IsIn, IsOptional } from 'class-validator';
|
||||||
import { CurrentSession } from '../auth/session.decorator';
|
import { CurrentSession } from '../auth/session.decorator';
|
||||||
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
import type { AuthenticatedSession } from '../auth/tenant.guard';
|
||||||
import { db } from '../db/client';
|
import { db } from '../db/client';
|
||||||
import { aiRequests } from '../db/schema';
|
import { aiRequests } from '../db/schema';
|
||||||
|
|
||||||
|
class UpdateAiRequestStatusDto {
|
||||||
|
@IsIn(['completed', 'cancelled']) resultStatus!: 'completed' | 'cancelled';
|
||||||
|
@IsOptional() @IsString() rejectionReason?: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Controller('ai-requests')
|
@Controller('ai-requests')
|
||||||
export class AiRequestsController {
|
export class AiRequestsController {
|
||||||
@Get()
|
@Get()
|
||||||
async list(
|
async list(
|
||||||
@CurrentSession() session: AuthenticatedSession,
|
@CurrentSession() session: AuthenticatedSession,
|
||||||
@Query('limit') limitStr?: string,
|
@Query('limit') limitStr?: string,
|
||||||
|
@Query('status') status?: string,
|
||||||
) {
|
) {
|
||||||
const limit = Math.min(Math.max(1, parseInt(limitStr ?? '200', 10) || 200), 500);
|
const limit = Math.min(Math.max(1, parseInt(limitStr ?? '200', 10) || 200), 500);
|
||||||
|
const where = status
|
||||||
|
? and(eq(aiRequests.tenantId, session.tenantId), eq(aiRequests.resultStatus, status))
|
||||||
|
: eq(aiRequests.tenantId, session.tenantId);
|
||||||
return db.query.aiRequests.findMany({
|
return db.query.aiRequests.findMany({
|
||||||
where: eq(aiRequests.tenantId, session.tenantId),
|
where,
|
||||||
orderBy: desc(aiRequests.createdAt),
|
orderBy: desc(aiRequests.createdAt),
|
||||||
limit,
|
limit,
|
||||||
columns: {
|
columns: {
|
||||||
|
|
@ -86,4 +96,29 @@ export class AiRequestsController {
|
||||||
}
|
}
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Patch(':id/status')
|
||||||
|
async updateStatus(
|
||||||
|
@CurrentSession() session: AuthenticatedSession,
|
||||||
|
@Param('id', ParseUUIDPipe) id: string,
|
||||||
|
@Body() dto: UpdateAiRequestStatusDto,
|
||||||
|
) {
|
||||||
|
const record = await db.query.aiRequests.findFirst({
|
||||||
|
where: and(
|
||||||
|
eq(aiRequests.id, id),
|
||||||
|
eq(aiRequests.tenantId, session.tenantId),
|
||||||
|
),
|
||||||
|
columns: { id: true, resultStatus: true },
|
||||||
|
});
|
||||||
|
if (!record) throw new NotFoundException('AI request not found');
|
||||||
|
if (record.resultStatus !== 'pending') {
|
||||||
|
return { updated: false, reason: 'request is not pending' };
|
||||||
|
}
|
||||||
|
const [updated] = await db
|
||||||
|
.update(aiRequests)
|
||||||
|
.set({ resultStatus: dto.resultStatus, completedAt: new Date() })
|
||||||
|
.where(eq(aiRequests.id, id))
|
||||||
|
.returning({ id: aiRequests.id, resultStatus: aiRequests.resultStatus, completedAt: aiRequests.completedAt });
|
||||||
|
return { updated: true, record: updated };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue