diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-17 09:02:32 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-17 09:02:32 +0000 |
| commit | 7a1524ba54f43d0f2a19e4bca2c6a2e0b01c5ef1 (patch) | |
| tree | daa214d404c7fc78b32419a028724e5671a6c7a4 /lib/b-rfq/validations.ts | |
| parent | fa6a6093014c5d60188edfc9c4552e81c4b97bd1 (diff) | |
(대표님) 20250617 18시 작업사항
Diffstat (limited to 'lib/b-rfq/validations.ts')
| -rw-r--r-- | lib/b-rfq/validations.ts | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/lib/b-rfq/validations.ts b/lib/b-rfq/validations.ts index 15cc9425..f9473656 100644 --- a/lib/b-rfq/validations.ts +++ b/lib/b-rfq/validations.ts @@ -7,6 +7,7 @@ import { createSearchParamsCache, import * as z from "zod" import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" +import { VendorAttachmentResponse } from "@/db/schema"; export const searchParamsRFQDashboardCache = createSearchParamsCache({ // 공통 플래그 @@ -265,3 +266,141 @@ export const searchParamsInitialRfqDetailCache = createSearchParamsCache({ export type GetInitialRfqDetailSchema = Awaited<ReturnType<typeof searchParamsInitialRfqDetailCache.parse>>; + +export const updateInitialRfqSchema = z.object({ + initialRfqStatus: z.enum(["DRAFT", "Init. RFQ Sent", "S/L Decline", "Init. RFQ Answered"]), + dueDate: z.date({ + required_error: "마감일을 선택해주세요.", + }), + validDate: z.date().optional(), + incotermsCode: z.string().max(20, "Incoterms 코드는 20자 이하여야 합니다.").optional(), + classification: z.string().max(255, "분류는 255자 이하여야 합니다.").optional(), + sparepart: z.string().max(255, "예비부품은 255자 이하여야 합니다.").optional(), + shortList: z.boolean().default(false), + returnYn: z.boolean().default(false), + cpRequestYn: z.boolean().default(false), + prjectGtcYn: z.boolean().default(false), + rfqRevision: z.number().int().min(0, "RFQ 리비전은 0 이상이어야 합니다.").default(0), +}) + +export const removeInitialRfqsSchema = z.object({ + ids: z.array(z.number()).min(1, "최소 하나의 항목을 선택해주세요."), +}) + +export type UpdateInitialRfqSchema = z.infer<typeof updateInitialRfqSchema> +export type RemoveInitialRfqsSchema = z.infer<typeof removeInitialRfqsSchema> + +// 벌크 이메일 발송 스키마 +export const bulkEmailSchema = z.object({ + initialRfqIds: z.array(z.number()).min(1, "최소 하나의 초기 RFQ를 선택해주세요."), + language: z.enum(["en", "ko"]).default("en"), +}) + +export type BulkEmailInput = z.infer<typeof bulkEmailSchema> + +// 검색 파라미터 캐시 설정 + +export type ResponseStatus = "NOT_RESPONDED" | "RESPONDED" | "REVISION_REQUESTED" | "WAIVED"; +export type RfqType = "INITIAL" | "FINAL"; + + +export type VendorRfqResponseColumns = { + id: string; + vendorId: number; + rfqRecordId: number; + rfqType: RfqType; + overallStatus: ResponseStatus; + totalAttachments: number; + respondedCount: number; + pendingCount: number; + responseRate: number; + completionRate: number; + requestedAt: Date; + lastRespondedAt: Date | null; +}; + +// 검색 파라미터 캐시 설정 +export const searchParamsVendorResponseCache = createSearchParamsCache({ + flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), + page: parseAsInteger.withDefault(1), + perPage: parseAsInteger.withDefault(10), + sort: getSortingStateParser<VendorRfqResponseColumns>().withDefault([ + { id: "requestedAt", desc: true }, + ]), + + // 고급 필터 + filters: getFiltersStateParser().withDefault([]), + joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), + + // 기본 필터 + basicFilters: getFiltersStateParser().withDefault([]), + basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), + + // 검색 및 필터 + search: parseAsString.withDefault(""), + rfqType: parseAsStringEnum(["INITIAL", "FINAL", "ALL"]).withDefault("ALL"), + responseStatus: parseAsStringEnum(["NOT_RESPONDED", "RESPONDED", "REVISION_REQUESTED", "WAIVED", "ALL"]).withDefault("ALL"), + + // 날짜 범위 + from: parseAsString.withDefault(""), + to: parseAsString.withDefault(""), +}); + +export type GetVendorResponsesSchema = Awaited<ReturnType<typeof searchParamsVendorResponseCache.parse>>; + +// vendorId + rfqRecordId로 그룹핑된 응답 요약 타입 +export type VendorRfqResponseSummary = { + id: string; // vendorId + rfqRecordId + rfqType 조합으로 생성된 고유 ID + vendorId: number; + rfqRecordId: number; + rfqType: RfqType; + + // RFQ 정보 + rfq: { + id: number; + rfqCode: string | null; + description: string | null; + status: string; + dueDate: Date; + } | null; + + // 벤더 정보 + vendor: { + id: number; + vendorCode: string; + vendorName: string; + country: string | null; + businessSize: string | null; + } | null; + + // 응답 통계 + totalAttachments: number; + respondedCount: number; + pendingCount: number; + revisionRequestedCount: number; + waivedCount: number; + responseRate: number; + completionRate: number; + overallStatus: ResponseStatus; // 전체적인 상태 + + // 날짜 정보 + requestedAt: Date; + lastRespondedAt: Date | null; + + // 기타 + hasComments: boolean; +}; + + +// 수정 요청 스키마 +export const requestRevisionSchema = z.object({ + responseId: z.number().positive(), + revisionReason: z.string().min(10, "수정 요청 사유를 최소 10자 이상 입력해주세요").max(500), +}); + +// 수정 요청 결과 타입 +export type RequestRevisionResult = { + success: boolean; + message: string; + error?: string; +};
\ No newline at end of file |
