diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-11 09:02:00 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-11 09:02:00 +0000 |
| commit | cbb4c7fe0b94459162ad5e998bc05cd293e0ff96 (patch) | |
| tree | 0a26712f7685e4f6511e637b9a81269d90a47c8f /lib/bidding/validation.ts | |
| parent | eb654f88214095f71be142b989e620fd28db3f69 (diff) | |
(대표님) 입찰, EDP 변경사항 대응, spreadJS 오류 수정, 벤더실사 수정
Diffstat (limited to 'lib/bidding/validation.ts')
| -rw-r--r-- | lib/bidding/validation.ts | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/lib/bidding/validation.ts b/lib/bidding/validation.ts new file mode 100644 index 00000000..3d47aefe --- /dev/null +++ b/lib/bidding/validation.ts @@ -0,0 +1,157 @@ +import { biddings, type Bidding } from "@/db/schema" +import { + createSearchParamsCache, + parseAsArrayOf, + parseAsInteger, + parseAsString, + parseAsStringEnum, +} from "nuqs/server" +import * as z from "zod" + +import { getFiltersStateParser, getSortingStateParser } from "@/lib/parsers" + +export const searchParamsCache = createSearchParamsCache({ + flags: parseAsArrayOf(z.enum(["advancedTable", "floatingBar"])).withDefault([]), + page: parseAsInteger.withDefault(1), + perPage: parseAsInteger.withDefault(10), + sort: getSortingStateParser<Bidding>().withDefault([ + { id: "createdAt", desc: true }, + ]), + + // 기본 필터 + biddingNumber: parseAsString.withDefault(""), + status: parseAsArrayOf(z.enum(biddings.status.enumValues)).withDefault([]), + biddingType: parseAsArrayOf(z.enum(biddings.biddingType.enumValues)).withDefault([]), + contractType: parseAsArrayOf(z.enum(biddings.contractType.enumValues)).withDefault([]), + managerName: parseAsString.withDefault(""), + + // 날짜 필터 + preQuoteDateFrom: parseAsString.withDefault(""), + preQuoteDateTo: parseAsString.withDefault(""), + submissionDateFrom: parseAsString.withDefault(""), + submissionDateTo: parseAsString.withDefault(""), + createdAtFrom: parseAsString.withDefault(""), + createdAtTo: parseAsString.withDefault(""), + + // 가격 필터 + budgetMin: parseAsString.withDefault(""), + budgetMax: parseAsString.withDefault(""), + + // Boolean 필터 + hasSpecificationMeeting: parseAsString.withDefault(""), // "true" | "false" | "" + hasPrDocument: parseAsString.withDefault(""), // "true" | "false" | "" + + // 고급 필터 + filters: getFiltersStateParser().withDefault([]), + joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"), + search: parseAsString.withDefault(""), +}) + +export const createBiddingSchema = z.object({ + // ❌ 제거: biddingNumber (자동 생성) + // ❌ 제거: preQuoteDate (나중에 자동 기록) + // ❌ 제거: biddingRegistrationDate (시스템에서 자동 기록) + + revision: z.number().int().min(0).default(0), + + // ✅ 프로젝트 정보 (새로 추가) + projectId: z.number().min(1, "프로젝트를 선택해주세요"), // 필수 + projectName: z.string().optional(), // ProjectSelector에서 자동 설정 + + // ✅ 필수 필드들 + itemName: z.string().min(1, "품목명은 필수입니다"), + title: z.string().min(1, "입찰명은 필수입니다"), + description: z.string().optional(), + content: z.string().optional(), + + // ✅ 계약 정보 (필수) + contractType: z.enum(biddings.contractType.enumValues, { + required_error: "계약구분을 선택해주세요" + }), + biddingType: z.enum(biddings.biddingType.enumValues, { + required_error: "입찰유형을 선택해주세요" + }), + awardCount: z.enum(biddings.awardCount.enumValues, { + required_error: "낙찰수를 선택해주세요" + }), + contractPeriod: z.string().min(1, "계약기간은 필수입니다"), + + // ✅ 일정 (제출기간 필수) + submissionStartDate: z.string().min(1, "제출시작일시는 필수입니다"), + submissionEndDate: z.string().min(1, "제출마감일시는 필수입니다"), + evaluationDate: z.string().optional(), + + // 회의 및 문서 + hasSpecificationMeeting: z.boolean().default(false), + hasPrDocument: z.boolean().default(false), + prNumber: z.string().optional(), + + // ✅ 가격 정보 (통화 필수) + currency: z.string().min(1, "통화를 선택해주세요").default("KRW"), + budget: z.string().optional(), + targetPrice: z.string().optional(), + finalBidPrice: z.string().optional(), + + // 상태 및 담당자 + status: z.enum(biddings.status.enumValues).default("bidding_generated"), + isPublic: z.boolean().default(false), + managerName: z.string().optional(), + managerEmail: z.string().email().optional().or(z.literal("")), + managerPhone: z.string().optional(), + + // 메타 + remarks: z.string().optional(), + }).refine((data) => { + // 제출 기간 검증: 시작일이 마감일보다 이전이어야 함 + if (data.submissionStartDate && data.submissionEndDate) { + const startDate = new Date(data.submissionStartDate) + const endDate = new Date(data.submissionEndDate) + return startDate < endDate + } + return true + }, { + message: "제출시작일시가 제출마감일시보다 늦을 수 없습니다", + path: ["submissionEndDate"] + }) + + export const updateBiddingSchema = z.object({ + biddingNumber: z.string().min(1, "입찰번호는 필수입니다").optional(), + revision: z.number().int().min(0).optional(), + + projectId: z.number().min(1).optional(), + projectName: z.string().optional(), + itemName: z.string().min(1, "품목명은 필수입니다").optional(), + title: z.string().min(1, "입찰명은 필수입니다").optional(), + description: z.string().optional(), + content: z.string().optional(), + + contractType: z.enum(biddings.contractType.enumValues).optional(), + biddingType: z.enum(biddings.biddingType.enumValues).optional(), + awardCount: z.enum(biddings.awardCount.enumValues).optional(), + contractPeriod: z.string().optional(), + + submissionStartDate: z.string().optional(), + submissionEndDate: z.string().optional(), + evaluationDate: z.string().optional(), + + hasSpecificationMeeting: z.boolean().optional(), + hasPrDocument: z.boolean().optional(), + prNumber: z.string().optional(), + + currency: z.string().optional(), + budget: z.string().optional(), + targetPrice: z.string().optional(), + finalBidPrice: z.string().optional(), + + status: z.enum(biddings.status.enumValues).optional(), + isPublic: z.boolean().optional(), + managerName: z.string().optional(), + managerEmail: z.string().email().optional().or(z.literal("")), + managerPhone: z.string().optional(), + + remarks: z.string().optional(), + }) + + export type GetBiddingsSchema = Awaited<ReturnType<typeof searchParamsCache.parse>> + export type CreateBiddingSchema = z.infer<typeof createBiddingSchema> + export type UpdateBiddingSchema = z.infer<typeof updateBiddingSchema> |
