690328:1106 Fixing Refactor uuid by Kimi #01
CI / CD Pipeline / build (push) Successful in 5m11s
CI / CD Pipeline / deploy (push) Failing after 4m28s

This commit is contained in:
2026-03-28 11:06:25 +07:00
parent 76b18e7c37
commit da8579d21b
24 changed files with 606 additions and 182 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
{
"npm.packageManager": "pnpm"
"npm.packageManager": "pnpm",
"editor.fontSize": 16
}
+27 -32
View File
@@ -20,7 +20,7 @@ import { useProjects } from '@/hooks/use-projects';
import { CreateRfaDto } from '@/types/dto/rfa/rfa.dto';
import { useState, useEffect, type FormEvent } from 'react';
import { correspondenceService } from '@/lib/services/correspondence.service';
import { Contract, getContractPublicId } from '@/types/contract';
import { Contract } from '@/types/contract';
const rfaSchema = z.object({
projectId: z.string().min(1, 'Project is required'), // ADR-019: UUID
@@ -41,16 +41,12 @@ type RFAFormData = z.infer<typeof rfaSchema>;
type ProjectOption = {
publicId?: string;
uuid?: string; // Legacy alias for publicId
id?: number;
projectName?: string;
projectCode?: string;
};
type ContractOption = {
publicId?: string;
uuid?: string;
id?: string;
contractName?: string;
name?: string;
contractCode?: string;
@@ -78,20 +74,19 @@ type CorrespondenceTypeOption = {
};
type OrganizationOption = {
uuid?: string;
id?: number;
publicId?: string;
organizationCode?: string;
organizationName?: string;
};
type SelectableDrawingOption = {
uuid?: string;
publicId?: string;
drawingNumber?: string;
title?: string;
legacyDrawingNumber?: string;
currentRevisionUuid?: string;
currentRevisionPublicId?: string;
currentRevision?: {
uuid?: string;
publicId?: string;
revisionLabel?: string;
revisionNumber?: number | string;
title?: string;
@@ -145,11 +140,11 @@ export function RFAForm() {
const createMutation = useCreateRFA();
const { data: projectsData, isLoading: isLoadingProjects } = useProjects();
const projects = dedupeByKey(extractArrayData<ProjectOption>(projectsData), (project) => project.publicId ?? project.uuid ?? project.id);
const projects = dedupeByKey(extractArrayData<ProjectOption>(projectsData), (project) => project.publicId);
const { data: organizationsData, isLoading: isLoadingOrganizations } = useOrganizations({ isActive: true });
const organizations = dedupeByKey(
extractArrayData<OrganizationOption>(organizationsData),
(organization) => organization.uuid ?? organization.id
(organization) => organization.publicId
);
const { data: correspondenceTypesData } = useCorrespondenceTypes();
const correspondenceTypes = extractArrayData<CorrespondenceTypeOption>(correspondenceTypesData);
@@ -185,7 +180,7 @@ export function RFAForm() {
const { data: contractsData, isLoading: isLoadingContracts } = useContracts(selectedProjectId);
const contracts = dedupeByKey(
extractArrayData<ContractOption & Contract>(contractsData),
(contract) => contract.publicId ?? contract.uuid ?? contract.id
(contract) => contract.publicId
);
const selectedContractId = watch('contractId');
@@ -196,27 +191,27 @@ export function RFAForm() {
const [shopDrawingSearch, setShopDrawingSearch] = useState('');
const [shopDrawingPage, setShopDrawingPage] = useState(1);
const { data: shopDrawingsData, isLoading: isLoadingShopDrawings } = useDrawings('SHOP', {
projectUuid: selectedProjectId || '',
projectPublicId: selectedProjectId || '',
search: shopDrawingSearch,
page: shopDrawingPage,
limit: 10,
});
const shopDrawings = dedupeByKey(
extractArrayData<SelectableDrawingOption>(shopDrawingsData),
(drawing) => drawing.currentRevisionUuid ?? drawing.currentRevision?.uuid ?? drawing.uuid
(drawing) => drawing.currentRevisionPublicId ?? drawing.currentRevision?.publicId ?? drawing.publicId
);
const [asBuiltDrawingSearch, setAsBuiltDrawingSearch] = useState('');
const [asBuiltDrawingPage, setAsBuiltDrawingPage] = useState(1);
const { data: asBuiltDrawingsData, isLoading: isLoadingAsBuiltDrawings } = useDrawings('AS_BUILT', {
projectUuid: selectedProjectId || '',
projectPublicId: selectedProjectId || '',
search: asBuiltDrawingSearch,
page: asBuiltDrawingPage,
limit: 10,
});
const asBuiltDrawings = dedupeByKey(
extractArrayData<SelectableDrawingOption>(asBuiltDrawingsData),
(drawing) => drawing.currentRevisionUuid ?? drawing.currentRevision?.uuid ?? drawing.uuid
(drawing) => drawing.currentRevisionPublicId ?? drawing.currentRevision?.publicId ?? drawing.publicId
);
const selectedDisciplineId = watch('disciplineId');
@@ -381,7 +376,7 @@ export function RFAForm() {
</SelectTrigger>
<SelectContent>
{projects.map((p) => {
const projectValue = getOptionValue(p.publicId ?? p.uuid ?? p.id);
const projectValue = getOptionValue(p.publicId);
if (!projectValue) {
return null;
@@ -417,7 +412,7 @@ export function RFAForm() {
</SelectTrigger>
<SelectContent>
{contracts.map((c) => {
const contractValue = getOptionValue(getContractPublicId(c) || c.uuid);
const contractValue = getOptionValue(c.publicId);
if (!contractValue) {
return null;
@@ -499,7 +494,7 @@ export function RFAForm() {
</SelectTrigger>
<SelectContent>
{organizations.map((organization) => {
const organizationValue = getOptionValue(organization.uuid ?? organization.id);
const organizationValue = getOptionValue(organization.publicId);
if (!organizationValue) {
return null;
@@ -551,24 +546,24 @@ export function RFAForm() {
)}
<div className="grid grid-cols-1 gap-3">
{shopDrawings.map((drawing) => {
const revisionUuid = drawing.currentRevisionUuid ?? drawing.currentRevision?.uuid;
const revisionPublicId = drawing.currentRevisionPublicId ?? drawing.currentRevision?.publicId;
if (!revisionUuid) {
if (!revisionPublicId) {
return null;
}
return (
<label
key={revisionUuid}
key={revisionPublicId}
className="flex items-start gap-3 rounded-lg border p-3 cursor-pointer hover:bg-muted/50 transition-colors"
>
<Checkbox
checked={selectedShopDrawingRevisionIds.includes(revisionUuid)}
checked={selectedShopDrawingRevisionIds.includes(revisionPublicId)}
onCheckedChange={(checked) => {
const nextValues =
checked === true
? [...selectedShopDrawingRevisionIds, revisionUuid]
: selectedShopDrawingRevisionIds.filter((value) => value !== revisionUuid);
? [...selectedShopDrawingRevisionIds, revisionPublicId]
: selectedShopDrawingRevisionIds.filter((value) => value !== revisionPublicId);
setValue('shopDrawingRevisionIds', nextValues, { shouldDirty: true, shouldValidate: true });
clearErrors('shopDrawingRevisionIds');
}}
@@ -647,24 +642,24 @@ export function RFAForm() {
)}
<div className="grid grid-cols-1 gap-3">
{asBuiltDrawings.map((drawing) => {
const revisionUuid = drawing.currentRevisionUuid ?? drawing.currentRevision?.uuid;
const revisionPublicId = drawing.currentRevisionPublicId ?? drawing.currentRevision?.publicId;
if (!revisionUuid) {
if (!revisionPublicId) {
return null;
}
return (
<label
key={revisionUuid}
key={revisionPublicId}
className="flex items-start gap-3 rounded-lg border p-3 cursor-pointer hover:bg-muted/50 transition-colors"
>
<Checkbox
checked={selectedAsBuiltDrawingRevisionIds.includes(revisionUuid)}
checked={selectedAsBuiltDrawingRevisionIds.includes(revisionPublicId)}
onCheckedChange={(checked) => {
const nextValues =
checked === true
? [...selectedAsBuiltDrawingRevisionIds, revisionUuid]
: selectedAsBuiltDrawingRevisionIds.filter((value) => value !== revisionUuid);
? [...selectedAsBuiltDrawingRevisionIds, revisionPublicId]
: selectedAsBuiltDrawingRevisionIds.filter((value) => value !== revisionPublicId);
setValue('asBuiltDrawingRevisionIds', nextValues, {
shouldDirty: true,
shouldValidate: true,
-9
View File
@@ -1,13 +1,11 @@
export interface ContractProjectReference {
publicId?: string;
id?: string;
projectCode: string;
projectName: string;
}
export interface Contract {
publicId?: string;
id?: string;
contractCode: string;
contractName: string;
projectId?: number | string;
@@ -16,10 +14,3 @@ export interface Contract {
endDate?: string;
project?: ContractProjectReference;
}
export const getContractPublicId = (contract?: Pick<Contract, 'publicId' | 'id'>): string =>
String(contract?.publicId ?? contract?.id ?? '');
export const getProjectPublicId = (
project?: Pick<ContractProjectReference, 'publicId' | 'id'>
): string => String(project?.publicId ?? project?.id ?? '');
+7 -12
View File
@@ -1,13 +1,11 @@
export interface Organization {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
organizationName: string;
organizationCode: string;
}
export interface Attachment {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
name: string;
url: string;
size?: number;
@@ -17,8 +15,7 @@ export interface Attachment {
// Used in List View mainly
export interface CorrespondenceRevision {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
revisionNumber: number;
revisionLabel?: string; // e.g. "A", "00"
subject: string;
@@ -42,22 +39,20 @@ export interface CorrespondenceRevision {
// Nested Relation from Backend Refactor
correspondence: {
publicId: string;
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
correspondenceNumber: string;
projectId: number;
originatorId?: number;
isInternal: boolean;
originator?: Organization;
project?: { publicId: string; id?: number; projectName: string; projectCode: string };
project?: { publicId: string; projectName: string; projectCode: string };
type?: { id: number; typeName: string; typeCode: string };
};
}
// Keep explicit Correspondence for Detail View if needed, or merge concepts
export interface Correspondence {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
correspondenceNumber: string;
projectId: number;
originatorId?: number;
@@ -67,7 +62,7 @@ export interface Correspondence {
// Relations
originator?: Organization;
project?: { publicId: string; id?: number; projectName: string; projectCode: string };
project?: { publicId: string; projectName: string; projectCode: string };
type?: { id: number; typeName: string; typeCode: string };
revisions?: CorrespondenceRevision[]; // Nested revisions
recipients?: {
+5 -10
View File
@@ -1,7 +1,6 @@
// Entity Interfaces
export interface DrawingRevision {
publicId: string; // ADR-019: exposed as 'id' in API responses
revisionId?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
revisionNumber: string;
title?: string; // Added
legacyDrawingNumber?: string; // Added
@@ -15,8 +14,7 @@ export interface DrawingRevision {
}
export interface ContractDrawing {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
contractDrawingNo: string;
title: string;
projectId: number;
@@ -28,8 +26,7 @@ export interface ContractDrawing {
}
export interface ShopDrawing {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
drawingNumber: string;
projectId: number;
mainCategoryId: number;
@@ -41,8 +38,7 @@ export interface ShopDrawing {
}
export interface AsBuiltDrawing {
publicId: string; // ADR-019: exposed as 'id' in API responses
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
drawingNumber: string;
projectId: number;
mainCategoryId: number;
@@ -54,8 +50,7 @@ export interface AsBuiltDrawing {
// Unified Type for List
export interface Drawing {
publicId?: string; // ADR-019: exposed as 'id' in API responses
drawingId?: number; // Excluded from API responses (ADR-019)
publicId?: string; // ADR-019: public identifier
drawingNumber: string;
title: string; // Display title (from current revision for Shop/AsBuilt)
discipline?: string | { disciplineCode: string; disciplineName: string };
-2
View File
@@ -17,7 +17,6 @@ export interface Discipline {
codeNameTh?: string;
isActive: boolean;
contract?: {
id?: number;
publicId?: string;
contractCode: string;
contractName: string;
@@ -33,7 +32,6 @@ export interface RfaType {
remark?: string;
isActive: boolean;
contract?: {
id?: number;
publicId?: string;
contractCode: string;
contractName: string;
+2 -4
View File
@@ -28,8 +28,7 @@ export interface RFAItem {
}
export interface RFA {
publicId: string; // ADR-019: from correspondence.publicId
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier (from correspondence.publicId)
rfaTypeId: number;
createdBy: number;
disciplineId?: number;
@@ -56,8 +55,7 @@ export interface RFA {
};
// Shared Correspondence Relation
correspondence?: {
publicId: string;
id?: number; // Excluded from API responses (ADR-019)
publicId: string; // ADR-019: public identifier
correspondenceNumber: string;
projectId: number;
originatorId?: number;