diff --git a/src/modules/document-import/document-import.controller.ts b/src/modules/document-import/document-import.controller.ts index a62ed52..053d683 100644 --- a/src/modules/document-import/document-import.controller.ts +++ b/src/modules/document-import/document-import.controller.ts @@ -1,20 +1,33 @@ -import { Controller, Get, Post, Param, HttpCode, HttpStatus, Body } from '@nestjs/common'; +import { Controller, Get, Post, Param, HttpCode, HttpStatus, Body, BadRequestException } from '@nestjs/common'; import { ApiTags, ApiOperation } from '@nestjs/swagger'; import { DocumentImportService } from './document-import.service'; import { CreateImportDto } from './dto/create-import.dto'; +import { QuotaGuardService } from '../membership/quota-guard.service'; import { CurrentUser } from '../../common/decorators/current-user.decorator'; import type { UserPayload } from '../../common/types'; @ApiTags('document-import') @Controller('imports') export class DocumentImportController { - constructor(private readonly service: DocumentImportService) {} + constructor( + private readonly service: DocumentImportService, + private readonly quotaGuard: QuotaGuardService, + ) {} @Post() @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: '创建导入任务' }) async createImport(@CurrentUser() user: UserPayload, @Body() dto: CreateImportDto) { - return this.service.createImport({ ...dto, userId: user.id }); + const userId = user.id; + // M-MEMBER-01-CLOSE-01D: OCR/Vision 预检——导入创建时检查可用额度 + // 实际逐页计量由 RAG Worker 侧完成 + const opId = `import:${userId}:${Date.now()}`; + const ocrCheck = await this.quotaGuard.check(userId, 'ocr_pages', `${opId}:ocr`, 0); + const visionCheck = await this.quotaGuard.check(userId, 'vision_pages', `${opId}:vision`, 0); + if (!ocrCheck.allowed || !visionCheck.allowed) { + throw new BadRequestException({ errorCode: 'QUOTA_EXCEEDED', message: 'OCR/Vision quota exceeded', quotaType: !ocrCheck.allowed ? 'ocr_pages' : 'vision_pages', limit: !ocrCheck.allowed ? ocrCheck.limit : visionCheck.limit, used: !ocrCheck.allowed ? ocrCheck.used : visionCheck.used, remaining: 0, upgradeAvailable: true }); + } + return this.service.createImport({ ...dto, userId }); } @Get(':id/status') diff --git a/src/modules/document-import/document-import.module.ts b/src/modules/document-import/document-import.module.ts index d9b48e7..d2d1bbf 100644 --- a/src/modules/document-import/document-import.module.ts +++ b/src/modules/document-import/document-import.module.ts @@ -4,8 +4,10 @@ import { AdminImportsController } from './admin-imports.controller'; import { DocumentImportService } from './document-import.service'; import { DocumentImportRepository } from './document-import.repository'; import { PrismaService } from '../../infrastructure/database/prisma.service'; +import { MembershipModule } from '../membership/membership.module'; @Module({ + imports: [MembershipModule], controllers: [DocumentImportController, AdminImportsController], providers: [DocumentImportService, DocumentImportRepository, PrismaService], exports: [DocumentImportService, DocumentImportRepository],