diff options
Diffstat (limited to 'lib/rfqs/validations.ts')
| -rw-r--r-- | lib/rfqs/validations.ts | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/lib/rfqs/validations.ts b/lib/rfqs/validations.ts deleted file mode 100644 index 8752f693..00000000 --- a/lib/rfqs/validations.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { createSearchParamsCache, - parseAsArrayOf, - parseAsInteger, - parseAsString, - parseAsStringEnum,parseAsBoolean -} from "nuqs/server" -import * as z from "zod" - -import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" -import { Rfq, rfqs, RfqsView, VendorCbeView, VendorResponseCBEView, VendorRfqViewBase, VendorTbeView } from "@/db/schema/rfq"; -import { Vendor, vendors } from "@/db/schema/vendors"; - -export const RfqType = { - PURCHASE_BUDGETARY: "PURCHASE_BUDGETARY", - PURCHASE: "PURCHASE", - BUDGETARY: "BUDGETARY" -} as const; - -export type RfqType = typeof RfqType[keyof typeof RfqType]; - -// ======================= -// 1) SearchParams (목록 필터링/정렬) -// ======================= -export const searchParamsCache = createSearchParamsCache({ - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - sort: getSortingStateParser<RfqsView>().withDefault([ - { id: "createdAt", desc: true }, - ]), - - // 간단 검색 필드 - rfqCode: parseAsString.withDefault(""), - projectCode: parseAsString.withDefault(""), - projectName: parseAsString.withDefault(""), - dueDate: parseAsString.withDefault(""), - - // 상태 - 여러 개일 수 있다고 가정 - status: parseAsArrayOf(z.enum(rfqs.status.enumValues)).withDefault([]), - - // 고급 필터 - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - search: parseAsString.withDefault(""), - rfqType: parseAsStringEnum(["PURCHASE", "BUDGETARY", "PURCHASE_BUDGETARY"]).withDefault("PURCHASE"), - -}); - -export type GetRfqsSchema = Awaited<ReturnType<typeof searchParamsCache.parse>>; - - -export const searchParamsMatchedVCache = createSearchParamsCache({ - // 1) 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 2) 페이지네이션 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 3) 정렬 (Rfq 테이블) - // getSortingStateParser<Rfq>() → Rfq 테이블의 컬럼명에 맞춘 유효성 검사 - sort: getSortingStateParser<VendorRfqViewBase>().withDefault([ - { id: "rfqVendorUpdated", desc: true }, - ]), - - // 4) 간단 검색 필드 - vendorName: parseAsString.withDefault(""), - vendorCode: parseAsString.withDefault(""), - country: parseAsString.withDefault(""), - email: parseAsString.withDefault(""), - website: parseAsString.withDefault(""), - - // 5) 상태 (배열) - Rfq["status"]는 "DRAFT"|"PUBLISHED"|"EVALUATION"|"AWARDED" - // rfqs.status.enumValues 로 가져온 문자열 배열을 z.enum([...])로 처리 - vendorStatus: parseAsArrayOf(z.enum(vendors.status.enumValues)).withDefault([]), - - // 6) 고급 필터 (nuqs - filterColumns) - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 7) 글로벌 검색어 - search: parseAsString.withDefault(""), -}) -export type GetMatchedVendorsSchema = Awaited<ReturnType<typeof searchParamsMatchedVCache.parse>>; - -export const searchParamsTBECache = createSearchParamsCache({ - // 1) 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 2) 페이지네이션 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 3) 정렬 (Rfq 테이블) - // getSortingStateParser<Rfq>() → Rfq 테이블의 컬럼명에 맞춘 유효성 검사 - sort: getSortingStateParser<VendorTbeView>().withDefault([ - { id: "tbeUpdated", desc: true }, - ]), - - // 4) 간단 검색 필드 - vendorName: parseAsString.withDefault(""), - vendorCode: parseAsString.withDefault(""), - country: parseAsString.withDefault(""), - email: parseAsString.withDefault(""), - website: parseAsString.withDefault(""), - - tbeResult: parseAsString.withDefault(""), - tbeNote: parseAsString.withDefault(""), - tbeUpdated: parseAsString.withDefault(""), - rfqType: parseAsStringEnum(["PURCHASE", "BUDGETARY", "PURCHASE_BUDGETARY"]).withDefault("PURCHASE"), - - // 5) 상태 (배열) - Rfq["status"]는 "DRAFT"|"PUBLISHED"|"EVALUATION"|"AWARDED" - // rfqs.status.enumValues 로 가져온 문자열 배열을 z.enum([...])로 처리 - vendorStatus: parseAsArrayOf(z.enum(vendors.status.enumValues)).withDefault([]), - - // 6) 고급 필터 (nuqs - filterColumns) - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 7) 글로벌 검색어 - search: parseAsString.withDefault(""), -}) -export type GetTBESchema = Awaited<ReturnType<typeof searchParamsTBECache.parse>>; - -// ======================= -// 2) Create RFQ Schema -// ======================= -export const createRfqSchema = z.object({ - rfqCode: z.string().min(3, "RFQ 코드는 최소 3글자 이상이어야 합니다"), - description: z.string().optional(), - projectId: z.number().nullable().optional(), // 프로젝트 ID (선택적) - bidProjectId: z.number().nullable().optional(), // 프로젝트 ID (선택적) - parentRfqId: z.number().nullable().optional(), // 부모 RFQ ID (선택적) - dueDate: z.date(), - status: z.enum(["DRAFT", "PUBLISHED", "EVALUATION", "AWARDED"]), - rfqType: z.enum([RfqType.PURCHASE, RfqType.BUDGETARY, RfqType.PURCHASE_BUDGETARY]).default(RfqType.PURCHASE), - createdBy: z.number(), -}); - -export type CreateRfqSchema = z.infer<typeof createRfqSchema>; - -export const createRfqItemSchema = z.object({ - rfqId: z.number().int().min(1, "Invalid RFQ ID"), - itemCode: z.string().min(1), - itemName: z.string().optional(), - description: z.string().optional(), - quantity: z.number().min(1).optional(), - uom: z.string().optional(), - rfqType: z.string().default("PURCHASE"), // rfqType 필드 추가 - -}); - -export type CreateRfqItemSchema = z.infer<typeof createRfqItemSchema>; - -// ======================= -// 3) Update RFQ Schema -// (현재 코드엔 updateTaskSchema라고 되어 있는데, -// RFQ 업데이트이므로 'updateRfqSchema'라 명명하는 게 자연스러움) -// ======================= -export const updateRfqSchema = z.object({ - // PK id -> 실제로는 URL params로 받을 수도 있지만, - // 여기서는 body에서 받는다고 가정 - id: z.number().int().min(1, "Invalid ID"), - - // 업데이트 시 대부분 optional - rfqCode: z.string().max(50).optional(), - projectId: z.number().nullable().optional(), // null 값도 허용 - description: z.string().optional(), - parentRfqId: z.number().nullable().optional(), // 부모 RFQ ID (선택적) - dueDate: z.preprocess( - // null이나 빈 문자열을 undefined로 변환 - (val) => (val === null || val === '') ? undefined : val, - z.date().optional() - ), - rfqType: z.enum(["PURCHASE", "BUDGETARY", "PURCHASE_BUDGETARY"]).optional(), - status: z.union([ - z.enum(["DRAFT", "PUBLISHED", "EVALUATION", "AWARDED"]), - z.string().refine( - (val) => ["DRAFT", "PUBLISHED", "EVALUATION", "AWARDED"].includes(val), - { message: "Invalid status value" } - ) - ]).optional(), - createdBy: z.number().int().min(1).optional(), -}); -export type UpdateRfqSchema = z.infer<typeof updateRfqSchema>; - -export const searchParamsRfqsForVendorsCache = createSearchParamsCache({ - // 1) 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 2) 페이지네이션 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 3) 정렬 (rfqs 테이블) - sort: getSortingStateParser<Rfq>().withDefault([ - { id: "createdAt", desc: true }, - ]), - - // 4) 간단 검색 필드 (예: rfqCode, projectName, projectCode 등) - rfqCode: parseAsString.withDefault(""), - projectCode: parseAsString.withDefault(""), - projectName: parseAsString.withDefault(""), - - // 5) 상태 배열 (rfqs.status.enumValues: "DRAFT" | "PUBLISHED" | ...) - status: parseAsArrayOf(z.enum(rfqs.status.enumValues)).withDefault([]), - - // 6) 고급 필터 (nuqs filterColumns) - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 7) 글로벌 검색어 - search: parseAsString.withDefault(""), -}) - -/** - * 최종 타입 - * `Awaited<ReturnType<...parse>>` 형태로 - * Next.js 13 서버 액션이나 클라이언트에서 사용 가능 - */ -export type GetRfqsForVendorsSchema = Awaited<ReturnType<typeof searchParamsRfqsForVendorsCache.parse>> - -export const updateRfqVendorSchema = z.object({ - id: z.number().int().min(1, "Invalid ID"), // rfq_vendors.id - status: z.enum(["INVITED","ACCEPTED","DECLINED","REVIEWING", "RESPONDED"]) -}) - -export type UpdateRfqVendorSchema = z.infer<typeof updateRfqVendorSchema> - - -export const searchParamsCBECache = createSearchParamsCache({ - // 1) 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 2) 페이지네이션 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 3) 정렬 (VendorResponseCBEView 테이블) - // getSortingStateParser<VendorResponseCBEView>() → CBE 테이블의 컬럼명에 맞춤 - sort: getSortingStateParser<VendorResponseCBEView>().withDefault([ - { id: "totalPrice", desc: true }, - ]), - - // 4) 간단 검색 필드 - 기본 정보 - vendorName: parseAsString.withDefault(""), - vendorCode: parseAsString.withDefault(""), - country: parseAsString.withDefault(""), - email: parseAsString.withDefault(""), - website: parseAsString.withDefault(""), - - // CBE 관련 필드 - commercialResponseId: parseAsString.withDefault(""), - totalPrice: parseAsString.withDefault(""), - currency: parseAsString.withDefault(""), - paymentTerms: parseAsString.withDefault(""), - incoterms: parseAsString.withDefault(""), - deliveryPeriod: parseAsString.withDefault(""), - warrantyPeriod: parseAsString.withDefault(""), - validityPeriod: parseAsString.withDefault(""), - - // RFQ 관련 필드 - rfqType: parseAsStringEnum(["PURCHASE", "BUDGETARY", "PURCHASE_BUDGETARY"]).withDefault("PURCHASE"), - - // 응답 상태 - responseStatus: parseAsStringEnum(["INVITED", "ACCEPTED", "DECLINED", "REVIEWING", "RESPONDED"]).withDefault("REVIEWING"), - - // 5) 상태 (배열) - vendor 상태 - vendorStatus: parseAsArrayOf(z.enum(vendors.status.enumValues)).withDefault([]), - - // 6) 고급 필터 (nuqs - filterColumns) - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 7) 글로벌 검색어 - search: parseAsString.withDefault(""), - - // 8) 첨부파일 관련 필터 - hasAttachments: parseAsBoolean.withDefault(false), - - // 9) 날짜 범위 필터 - respondedAtRange: parseAsString.withDefault(""), - commercialUpdatedAtRange: parseAsString.withDefault(""), -}) - -export type GetCBESchema = Awaited<ReturnType<typeof searchParamsCBECache.parse>>; - - -export const createCbeEvaluationSchema = z.object({ - paymentTerms: z.string().min(1, "지급 조건을 입력하세요"), - incoterms: z.string().min(1, "Incoterms를 입력하세요"), - deliverySchedule: z.string().min(1, "배송 일정을 입력하세요"), - notes: z.string().optional(), -}) - -// 타입 추출 -export type CreateCbeEvaluationSchema = z.infer<typeof createCbeEvaluationSchema>
\ No newline at end of file |
