diff options
Diffstat (limited to 'lib/b-rfq/validations.ts')
| -rw-r--r-- | lib/b-rfq/validations.ts | 447 |
1 files changed, 0 insertions, 447 deletions
diff --git a/lib/b-rfq/validations.ts b/lib/b-rfq/validations.ts deleted file mode 100644 index bee10a11..00000000 --- a/lib/b-rfq/validations.ts +++ /dev/null @@ -1,447 +0,0 @@ -import { createSearchParamsCache, - parseAsArrayOf, - parseAsInteger, - parseAsString, - parseAsStringEnum,parseAsBoolean - } from "nuqs/server" - import * as z from "zod" - -import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" -import { FinalRfqDetailView, VendorAttachmentResponse } from "@/db/schema"; - -export const searchParamsRFQDashboardCache = createSearchParamsCache({ - // 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 페이징 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 정렬 - rfqDashboardView 기반 - sort: getSortingStateParser<{ - rfqId: number; - rfqCode: string; - description: string; - status: string; - dueDate: Date; - projectCode: string; - projectName: string; - packageNo: string; - packageName: string; - picName: string; - totalAttachments: number; - initialVendorCount: number; - finalVendorCount: number; - initialResponseRate: number; - finalResponseRate: number; - overallProgress: number; - daysToDeadline: number; - createdAt: Date; - }>().withDefault([ - { id: "createdAt", desc: true }, - ]), - - // 고급 필터 - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 기본 필터 - rfqBasicFilters: getFiltersStateParser().withDefault([]), - rfqBasicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - basicFilters: getFiltersStateParser().withDefault([]), - basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 검색 키워드 - search: parseAsString.withDefault(""), - - // RFQ 특화 필터 - rfqCode: parseAsString.withDefault(""), - projectName: parseAsString.withDefault(""), - projectCode: parseAsString.withDefault(""), - picName: parseAsString.withDefault(""), - packageNo: parseAsString.withDefault(""), - status: parseAsStringEnum([ - "DRAFT", - "Doc. Received", - "PIC Assigned", - "Doc. Confirmed", - "Init. RFQ Sent", - "Init. RFQ Answered", - "TBE started", - "TBE finished", - "Final RFQ Sent", - "Quotation Received", - "Vendor Selected" - ]), - dueDateFrom: parseAsString.withDefault(""), - dueDateTo: parseAsString.withDefault(""), - progressMin: parseAsInteger.withDefault(0), - progressMax: parseAsInteger.withDefault(100), - }); - - export type GetRFQDashboardSchema = Awaited<ReturnType<typeof searchParamsRFQDashboardCache.parse>> - - - export const createRfqServerSchema = z.object({ - projectId: z.number().min(1, "프로젝트를 선택해주세요"), // 필수로 변경 - dueDate: z.date(), // Date 객체로 직접 받기 - picCode: z.string().min(1, "구매 담당자 코드를 입력해주세요"), - picName: z.string().optional(), - engPicName: z.string().optional(), - packageNo: z.string().min(1, "패키지 번호를 입력해주세요"), - packageName: z.string().min(1, "패키지명을 입력해주세요"), - remark: z.string().optional(), - projectCompany: z.string().optional(), - projectFlag: z.string().optional(), - projectSite: z.string().optional(), - createdBy: z.number(), - updatedBy: z.number(), - }) - - export type CreateRfqInput = z.infer<typeof createRfqServerSchema> - - - - export type RfqAttachment = { - id: number - attachmentType: string - serialNo: string - rfqId: number - fileName: string - originalFileName: string - filePath: string - fileSize: number | null - fileType: string | null - description: string | null - createdBy: number - createdAt: Date - createdByName?: string - responseStats?: { - totalVendors: number - respondedCount: number - pendingCount: number - waivedCount: number - responseRate: number - } - } - - // RFQ Attachments용 검색 파라미터 캐시 - export const searchParamsRfqAttachmentsCache = createSearchParamsCache({ - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - sort: getSortingStateParser<RfqAttachment>().withDefault([ - { id: "createdAt", desc: true }, - ]), - // 기본 필터 - attachmentType: parseAsArrayOf(z.string()).withDefault([]), - fileType: parseAsArrayOf(z.string()).withDefault([]), - search: parseAsString.withDefault(""), - // advanced filter - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - }) - - // 스키마 타입들 - export type GetRfqAttachmentsSchema = Awaited<ReturnType<typeof searchParamsRfqAttachmentsCache.parse>> - - - // 첨부파일 레코드 타입 -export const attachmentRecordSchema = z.object({ - rfqId: z.number().positive(), - attachmentType: z.enum(["구매", "설계"]), - // serialNo: z.string().min(1), - description: z.string().optional(), - fileName: z.string(), - originalFileName: z.string(), - filePath: z.string(), - fileSize: z.number(), - fileType: z.string(), -}) - -export type AttachmentRecord = z.infer<typeof attachmentRecordSchema> - -export const deleteAttachmentsSchema = z.object({ - ids: z.array(z.number()).min(1, "삭제할 첨부파일을 선택해주세요."), -}) - -export type DeleteAttachmentsInput = z.infer<typeof deleteAttachmentsSchema> - - -//Inital RFQ -export const searchParamsInitialRfqDetailCache = createSearchParamsCache({ - // 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 페이징 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 정렬 - initialRfqDetailView 기반 - sort: getSortingStateParser<{ - rfqId: number; - rfqCode: string; - rfqStatus: string; - initialRfqId: number; - initialRfqStatus: string; - vendorId: number; - vendorCode: string; - vendorName: string; - vendorCountry: string; - vendorBusinessSize: string; - dueDate: Date; - validDate: Date; - incotermsCode: string; - incotermsDescription: string; - shortList: boolean; - returnYn: boolean; - cpRequestYn: boolean; - prjectGtcYn: boolean; - returnRevision: number; - gtc: string; - gtcValidDate: string; - classification: string; - sparepart: string; - createdAt: Date; - updatedAt: Date; - }>().withDefault([ - { id: "createdAt", desc: true }, - ]), - - // 고급 필터 - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 기본 필터 - basicFilters: getFiltersStateParser().withDefault([]), - basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 검색 키워드 - search: parseAsString.withDefault(""), - - // Initial RFQ Detail 특화 필터 - rfqCode: parseAsString.withDefault(""), - rfqStatus: parseAsStringEnum([ - "DRAFT", - "Doc. Received", - "PIC Assigned", - "Doc. Confirmed", - "Init. RFQ Sent", - "Init. RFQ Answered", - "TBE started", - "TBE finished", - "Final RFQ Sent", - "Quotation Received", - "Vendor Selected" - ]), - initialRfqStatus: parseAsStringEnum([ - "PENDING", - "SENT", - "RESPONDED", - "EXPIRED", - "CANCELLED" - ]), - vendorName: parseAsString.withDefault(""), - vendorCode: parseAsString.withDefault(""), - vendorCountry: parseAsString.withDefault(""), - vendorBusinessSize: parseAsStringEnum([ - "LARGE", - "MEDIUM", - "SMALL", - "STARTUP" - ]), - incotermsCode: parseAsString.withDefault(""), - dueDateFrom: parseAsString.withDefault(""), - dueDateTo: parseAsString.withDefault(""), - validDateFrom: parseAsString.withDefault(""), - validDateTo: parseAsString.withDefault(""), - shortList: parseAsStringEnum(["true", "false"]), - returnYn: parseAsStringEnum(["true", "false"]), - cpRequestYn: parseAsStringEnum(["true", "false"]), - prjectGtcYn: parseAsStringEnum(["true", "false"]), - classification: parseAsString.withDefault(""), - sparepart: parseAsString.withDefault(""), -}); - -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(), - gtc: z.string().optional(), - gtcValidDate: z.string().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; -}; - -export const shortListConfirmSchema = z.object({ - rfqId: z.number(), - selectedVendorIds: z.array(z.number()).min(1), - rejectedVendorIds: z.array(z.number()), -}) - -export type ShortListConfirmInput = z.infer<typeof shortListConfirmSchema> - - -export const searchParamsFinalRfqDetailCache = createSearchParamsCache({ - // 공통 플래그 - flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), - - // 페이징 - page: parseAsInteger.withDefault(1), - perPage: parseAsInteger.withDefault(10), - - // 정렬 - initialRfqDetailView 기반 - sort: getSortingStateParser<FinalRfqDetailView>().withDefault([ - { id: "createdAt", desc: true }, - ]), - - // 고급 필터 - filters: getFiltersStateParser().withDefault([]), - joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 기본 필터 - basicFilters: getFiltersStateParser().withDefault([]), - basicJoinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), - - // 검색 키워드 - search: parseAsString.withDefault(""), - - -}); - -export type GetFinalRfqDetailSchema = Awaited<ReturnType<typeof searchParamsFinalRfqDetailCache.parse>>; - |
