import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards, Request, } from '@nestjs/common'; import { DepositsService } from './deposits.service'; import { NotificationsService } from '../notifications/notifications.service'; import { NotificationType } from '../entities/notification.entity'; import { CreateDepositDto, RefundDepositDto, CreateDepositWithInstallmentsDto } from './dto/deposit.dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { OperationLogsService } from '../operation-logs/operation-logs.service'; import { extractRequestInfo } from '../common/request-utils'; import { RequirePermission } from '../auth/decorators/permission.decorator'; @UseGuards(JwtAuthGuard) @Controller('deposits') export class DepositsController { constructor( private service: DepositsService, private logService: OperationLogsService, private readonly notificationsService: NotificationsService, ) {} @Get() @RequirePermission('deposit:view') findAll(@Query('studentId') studentId?: string, @Query('status') status?: string) { return this.service.findAll({ studentId: studentId ? +studentId : undefined, status: status || undefined, }); } @Get('pending-refunds') @RequirePermission('deposit:edit') findPendingRefunds() { return this.service.findPendingRefunds(); } @Get('stats') @RequirePermission('deposit:view') getStats() { return this.service.getStats(); } @Get(':id') @RequirePermission('deposit:view') findOne(@Param('id') id: string) { return this.service.findOne(+id); } @Post() @RequirePermission('deposit:create') async create(@Body() dto: CreateDepositDto | CreateDepositWithInstallmentsDto, @Request() req: any) { const { ipAddress, userAgent } = extractRequestInfo(req); const result = await this.service.create(dto, req.user?.id); await this.logService.log({ userId: req.user?.id, username: req.user?.username, module: '押金管理', action: '收取押金', targetId: result.id, targetType: 'deposit', detail: `学生${dto.studentId} ¥${dto.amount}`, ipAddress, userAgent, }); // TODO: Send notification for deposit_due — studentId→userId mapping unavailable return result; } @Post(':id/installments') @RequirePermission('deposit:edit') async addInstallment( @Param('id') id: string, @Body() body: { amount: number; dueDate: string }, ) { return this.service.addInstallment(+id, body.amount, body.dueDate); } @Put('installments/:installmentId') @RequirePermission('deposit:edit') async updateInstallment( @Param('installmentId') installmentId: string, @Body() body: { paidDate?: string; status?: string }, ) { return this.service.updateInstallment(+installmentId, body); } @Delete('installments/:installmentId') @RequirePermission('deposit:delete') async deleteInstallment(@Param('installmentId') installmentId: string) { return this.service.deleteInstallment(+installmentId); } @Put(':id/refund') @RequirePermission('deposit:edit') async refund(@Param('id') id: string, @Body() dto: RefundDepositDto, @Request() req: any) { const { ipAddress, userAgent } = extractRequestInfo(req); const result = await this.service.refund(+id, dto, req.user?.id); await this.logService.log({ userId: req.user?.id, username: req.user?.username, module: '押金管理', action: '退还押金', targetId: +id, targetType: 'deposit', detail: `退还¥${result.refundAmount}, 扣除¥${result.deductionAmount}`, ipAddress, userAgent, }); // TODO: Send notification for deposit_refunded — studentId→userId mapping unavailable return result; } @Post(':id/request-refund') @RequirePermission('deposit:edit') async requestRefund(@Param('id') id: string, @Request() req: any) { const { ipAddress, userAgent } = extractRequestInfo(req); const result = await this.service.requestRefund(+id); await this.logService.log({ userId: req.user?.id, username: req.user?.username, module: '押金管理', action: '申请退款', targetId: +id, targetType: 'deposit', detail: '提交退款申请', ipAddress, userAgent, }); return result; } @Put(':id/approve-refund') @RequirePermission('deposit:approve') async approveRefund(@Param('id') id: string, @Request() req: any) { const { ipAddress, userAgent } = extractRequestInfo(req); const result = await this.service.approveRefund(+id, req.user?.id); await this.logService.log({ userId: req.user?.id, username: req.user?.username, module: '押金管理', action: '审批退款', targetId: +id, targetType: 'deposit', detail: `审批通过 → ${result.refundStatus}`, ipAddress, userAgent, }); return result; } @Delete(':id') @RequirePermission('deposit:delete') async remove(@Param('id') id: string, @Request() req: any) { const { ipAddress, userAgent } = extractRequestInfo(req); const result = await this.service.remove(+id); await this.logService.log({ userId: req.user?.id, username: req.user?.username, module: '押金管理', action: '删除押金记录', targetId: +id, targetType: 'deposit', ipAddress, userAgent, }); return result; } }