690320:2126 UUID agian by Claude Sonnet #02
Build and Deploy / deploy (push) Failing after 4m27s
Build and Deploy / deploy (push) Failing after 4m27s
This commit is contained in:
@@ -85,6 +85,7 @@ export class UserService {
|
|||||||
.leftJoinAndSelect('user.preference', 'preference') // Optional
|
.leftJoinAndSelect('user.preference', 'preference') // Optional
|
||||||
.leftJoinAndSelect('user.assignments', 'assignments')
|
.leftJoinAndSelect('user.assignments', 'assignments')
|
||||||
.leftJoinAndSelect('assignments.role', 'role')
|
.leftJoinAndSelect('assignments.role', 'role')
|
||||||
|
.leftJoin('user.organization', 'organization') // ADR-019: expose uuid, not INT
|
||||||
.select([
|
.select([
|
||||||
'user.user_id',
|
'user.user_id',
|
||||||
'user.uuid',
|
'user.uuid',
|
||||||
@@ -93,13 +94,15 @@ export class UserService {
|
|||||||
'user.firstName',
|
'user.firstName',
|
||||||
'user.lastName',
|
'user.lastName',
|
||||||
'user.lineId',
|
'user.lineId',
|
||||||
'user.primaryOrganizationId',
|
|
||||||
'user.isActive',
|
'user.isActive',
|
||||||
'user.createdAt',
|
'user.createdAt',
|
||||||
'user.updatedAt',
|
'user.updatedAt',
|
||||||
'assignments.id',
|
'assignments.id',
|
||||||
'role.roleId',
|
'role.roleId',
|
||||||
'role.roleName',
|
'role.roleName',
|
||||||
|
'organization.uuid',
|
||||||
|
'organization.organizationCode',
|
||||||
|
'organization.organizationName',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Apply Filters
|
// Apply Filters
|
||||||
@@ -165,6 +168,7 @@ export class UserService {
|
|||||||
'assignments',
|
'assignments',
|
||||||
'assignments.role',
|
'assignments.role',
|
||||||
'assignments.role.permissions',
|
'assignments.role.permissions',
|
||||||
|
'organization', // ADR-019: expose org.uuid, not INT primaryOrganizationId
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -92,11 +92,7 @@ export default function UsersPage() {
|
|||||||
{
|
{
|
||||||
id: "organization",
|
id: "organization",
|
||||||
header: "Organization",
|
header: "Organization",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => row.original.organization?.organizationCode ?? "-",
|
||||||
const orgId = row.original.primaryOrganizationId;
|
|
||||||
const org = (organizations as Organization[]).find((o) => (o.id ?? o.uuid) === orgId?.toString() || o.uuid === orgId?.toString());
|
|
||||||
return org ? org.organizationCode : "-";
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "roles",
|
id: "roles",
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ import { SearchContractDto, CreateContractDto, UpdateContractDto } from "@/types
|
|||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
|
|
||||||
interface Project {
|
interface Project {
|
||||||
id: string; // ADR-019: uuid exposed as 'id'
|
uuid: string;
|
||||||
|
id?: number;
|
||||||
projectCode: string;
|
projectCode: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
}
|
}
|
||||||
@@ -82,14 +83,14 @@ const contractSchema = z.object({
|
|||||||
type ContractFormData = z.infer<typeof contractSchema>;
|
type ContractFormData = z.infer<typeof contractSchema>;
|
||||||
|
|
||||||
const useContracts = (params?: SearchContractDto) => {
|
const useContracts = (params?: SearchContractDto) => {
|
||||||
return useQuery({
|
return useQuery<Contract[]>({
|
||||||
queryKey: ['contracts', params],
|
queryKey: ['contracts', params],
|
||||||
queryFn: () => contractService.getAll(params),
|
queryFn: () => contractService.getAll(params),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const useProjectsList = () => {
|
const useProjectsList = () => {
|
||||||
return useQuery({
|
return useQuery<Project[]>({
|
||||||
queryKey: ['projects-list'],
|
queryKey: ['projects-list'],
|
||||||
queryFn: () => projectService.getAll(),
|
queryFn: () => projectService.getAll(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export function UserDialog({ open, onOpenChange, user }: UserDialogProps) {
|
|||||||
lastName: user.lastName,
|
lastName: user.lastName,
|
||||||
isActive: user.isActive,
|
isActive: user.isActive,
|
||||||
lineId: user.lineId || "",
|
lineId: user.lineId || "",
|
||||||
primaryOrganizationId: user.primaryOrganizationId?.toString(),
|
primaryOrganizationId: user.organization?.uuid ?? undefined,
|
||||||
roleIds: user.roles?.map((r: { roleId: number }) => r.roleId) || [],
|
roleIds: user.roles?.map((r: { roleId: number }) => r.roleId) || [],
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: ""
|
confirmPassword: ""
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ import { FileUploadZone } from "@/components/custom/file-upload-zone";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { useCreateCorrespondence, useUpdateCorrespondence } from "@/hooks/use-correspondence";
|
import { useCreateCorrespondence, useUpdateCorrespondence } from "@/hooks/use-correspondence";
|
||||||
import { Organization } from "@/types/organization";
|
import { Organization, Correspondence, CorrespondenceRevision } from "@/types/correspondence";
|
||||||
import { useOrganizations, useProjects, useCorrespondenceTypes, useDisciplines } from "@/hooks/use-master-data";
|
import { useOrganizations, useProjects, useCorrespondenceTypes, useDisciplines } from "@/hooks/use-master-data";
|
||||||
import { CreateCorrespondenceDto } from "@/types/dto/correspondence/create-correspondence.dto";
|
import { CreateCorrespondenceDto } from "@/types/dto/correspondence/create-correspondence.dto";
|
||||||
|
import type { ProjectListItem } from "@/lib/services/project.service";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { correspondenceService } from "@/lib/services/correspondence.service";
|
import { correspondenceService } from "@/lib/services/correspondence.service";
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ const correspondenceSchema = z.object({
|
|||||||
|
|
||||||
type FormData = z.infer<typeof correspondenceSchema>;
|
type FormData = z.infer<typeof correspondenceSchema>;
|
||||||
|
|
||||||
export function CorrespondenceForm({ initialData, uuid }: { initialData?: any, uuid?: string }) {
|
export function CorrespondenceForm({ initialData, uuid }: { initialData?: Correspondence, uuid?: string }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const createMutation = useCreateCorrespondence();
|
const createMutation = useCreateCorrespondence();
|
||||||
const updateMutation = useUpdateCorrespondence();
|
const updateMutation = useUpdateCorrespondence();
|
||||||
@@ -53,23 +54,20 @@ export function CorrespondenceForm({ initialData, uuid }: { initialData?: any, u
|
|||||||
const { data: correspondenceTypes, isLoading: isLoadingTypes } = useCorrespondenceTypes();
|
const { data: correspondenceTypes, isLoading: isLoadingTypes } = useCorrespondenceTypes();
|
||||||
const { data: disciplines, isLoading: isLoadingDisciplines } = useDisciplines();
|
const { data: disciplines, isLoading: isLoadingDisciplines } = useDisciplines();
|
||||||
|
|
||||||
// Extract initial values if editing
|
// Extract initial values if editing — ADR-019: use nested relation UUIDs, never raw INT FK columns
|
||||||
const currentRev = initialData?.revisions?.find((r: any) => r.isCurrent) || initialData?.revisions?.[0];
|
const currentRev = initialData?.revisions?.find((r: CorrespondenceRevision) => r.isCurrent) ?? initialData?.revisions?.[0];
|
||||||
const defaultValues: Partial<FormData> = {
|
const defaultValues: Partial<FormData> = {
|
||||||
projectId: initialData?.projectId ? String(initialData.projectId) : undefined,
|
projectId: initialData?.project?.uuid ?? undefined,
|
||||||
documentTypeId: initialData?.correspondenceTypeId || undefined,
|
documentTypeId: initialData?.correspondenceTypeId || undefined,
|
||||||
disciplineId: initialData?.disciplineId || undefined,
|
disciplineId: initialData?.disciplineId || undefined,
|
||||||
subject: currentRev?.subject || currentRev?.title || "",
|
subject: currentRev?.subject || "",
|
||||||
description: currentRev?.description || "",
|
description: currentRev?.description || "",
|
||||||
body: currentRev?.body || "",
|
body: currentRev?.body || "",
|
||||||
remarks: currentRev?.remarks || "",
|
remarks: currentRev?.remarks || "",
|
||||||
dueDate: currentRev?.dueDate ? new Date(currentRev.dueDate).toISOString().split('T')[0] : undefined,
|
dueDate: currentRev?.dueDate ? new Date(currentRev.dueDate).toISOString().split('T')[0] : undefined,
|
||||||
fromOrganizationId: initialData?.originatorId ? String(initialData.originatorId) : undefined,
|
fromOrganizationId: initialData?.originator?.uuid ?? undefined,
|
||||||
// Map initial recipient (TO) - Simplified for now
|
toOrganizationId: initialData?.recipients?.find(r => r.recipientType === 'TO')?.recipientOrganization?.uuid ?? undefined,
|
||||||
toOrganizationId: initialData?.recipients?.find((r: any) => r.recipientType === 'TO')?.recipientOrganizationId
|
importance: (currentRev?.details?.['importance'] as "NORMAL" | "HIGH" | "URGENT") ?? "NORMAL",
|
||||||
? String(initialData.recipients.find((r: any) => r.recipientType === 'TO').recipientOrganizationId)
|
|
||||||
: undefined,
|
|
||||||
importance: currentRev?.details?.importance || "NORMAL",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -219,8 +217,8 @@ export function CorrespondenceForm({ initialData, uuid }: { initialData?: any, u
|
|||||||
<SelectValue placeholder={isLoadingProjects ? "Loading..." : "Select Project"} />
|
<SelectValue placeholder={isLoadingProjects ? "Loading..." : "Select Project"} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(projects || []).map((p: any) => (
|
{(projects || []).map((p: ProjectListItem) => (
|
||||||
<SelectItem key={p.id} value={String(p.id)}>
|
<SelectItem key={p.uuid} value={p.uuid}>
|
||||||
{p.projectName} ({p.projectCode})
|
{p.projectName} ({p.projectCode})
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
@@ -243,7 +241,7 @@ export function CorrespondenceForm({ initialData, uuid }: { initialData?: any, u
|
|||||||
<SelectValue placeholder={isLoadingTypes ? "Loading..." : "Select Type"} />
|
<SelectValue placeholder={isLoadingTypes ? "Loading..." : "Select Type"} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(correspondenceTypes || []).map((t: any) => (
|
{(correspondenceTypes || []).map((t: { id: number; typeName: string; typeCode: string }) => (
|
||||||
<SelectItem key={t.id} value={String(t.id)}>
|
<SelectItem key={t.id} value={String(t.id)}>
|
||||||
{t.typeName} ({t.typeCode})
|
{t.typeName} ({t.typeCode})
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
@@ -267,7 +265,7 @@ export function CorrespondenceForm({ initialData, uuid }: { initialData?: any, u
|
|||||||
<SelectValue placeholder={isLoadingDisciplines ? "Loading..." : "Select Discipline (Optional)"} />
|
<SelectValue placeholder={isLoadingDisciplines ? "Loading..." : "Select Discipline (Optional)"} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{(disciplines || []).map((d: any) => (
|
{(disciplines || []).map((d: { id: number; disciplineCode?: string; codeNameEn?: string }) => (
|
||||||
<SelectItem key={d.id} value={String(d.id)}>
|
<SelectItem key={d.id} value={String(d.id)}>
|
||||||
{d.codeNameEn || d.disciplineCode}
|
{d.codeNameEn || d.disciplineCode}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
UpdateOrganizationDto,
|
UpdateOrganizationDto,
|
||||||
SearchOrganizationDto,
|
SearchOrganizationDto,
|
||||||
} from '@/types/dto/organization/organization.dto';
|
} from '@/types/dto/organization/organization.dto';
|
||||||
|
import { Organization } from '@/types/organization';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { organizationService } from '@/lib/services/organization.service';
|
import { organizationService } from '@/lib/services/organization.service';
|
||||||
import { projectService } from '@/lib/services/project.service';
|
import { projectService } from '@/lib/services/project.service';
|
||||||
@@ -19,7 +20,7 @@ export const masterDataKeys = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function useOrganizations(params?: SearchOrganizationDto) {
|
export function useOrganizations(params?: SearchOrganizationDto) {
|
||||||
return useQuery({
|
return useQuery<Organization[]>({
|
||||||
queryKey: [...masterDataKeys.organizations(), params],
|
queryKey: [...masterDataKeys.organizations(), params],
|
||||||
queryFn: () => organizationService.getAll(params),
|
queryFn: () => organizationService.getAll(params),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { projectService } from '@/lib/services/project.service';
|
import { projectService } from '@/lib/services/project.service';
|
||||||
|
import type { ProjectListItem } from '@/lib/services/project.service';
|
||||||
import { CreateProjectDto, UpdateProjectDto, SearchProjectDto } from '@/types/dto/project/project.dto';
|
import { CreateProjectDto, UpdateProjectDto, SearchProjectDto } from '@/types/dto/project/project.dto';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getApiErrorMessage } from '@/types/api-error';
|
import { getApiErrorMessage } from '@/types/api-error';
|
||||||
@@ -11,7 +12,7 @@ export const projectKeys = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function useProjects(params?: SearchProjectDto) {
|
export function useProjects(params?: SearchProjectDto) {
|
||||||
return useQuery({
|
return useQuery<ProjectListItem[]>({
|
||||||
queryKey: projectKeys.list(params || {}),
|
queryKey: projectKeys.list(params || {}),
|
||||||
queryFn: () => projectService.getAll(params),
|
queryFn: () => projectService.getAll(params),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
UpdateOrganizationDto,
|
UpdateOrganizationDto,
|
||||||
SearchOrganizationDto,
|
SearchOrganizationDto,
|
||||||
} from "@/types/dto/organization/organization.dto";
|
} from "@/types/dto/organization/organization.dto";
|
||||||
|
import { Organization } from "@/types/organization";
|
||||||
|
|
||||||
type ApiEnvelope<T> = {
|
type ApiEnvelope<T> = {
|
||||||
data?: ApiEnvelope<T> | T;
|
data?: ApiEnvelope<T> | T;
|
||||||
@@ -36,8 +37,11 @@ export const organizationService = {
|
|||||||
* Get all organizations (supports filtering by projectId)
|
* Get all organizations (supports filtering by projectId)
|
||||||
* GET /organizations?projectId=1
|
* GET /organizations?projectId=1
|
||||||
*/
|
*/
|
||||||
getAll: async (params?: SearchOrganizationDto) => {
|
getAll: async (params?: SearchOrganizationDto): Promise<Organization[]> => {
|
||||||
const response = await apiClient.get("/organizations", { params });
|
const response = await apiClient.get<ApiEnvelope<Organization[]> | Organization[]>(
|
||||||
|
"/organizations",
|
||||||
|
{ params }
|
||||||
|
);
|
||||||
return unwrapArrayResponse(response.data);
|
return unwrapArrayResponse(response.data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ import {
|
|||||||
SearchProjectDto
|
SearchProjectDto
|
||||||
} from "@/types/dto/project/project.dto";
|
} from "@/types/dto/project/project.dto";
|
||||||
|
|
||||||
|
export interface ProjectListItem {
|
||||||
|
uuid: string;
|
||||||
|
id?: number;
|
||||||
|
projectCode: string;
|
||||||
|
projectName: string;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
type ApiEnvelope<T> = {
|
type ApiEnvelope<T> = {
|
||||||
data?: ApiEnvelope<T> | T;
|
data?: ApiEnvelope<T> | T;
|
||||||
message?: string;
|
message?: string;
|
||||||
@@ -39,9 +49,11 @@ export const projectService = {
|
|||||||
* ดึงรายการโครงการทั้งหมด (รองรับ Search & Pagination)
|
* ดึงรายการโครงการทั้งหมด (รองรับ Search & Pagination)
|
||||||
* (เดิมคือ getAllProjects แต่ปรับให้รับ params ได้)
|
* (เดิมคือ getAllProjects แต่ปรับให้รับ params ได้)
|
||||||
*/
|
*/
|
||||||
getAll: async (params?: SearchProjectDto) => {
|
getAll: async (params?: SearchProjectDto): Promise<ProjectListItem[]> => {
|
||||||
// GET /projects
|
// GET /projects
|
||||||
const response = await apiClient.get("/projects", { params });
|
const response = await apiClient.get<
|
||||||
|
ApiEnvelope<ProjectListItem[]> | ProjectListItem[]
|
||||||
|
>("/projects", { params });
|
||||||
return unwrapArrayResponse(response.data);
|
return unwrapArrayResponse(response.data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -89,10 +89,10 @@ export interface CirculationListResponse {
|
|||||||
* DTO for creating a circulation
|
* DTO for creating a circulation
|
||||||
*/
|
*/
|
||||||
export interface CreateCirculationDto {
|
export interface CreateCirculationDto {
|
||||||
correspondenceId: number | string;
|
correspondenceId: string; // ADR-019: UUID string only
|
||||||
projectId?: number | string;
|
projectId?: string; // ADR-019: UUID string only
|
||||||
subject: string;
|
subject: string;
|
||||||
assigneeIds: (number | string)[];
|
assigneeIds: string[]; // ADR-019: UUID string only
|
||||||
remarks?: string;
|
remarks?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export interface Correspondence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateCorrespondenceDto {
|
export interface CreateCorrespondenceDto {
|
||||||
projectId: number;
|
projectId: string; // ADR-019: UUID string only
|
||||||
typeId: number;
|
typeId: number;
|
||||||
subTypeId?: number;
|
subTypeId?: number;
|
||||||
disciplineId?: number;
|
disciplineId?: number;
|
||||||
@@ -87,7 +87,7 @@ export interface CreateCorrespondenceDto {
|
|||||||
description?: string;
|
description?: string;
|
||||||
details?: Record<string, unknown>;
|
details?: Record<string, unknown>;
|
||||||
isInternal?: boolean;
|
isInternal?: boolean;
|
||||||
originatorId?: number;
|
originatorId?: string; // ADR-019: UUID string only
|
||||||
recipients?: { organizationId: number; type: 'TO' | 'CC' }[];
|
recipients?: { organizationId: string; type: 'TO' | 'CC' }[]; // ADR-019: UUID string only
|
||||||
attachments?: File[];
|
attachments?: File[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
// File: src/types/dto/circulation/create-circulation.dto.ts
|
// File: src/types/dto/circulation/create-circulation.dto.ts
|
||||||
|
|
||||||
export interface CreateCirculationDto {
|
export interface CreateCirculationDto {
|
||||||
/** เอกสารต้นเรื่องที่จะเวียน (Correspondence ID or UUID) */
|
/** UUID ของเอกสารต้นเรื่องที่จะเวียน (ADR-019: UUID string only) */
|
||||||
correspondenceId: number | string;
|
correspondenceId: string;
|
||||||
|
|
||||||
/** หัวข้อเรื่อง (Subject) */
|
/** หัวข้อเรื่อง (Subject) */
|
||||||
subject: string;
|
subject: string;
|
||||||
|
|
||||||
/** รายชื่อ User ID/UUID ที่ต้องการส่งให้ (ผู้รับผิดชอบ) */
|
/** UUID ของ User ที่ต้องการส่งให้ (ADR-019: UUID string only) */
|
||||||
assigneeIds: (number | string)[];
|
assigneeIds: string[];
|
||||||
|
|
||||||
/** หมายเหตุเพิ่มเติม (ถ้ามี) */
|
/** หมายเหตุเพิ่มเติม (ถ้ามี) */
|
||||||
remarks?: string;
|
remarks?: string;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export interface CreateContractDto {
|
export interface CreateContractDto {
|
||||||
contractCode: string;
|
contractCode: string;
|
||||||
contractName: string;
|
contractName: string;
|
||||||
projectId: number | string;
|
projectId: string; // ADR-019: UUID string only
|
||||||
description?: string;
|
description?: string;
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
@@ -11,7 +11,7 @@ export type UpdateContractDto = Partial<CreateContractDto>;
|
|||||||
|
|
||||||
export interface SearchContractDto {
|
export interface SearchContractDto {
|
||||||
search?: string;
|
search?: string;
|
||||||
projectId?: number | string;
|
projectId?: string; // ADR-019: UUID string only
|
||||||
page?: number;
|
page?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// File: src/types/dto/correspondence/create-correspondence.dto.ts
|
// File: src/types/dto/correspondence/create-correspondence.dto.ts
|
||||||
|
|
||||||
export interface CreateCorrespondenceDto {
|
export interface CreateCorrespondenceDto {
|
||||||
/** ID or UUID ของโครงการ */
|
/** UUID ของโครงการ (ADR-019: UUID string only) */
|
||||||
projectId: number | string;
|
projectId: string;
|
||||||
|
|
||||||
/** ID ของประเภทเอกสาร (เช่น RFA, LETTER) */
|
/** ID ของประเภทเอกสาร (เช่น RFA, LETTER) */
|
||||||
typeId: number;
|
typeId: number;
|
||||||
@@ -34,11 +34,11 @@ export interface CreateCorrespondenceDto {
|
|||||||
/** เอกสารภายในหรือไม่ (True = ภายใน) */
|
/** เอกสารภายในหรือไม่ (True = ภายใน) */
|
||||||
isInternal?: boolean;
|
isInternal?: boolean;
|
||||||
|
|
||||||
/** * ✅ Field สำหรับ Impersonation (เลือกองค์กรผู้ส่ง)
|
/** ✅ Field สำหรับ Impersonation (เลือกองค์กรผู้ส่ง)
|
||||||
* ใช้กรณี Admin สร้างเอกสารแทนผู้อื่น
|
* ใช้กรณี Admin สร้างเอกสารแทนผู้อื่น (ADR-019: UUID string only)
|
||||||
*/
|
*/
|
||||||
originatorId?: number | string;
|
originatorId?: string;
|
||||||
|
|
||||||
/** รายชื่อผู้รับ */
|
/** รายชื่อผู้รับ (ADR-019: UUID string only) */
|
||||||
recipients?: { organizationId: number | string; type: 'TO' | 'CC' }[];
|
recipients?: { organizationId: string; type: 'TO' | 'CC' }[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import type { RFAItem } from '@/types/rfa';
|
|||||||
|
|
||||||
// --- Create ---
|
// --- Create ---
|
||||||
export interface CreateRfaDto {
|
export interface CreateRfaDto {
|
||||||
/** ID or UUID ของโครงการ */
|
/** UUID ของโครงการ (ADR-019: UUID string only) */
|
||||||
projectId: number | string; // ADR-019: Accept UUID
|
projectId: string;
|
||||||
|
|
||||||
/** ประเภท RFA (เช่น DWG, MAT) */
|
/** ประเภท RFA (เช่น DWG, MAT) */
|
||||||
rfaTypeId: number;
|
rfaTypeId: number;
|
||||||
@@ -24,8 +24,8 @@ export interface CreateRfaDto {
|
|||||||
/** Contract UUID (optional) */
|
/** Contract UUID (optional) */
|
||||||
contractId?: string; // ADR-019: Contract UUID
|
contractId?: string; // ADR-019: Contract UUID
|
||||||
|
|
||||||
/** ส่งถึงใคร (สำหรับ Routing Step 1) */
|
/** ส่งถึงใคร (สำหรับ Routing Step 1) (ADR-019: UUID string only) */
|
||||||
toOrganizationId: number | string; // ADR-019: Accept UUID
|
toOrganizationId: string;
|
||||||
|
|
||||||
/** รายละเอียดเพิ่มเติม */
|
/** รายละเอียดเพิ่มเติม */
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -48,8 +48,8 @@ export type UpdateRfaDto = Partial<CreateRfaDto>;
|
|||||||
|
|
||||||
// --- Search ---
|
// --- Search ---
|
||||||
export interface SearchRfaDto {
|
export interface SearchRfaDto {
|
||||||
/** Filter by Project ID or UUID (optional to allow cross-project search) */
|
/** Filter by Project UUID (ADR-019: UUID string only) */
|
||||||
projectId?: number | string; // ADR-019: Accept UUID
|
projectId?: string;
|
||||||
|
|
||||||
/** กรองตามประเภท RFA */
|
/** กรองตามประเภท RFA */
|
||||||
rfaTypeId?: number;
|
rfaTypeId?: number;
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ export enum TransmittalPurpose {
|
|||||||
|
|
||||||
// --- Create ---
|
// --- Create ---
|
||||||
export interface CreateTransmittalDto {
|
export interface CreateTransmittalDto {
|
||||||
projectId?: number | string; // ADR-019: Accept UUID
|
projectId?: string; // ADR-019: UUID string only
|
||||||
recipientOrganizationId?: number | string; // ADR-019: Accept UUID
|
recipientOrganizationId?: string; // ADR-019: UUID string only
|
||||||
subject: string;
|
subject: string;
|
||||||
purpose?: string;
|
purpose?: string;
|
||||||
remarks?: string;
|
remarks?: string;
|
||||||
correspondenceId: number | string; // ADR-019: Accept UUID
|
correspondenceId: string; // ADR-019: UUID string only
|
||||||
items: CreateTransmittalItemDto[];
|
items: CreateTransmittalItemDto[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export type UpdateTransmittalDto = Partial<CreateTransmittalDto>;
|
|||||||
// --- Search ---
|
// --- Search ---
|
||||||
export interface SearchTransmittalDto {
|
export interface SearchTransmittalDto {
|
||||||
/** บังคับระบุ Project */
|
/** บังคับระบุ Project */
|
||||||
projectId: number | string; // ADR-019: Accept UUID
|
projectId: string; // ADR-019: UUID string only
|
||||||
|
|
||||||
purpose?: TransmittalPurpose;
|
purpose?: TransmittalPurpose;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export interface CreateUserDto {
|
|||||||
firstName?: string;
|
firstName?: string;
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
lineId?: string;
|
lineId?: string;
|
||||||
primaryOrganizationId?: number | string; // ADR-019: Accept UUID
|
primaryOrganizationId?: string; // ADR-019: UUID string only
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ export interface RFA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateRFADto {
|
export interface CreateRFADto {
|
||||||
projectId: number | string; // ADR-019: Accept UUID
|
projectId: string; // ADR-019: UUID string only
|
||||||
contractId?: string; // ADR-019: Contract UUID
|
contractId?: string; // ADR-019: Contract UUID
|
||||||
toOrganizationId?: number | string; // ADR-019: Recipient org UUID
|
toOrganizationId?: string; // ADR-019: UUID string only
|
||||||
rfaTypeId: number;
|
rfaTypeId: number;
|
||||||
disciplineId?: number;
|
disciplineId?: number;
|
||||||
subject: string;
|
subject: string;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export interface TransmittalItem {
|
|||||||
export interface Transmittal {
|
export interface Transmittal {
|
||||||
uuid: string; // ADR-019: from correspondence.uuid
|
uuid: string; // ADR-019: from correspondence.uuid
|
||||||
id?: number; // Excluded from API responses (ADR-019)
|
id?: number; // Excluded from API responses (ADR-019)
|
||||||
correspondenceId?: number | string;
|
correspondenceId?: string; // ADR-019: UUID string only
|
||||||
transmittalNo: string;
|
transmittalNo: string;
|
||||||
subject: string;
|
subject: string;
|
||||||
purpose?: TransmittalPurpose;
|
purpose?: TransmittalPurpose;
|
||||||
@@ -74,9 +74,9 @@ export interface CreateTransmittalItemDto {
|
|||||||
* DTO for creating a transmittal
|
* DTO for creating a transmittal
|
||||||
*/
|
*/
|
||||||
export interface CreateTransmittalDto {
|
export interface CreateTransmittalDto {
|
||||||
projectId?: number | string; // ADR-019: Accept UUID
|
projectId?: string; // ADR-019: UUID string only
|
||||||
recipientOrganizationId?: number | string; // ADR-019: Accept UUID
|
recipientOrganizationId?: string; // ADR-019: UUID string only
|
||||||
correspondenceId: number | string; // ADR-019: Accept UUID
|
correspondenceId: string; // ADR-019: UUID string only
|
||||||
subject: string;
|
subject: string;
|
||||||
purpose?: TransmittalPurpose;
|
purpose?: TransmittalPurpose;
|
||||||
remarks?: string;
|
remarks?: string;
|
||||||
@@ -89,6 +89,6 @@ export interface CreateTransmittalDto {
|
|||||||
export interface SearchTransmittalDto {
|
export interface SearchTransmittalDto {
|
||||||
page?: number;
|
page?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
projectId?: number | string; // ADR-019: Accept UUID
|
projectId?: string; // ADR-019: UUID string only
|
||||||
search?: string;
|
search?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ export interface Role {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface UserOrganization {
|
export interface UserOrganization {
|
||||||
organizationId: number;
|
uuid: string; // ADR-019: Public identifier
|
||||||
orgCode: string;
|
organizationCode: string; // Matches backend Organization entity
|
||||||
orgName: string;
|
organizationName: string; // Matches backend Organization entity
|
||||||
orgNameTh?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
@@ -20,8 +19,8 @@ export interface User {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
lineId?: string;
|
lineId?: string;
|
||||||
primaryOrganizationId?: number | string; // ADR-019: May be INT or UUID
|
organization?: UserOrganization; // ADR-019: use organization.uuid — never expose INT id
|
||||||
organization?: UserOrganization;
|
|
||||||
roles?: Role[];
|
roles?: Role[];
|
||||||
|
|
||||||
// Security fields (from backend v1.5.1)
|
// Security fields (from backend v1.5.1)
|
||||||
@@ -42,7 +41,7 @@ export interface CreateUserDto {
|
|||||||
password?: string;
|
password?: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
lineId?: string;
|
lineId?: string;
|
||||||
primaryOrganizationId?: number | string; // ADR-019: Accept UUID
|
primaryOrganizationId?: string; // ADR-019: UUID string only
|
||||||
roleIds: number[];
|
roleIds: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,5 +52,5 @@ export interface SearchUserDto {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
search?: string;
|
search?: string;
|
||||||
roleId?: number;
|
roleId?: number;
|
||||||
primaryOrganizationId?: number | string; // ADR-019: Accept UUID
|
primaryOrganizationId?: string; // ADR-019: UUID string only
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user