260317:1200 Refactor to uploads
Build and Deploy / deploy (push) Successful in 5m48s

This commit is contained in:
admin
2026-03-17 12:00:26 +07:00
parent 2f0d67d8b2
commit 3abef2c745
9 changed files with 299 additions and 1069 deletions
@@ -19,6 +19,7 @@ import { JsonSchemaModule } from '../json-schema/json-schema.module';
import { UserModule } from '../user/user.module';
import { WorkflowEngineModule } from '../workflow-engine/workflow-engine.module';
import { SearchModule } from '../search/search.module';
import { FileStorageModule } from '../../common/file-storage/file-storage.module';
/**
* CorrespondenceModule
@@ -42,6 +43,7 @@ import { SearchModule } from '../search/search.module';
UserModule,
WorkflowEngineModule,
SearchModule,
FileStorageModule,
],
controllers: [CorrespondenceController],
providers: [CorrespondenceService, CorrespondenceWorkflowService],
@@ -14,6 +14,7 @@ import { JsonSchemaService } from '../json-schema/json-schema.service';
import { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';
import { UserService } from '../user/user.service';
import { SearchService } from '../search/search.service';
import { FileStorageService } from '../../common/file-storage/file-storage.service';
describe('CorrespondenceService', () => {
let service: CorrespondenceService;
@@ -118,6 +119,10 @@ describe('CorrespondenceService', () => {
provide: SearchService,
useValue: { indexDocument: jest.fn() },
},
{
provide: FileStorageService,
useValue: { commit: jest.fn().mockResolvedValue([]) },
},
],
}).compile();
@@ -34,6 +34,7 @@ import { JsonSchemaService } from '../json-schema/json-schema.service';
import { WorkflowEngineService } from '../workflow-engine/workflow-engine.service';
import { UserService } from '../user/user.service';
import { SearchService } from '../search/search.service';
import { FileStorageService } from '../../common/file-storage/file-storage.service';
/**
* CorrespondenceService - Document management (CRUD)
@@ -64,7 +65,8 @@ export class CorrespondenceService {
private workflowEngine: WorkflowEngineService,
private userService: UserService,
private dataSource: DataSource,
private searchService: SearchService
private searchService: SearchService,
private fileStorageService: FileStorageService
) {}
async create(createDto: CreateCorrespondenceDto, user: User) {
@@ -180,6 +182,12 @@ export class CorrespondenceService {
body: createDto.body,
remarks: createDto.remarks,
dueDate: createDto.dueDate ? new Date(createDto.dueDate) : undefined,
documentDate: createDto.documentDate
? new Date(createDto.documentDate)
: undefined,
issuedDate: createDto.issuedDate
? new Date(createDto.issuedDate)
: undefined,
description: createDto.description,
details: createDto.details,
createdBy: user.user_id,
@@ -199,6 +207,20 @@ export class CorrespondenceService {
await queryRunner.manager.save(recipients);
}
// Commit attachments from Temp → Permanent (Two-Phase Storage)
if (createDto.attachmentTempIds?.length) {
const issueDate = createDto.issuedDate
? new Date(createDto.issuedDate)
: createDto.documentDate
? new Date(createDto.documentDate)
: undefined;
await this.fileStorageService.commit(createDto.attachmentTempIds, {
issueDate,
documentType: 'Correspondence',
});
}
await queryRunner.commitTransaction();
// Start Workflow Instance (non-blocking)
@@ -457,6 +479,10 @@ export class CorrespondenceService {
if (updateDto.remarks) revisionUpdate.remarks = updateDto.remarks;
// Format Date correctly if string
if (updateDto.dueDate) revisionUpdate.dueDate = new Date(updateDto.dueDate);
if (updateDto.documentDate)
revisionUpdate.documentDate = new Date(updateDto.documentDate);
if (updateDto.issuedDate)
revisionUpdate.issuedDate = new Date(updateDto.issuedDate);
if (updateDto.description)
revisionUpdate.description = updateDto.description;
if (updateDto.details) revisionUpdate.details = updateDto.details;
@@ -465,6 +491,20 @@ export class CorrespondenceService {
await this.revisionRepo.update(revision.id, revisionUpdate);
}
// 4.5 Commit new attachments from Temp → Permanent (Two-Phase Storage)
if (updateDto.attachmentTempIds?.length) {
const issueDate = updateDto.issuedDate
? new Date(updateDto.issuedDate)
: updateDto.documentDate
? new Date(updateDto.documentDate)
: revision.issuedDate || revision.documentDate || undefined;
await this.fileStorageService.commit(updateDto.attachmentTempIds, {
issueDate: issueDate ? new Date(issueDate) : undefined,
documentType: 'Correspondence',
});
}
// 5. Update Recipients if provided
if (updateDto.recipients) {
const recipientRepo = this.dataSource.getRepository(
@@ -84,6 +84,30 @@ export class CreateCorrespondenceDto {
@IsOptional()
isInternal?: boolean;
@ApiPropertyOptional({
description: 'Document Date (วันที่เอกสาร)',
example: '2025-12-06',
})
@IsDateString()
@IsOptional()
documentDate?: string;
@ApiPropertyOptional({
description: 'Issued Date (วันที่ออกเอกสาร) — ใช้จัดเก็บไฟล์ตาม YYYY/MM',
example: '2025-12-06T00:00:00Z',
})
@IsDateString()
@IsOptional()
issuedDate?: string;
@ApiPropertyOptional({
description: 'Attachment temp IDs from upload phase (Two-Phase Storage)',
example: ['uuid-temp-1', 'uuid-temp-2'],
})
@IsArray()
@IsOptional()
attachmentTempIds?: string[];
// ✅ เพิ่ม Field สำหรับ Impersonation (เลือกองค์กรผู้ส่ง)
@ApiPropertyOptional({
description: 'Originator Organization ID (for impersonation)',