import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards, } from '@nestjs/common'; import { CommandBus, QueryBus } from '@nestjs/cqrs'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiParam, } from '@nestjs/swagger'; import { type JwtPayload, CurrentUser, JwtAuthGuard, RolesGuard, Roles } from '@modules/auth'; import { CreateLeadCommand } from '../../application/commands/create-lead/create-lead.command'; import { type CreateLeadResult } from '../../application/commands/create-lead/create-lead.handler'; import { DeleteLeadCommand } from '../../application/commands/delete-lead/delete-lead.command'; import { UpdateLeadStatusCommand } from '../../application/commands/update-lead-status/update-lead-status.command'; import { GetLeadStatsQuery } from '../../application/queries/get-lead-stats/get-lead-stats.query'; import { GetLeadsByAgentQuery } from '../../application/queries/get-leads-by-agent/get-leads-by-agent.query'; import { type LeadReadDto } from '../../domain/repositories/lead-read.dto'; import { type LeadStatsData, type PaginatedResult } from '../../domain/repositories/lead.repository'; import { CreateLeadDto } from '../dto/create-lead.dto'; import { ListLeadsDto } from '../dto/list-leads.dto'; import { UpdateLeadStatusDto } from '../dto/update-lead-status.dto'; @ApiTags('leads') @ApiBearerAuth('JWT') @Controller('leads') @UseGuards(JwtAuthGuard, RolesGuard) @Roles('AGENT') export class LeadsController { constructor( private readonly commandBus: CommandBus, private readonly queryBus: QueryBus, ) {} @ApiOperation({ summary: 'Tạo lead mới' }) @ApiResponse({ status: 201, description: 'Lead đã được tạo thành công' }) @ApiResponse({ status: 400, description: 'Lỗi validation' }) @ApiResponse({ status: 401, description: 'Chưa xác thực' }) @ApiResponse({ status: 403, description: 'Không có quyền' }) @Post() async createLead( @Body() dto: CreateLeadDto, @CurrentUser() user: JwtPayload, ): Promise { return this.commandBus.execute( new CreateLeadCommand( user.sub, dto.name, dto.phone, dto.email ?? null, dto.source, dto.score ?? null, dto.notes ?? null, ), ); } @ApiOperation({ summary: 'Danh sách lead của agent' }) @ApiResponse({ status: 200, description: 'Danh sách lead phân trang' }) @Get() async getLeads( @Query() dto: ListLeadsDto, @CurrentUser() user: JwtPayload, ): Promise> { return this.queryBus.execute( new GetLeadsByAgentQuery( user.sub, dto.status ?? null, dto.page ?? 1, dto.limit ?? 20, ), ); } @ApiOperation({ summary: 'Thống kê lead của agent' }) @ApiResponse({ status: 200, description: 'Thống kê lead' }) @Get('stats') async getStats( @CurrentUser() user: JwtPayload, ): Promise { return this.queryBus.execute( new GetLeadStatsQuery(user.sub), ); } @ApiOperation({ summary: 'Cập nhật trạng thái lead' }) @ApiParam({ name: 'id', description: 'Lead ID' }) @ApiResponse({ status: 200, description: 'Trạng thái đã được cập nhật' }) @ApiResponse({ status: 400, description: 'Chuyển trạng thái không hợp lệ' }) @ApiResponse({ status: 403, description: 'Không có quyền' }) @ApiResponse({ status: 404, description: 'Không tìm thấy lead' }) @Patch(':id/status') async updateStatus( @Param('id') id: string, @Body() dto: UpdateLeadStatusDto, @CurrentUser() user: JwtPayload, ): Promise<{ updated: boolean }> { await this.commandBus.execute( new UpdateLeadStatusCommand(id, user.sub, dto.status), ); return { updated: true }; } @ApiOperation({ summary: 'Xóa lead' }) @ApiParam({ name: 'id', description: 'Lead ID' }) @ApiResponse({ status: 200, description: 'Lead đã được xóa' }) @ApiResponse({ status: 403, description: 'Không có quyền' }) @ApiResponse({ status: 404, description: 'Không tìm thấy lead' }) @Delete(':id') async deleteLead( @Param('id') id: string, @CurrentUser() user: JwtPayload, ): Promise<{ deleted: boolean }> { await this.commandBus.execute(new DeleteLeadCommand(id, user.sub)); return { deleted: true }; } }