690409:0953 Done Task-BE-AI-02
CI / CD Pipeline / build (push) Successful in 4m30s
CI / CD Pipeline / deploy (push) Successful in 1m6s

This commit is contained in:
2026-04-09 09:53:57 +07:00
parent 4f34aeae6b
commit 99c8d61856
18 changed files with 1791 additions and 60 deletions
@@ -0,0 +1,87 @@
// File: src/modules/ai/dto/ai-callback.dto.ts
// DTO สำหรับ Callback จาก n8n หลังจาก AI ประมวลผลเสร็จ (ADR-018 AI Communication Contract)
import {
IsUUID,
IsString,
IsNumber,
IsOptional,
IsEnum,
Min,
Max,
MaxLength,
IsObject,
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { AiAuditStatus } from '../entities/ai-audit-log.entity';
// Metadata ที่ AI สกัดได้จากเอกสาร
export interface AiExtractedMetadata {
subject?: string;
date?: string; // รูปแบบ YYYY-MM-DD
discipline?: string; // Civil|Mechanical|Electrical|Architectural
drawingReference?: string;
contractNumber?: string;
documentType?: string;
discrepancies?: string[]; // รายการที่ไม่สอดคล้องกัน
[key: string]: unknown;
}
export class AiCallbackDto {
// UUID ของ MigrationLog ที่เกี่ยวข้อง (ADR-019)
@ApiProperty({ description: 'publicId ของ MigrationLog (UUID)' })
@IsUUID()
migrationLogPublicId!: string;
// ชื่อ AI Model ที่ใช้ประมวลผล
@ApiProperty({ description: 'ชื่อ AI Model เช่น gemma4, paddleocr' })
@IsString()
@MaxLength(50)
aiModel!: string;
// สถานะการประมวลผล
@ApiProperty({ enum: AiAuditStatus })
@IsEnum(AiAuditStatus)
status!: AiAuditStatus;
// คะแนนความมั่นใจ (0.00-1.00)
@ApiPropertyOptional({ minimum: 0, maximum: 1 })
@IsOptional()
@IsNumber()
@Min(0)
@Max(1)
confidenceScore?: number;
// Metadata ที่ AI สกัดได้
@ApiPropertyOptional()
@IsOptional()
@IsObject()
extractedMetadata?: AiExtractedMetadata;
// เวลาประมวลผล (milliseconds)
@ApiPropertyOptional()
@IsOptional()
@IsNumber()
@Min(0)
processingTimeMs?: number;
// SHA-256 hash ของ Input เพื่อ Audit
@ApiPropertyOptional()
@IsOptional()
@IsString()
@MaxLength(64)
inputHash?: string;
// SHA-256 hash ของ Output เพื่อ Audit
@ApiPropertyOptional()
@IsOptional()
@IsString()
@MaxLength(64)
outputHash?: string;
// ข้อความ Error (ถ้า status เป็น FAILED หรือ TIMEOUT)
@ApiPropertyOptional()
@IsOptional()
@IsString()
errorMessage?: string;
}
@@ -0,0 +1,33 @@
// File: src/modules/ai/dto/extract-document.dto.ts
// DTO สำหรับ Real-time AI Extraction endpoint (/api/ai/extract)
import { IsUUID, IsEnum, IsOptional, IsString } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
// บริบทการใช้งาน AI Extraction
export type ExtractionContext = 'migration' | 'ingestion';
export class ExtractDocumentDto {
// UUID ของไฟล์ที่ต้องการ Extract (ADR-019: ใช้ publicId เท่านั้น)
@ApiProperty({ description: 'UUID ของไฟล์ที่ต้องการให้ AI สกัด Metadata' })
@IsUUID()
publicId!: string;
// บริบทการใช้งาน: migration=นำเข้าเอกสารเก่า, ingestion=อัปโหลดเอกสารใหม่
@ApiProperty({
enum: ['migration', 'ingestion'],
description: 'บริบทการใช้งาน AI',
})
@IsEnum(['migration', 'ingestion'])
context!: ExtractionContext;
// ประเภทไฟล์ (optional — ใช้เพื่อ optimization)
@ApiPropertyOptional({
enum: ['pdf', 'docx', 'xlsx'],
description: 'ประเภทไฟล์ (optional)',
})
@IsOptional()
@IsString()
@IsEnum(['pdf', 'docx', 'xlsx'])
fileType?: string;
}
@@ -0,0 +1,41 @@
// File: src/modules/ai/dto/migration-query.dto.ts
// DTO สำหรับ Query Parameters ของ GET /api/ai/migration
import { IsOptional, IsEnum, IsNumber, Min, Max } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { MigrationLogStatus } from '../entities/migration-log.entity';
export class MigrationQueryDto {
// กรองตามสถานะ
@ApiPropertyOptional({ enum: MigrationLogStatus })
@IsOptional()
@IsEnum(MigrationLogStatus)
status?: MigrationLogStatus;
// กรองตาม Confidence Score ขั้นต่ำ
@ApiPropertyOptional({ minimum: 0, maximum: 1 })
@IsOptional()
@IsNumber()
@Min(0)
@Max(1)
@Type(() => Number)
minConfidence?: number;
// หน้าที่ต้องการ (เริ่มที่ 1)
@ApiPropertyOptional({ minimum: 1, default: 1 })
@IsOptional()
@IsNumber()
@Min(1)
@Type(() => Number)
page?: number = 1;
// จำนวนรายการต่อหน้า (สูงสุด 100)
@ApiPropertyOptional({ minimum: 1, maximum: 100, default: 10 })
@IsOptional()
@IsNumber()
@Min(1)
@Max(100)
@Type(() => Number)
limit?: number = 10;
}
@@ -0,0 +1,27 @@
// File: src/modules/ai/dto/migration-update.dto.ts
// DTO สำหรับ Admin อัปเดตสถานะ MigrationLog หลังตรวจสอบ
import { IsOptional, IsEnum, IsString, MaxLength } from 'class-validator';
import { ApiPropertyOptional } from '@nestjs/swagger';
import { MigrationLogStatus } from '../entities/migration-log.entity';
export class MigrationUpdateDto {
// สถานะใหม่ที่ต้องการเปลี่ยน (VERIFIED หรือ FAILED เท่านั้น)
@ApiPropertyOptional({
enum: [MigrationLogStatus.VERIFIED, MigrationLogStatus.FAILED],
description: 'สถานะใหม่ (Admin สามารถเปลี่ยนได้เฉพาะ VERIFIED หรือ FAILED)',
})
@IsOptional()
@IsEnum([MigrationLogStatus.VERIFIED, MigrationLogStatus.FAILED])
status?: MigrationLogStatus;
// ความเห็นของ Admin
@ApiPropertyOptional({
maxLength: 1000,
description: 'ความเห็นจาก Admin ผู้ตรวจสอบ',
})
@IsOptional()
@IsString()
@MaxLength(1000)
adminFeedback?: string;
}