251223:1649 On going update to 1.7.0: Refoctory drawing Module & document number Module
Some checks failed
Spec Validation / validate-markdown (push) Has been cancelled
Spec Validation / validate-diagrams (push) Has been cancelled
Spec Validation / check-todos (push) Has been cancelled

This commit is contained in:
admin
2025-12-23 16:49:16 +07:00
parent 0d6432ab83
commit 7db6a003db
81 changed files with 4703 additions and 1449 deletions

View File

@@ -1,6 +1,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { correspondenceService } from '../correspondence.service';
import apiClient from '@/lib/api/client';
import { WorkflowActionDto } from '@/types/dto/correspondence/workflow-action.dto';
// apiClient is already mocked in vitest.setup.ts
@@ -12,7 +13,7 @@ describe('correspondenceService', () => {
describe('getAll', () => {
it('should call GET /correspondences with params', async () => {
const mockResponse = {
data: [{ id: 1, title: 'Test' }],
data: [{ id: 1, subject: 'Test' }],
meta: { total: 1 },
};
vi.mocked(apiClient.get).mockResolvedValue({ data: mockResponse });
@@ -39,7 +40,7 @@ describe('correspondenceService', () => {
describe('getById', () => {
it('should call GET /correspondences/:id', async () => {
const mockData = { id: 1, title: 'Test' };
const mockData = { id: 1, subject: 'Test' };
// Service expects response.data.data (NestJS interceptor wrapper)
vi.mocked(apiClient.get).mockResolvedValue({ data: { data: mockData } });
@@ -62,9 +63,9 @@ describe('correspondenceService', () => {
describe('create', () => {
it('should call POST /correspondences with data', async () => {
const createDto = {
title: 'New Correspondence',
subject: 'New Correspondence',
projectId: 1,
correspondenceTypeId: 1,
typeId: 1,
};
const mockResponse = { id: 1, ...createDto };
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
@@ -78,8 +79,8 @@ describe('correspondenceService', () => {
describe('update', () => {
it('should call PUT /correspondences/:id with data', async () => {
const updateData = { title: 'Updated Title' };
const mockResponse = { id: 1, title: 'Updated Title' };
const updateData = { subject: 'Updated Title' };
const mockResponse = { id: 1, subject: 'Updated Title' };
vi.mocked(apiClient.put).mockResolvedValue({ data: mockResponse });
const result = await correspondenceService.update(1, updateData);
@@ -102,7 +103,7 @@ describe('correspondenceService', () => {
describe('submit', () => {
it('should call POST /correspondences/:id/submit', async () => {
const submitDto = { recipientIds: [2, 3] };
const submitDto = { note: 'Ready for review' };
const mockResponse = { id: 1, status: 'submitted' };
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
@@ -115,7 +116,7 @@ describe('correspondenceService', () => {
describe('processWorkflow', () => {
it('should call POST /correspondences/:id/workflow', async () => {
const workflowDto = { action: 'approve', comment: 'LGTM' };
const workflowDto: WorkflowActionDto = { action: 'APPROVE', comments: 'LGTM' };
const mockResponse = { id: 1, status: 'approved' };
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
@@ -128,7 +129,7 @@ describe('correspondenceService', () => {
describe('addReference', () => {
it('should call POST /correspondences/:id/references', async () => {
const referenceDto = { referencedDocumentId: 2, referenceType: 'reply_to' };
const referenceDto = { targetId: 2, referenceType: 'reply_to' };
const mockResponse = { id: 1 };
vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });
@@ -144,7 +145,7 @@ describe('correspondenceService', () => {
describe('removeReference', () => {
it('should call DELETE /correspondences/:id/references with body', async () => {
const referenceDto = { referencedDocumentId: 2 };
const referenceDto = { targetId: 2 };
vi.mocked(apiClient.delete).mockResolvedValue({ data: {} });
const result = await correspondenceService.removeReference(1, referenceDto);

View File

@@ -0,0 +1,41 @@
// File: lib/services/asbuilt-drawing.service.ts
import apiClient from "@/lib/api/client";
import {
CreateAsBuiltDrawingDto,
CreateAsBuiltDrawingRevisionDto,
SearchAsBuiltDrawingDto
} from "@/types/dto/drawing/asbuilt-drawing.dto";
export const asBuiltDrawingService = {
/**
* Get As Built Drawings list
*/
getAll: async (params: SearchAsBuiltDrawingDto) => {
const response = await apiClient.get("/drawings/asbuilt", { params });
return response.data;
},
/**
* Get details by ID
*/
getById: async (id: string | number) => {
const response = await apiClient.get(`/drawings/asbuilt/${id}`);
return response.data;
},
/**
* Create New As Built Drawing
*/
create: async (data: CreateAsBuiltDrawingDto | FormData) => {
const response = await apiClient.post("/drawings/asbuilt", data);
return response.data;
},
/**
* Create New Revision
*/
createRevision: async (id: string | number, data: CreateAsBuiltDrawingRevisionDto) => {
const response = await apiClient.post(`/drawings/asbuilt/${id}/revisions`, data);
return response.data;
}
};

View File

@@ -27,7 +27,7 @@ export const contractDrawingService = {
/**
* สร้างแบบสัญญาใหม่
*/
create: async (data: CreateContractDrawingDto) => {
create: async (data: CreateContractDrawingDto | FormData) => {
const response = await apiClient.post("/drawings/contract", data);
return response.data;
},

View File

@@ -0,0 +1,46 @@
import apiClient from "@/lib/api/client";
import {
NumberingMetrics,
ManualOverrideDto,
VoidReplaceDto,
CancelNumberDto,
AuditQueryParams
} from "@/types/dto/numbering.dto";
export const documentNumberingService = {
// --- Admin Dashboard Metrics ---
getMetrics: async (): Promise<NumberingMetrics> => {
const response = await apiClient.get("/admin/document-numbering/metrics");
return response.data;
},
// --- Admin Tools ---
manualOverride: async (dto: ManualOverrideDto): Promise<void> => {
await apiClient.post("/admin/document-numbering/manual-override", dto);
},
voidAndReplace: async (dto: VoidReplaceDto): Promise<any> => {
const response = await apiClient.post("/admin/document-numbering/void-and-replace", dto);
return response.data;
},
cancelNumber: async (dto: CancelNumberDto): Promise<void> => {
await apiClient.post("/admin/document-numbering/cancel", dto);
},
bulkImport: async (data: FormData | any[]): Promise<any> => {
const isFormData = data instanceof FormData;
const config = isFormData ? { headers: { "Content-Type": "multipart/form-data" } } : {};
const response = await apiClient.post("/admin/document-numbering/bulk-import", data, config);
return response.data;
},
// --- Audit Logs ---
getAuditLogs: async (params?: AuditQueryParams) => {
// NOTE: endpoint might be merged with metrics or separate
// Currently controller has getMetrics returning audit logs too.
// But if we want separate pagination later:
// return apiClient.get("/admin/document-numbering/audit", { params });
return [];
}
};

View File

@@ -191,5 +191,24 @@ export const masterDataService = {
params: { projectId, correspondenceTypeId: typeId }
});
return response.data;
},
// --- Drawing Categories ---
getContractDrawingCategories: async () => {
const response = await apiClient.get("/drawings/contract/categories");
return response.data.data || response.data;
},
getShopMainCategories: async (projectId: number) => {
const response = await apiClient.get("/drawings/shop/main-categories", { params: { projectId } });
return response.data.data || response.data;
},
getShopSubCategories: async (projectId: number, mainCategoryId?: number) => {
const response = await apiClient.get("/drawings/shop/sub-categories", {
params: { projectId, mainCategoryId }
});
return response.data.data || response.data;
}
};

View File

@@ -26,7 +26,7 @@ export const shopDrawingService = {
/**
* สร้าง Shop Drawing ใหม่ (พร้อม Revision 0)
*/
create: async (data: CreateShopDrawingDto) => {
create: async (data: CreateShopDrawingDto | FormData) => {
const response = await apiClient.post("/drawings/shop", data);
return response.data;
},