/** * PCR (Purchase Change Request) 관련 스키마 * * PCR_PO: 구매/계약 정보 변경 요청 테이블 * PCR_PR: 구매 요청 세부 정보 테이블 */ import { pgTable, serial, varchar, text, timestamp, integer, date, numeric, index, } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; import { users } from "./users"; import { vendors } from "./vendors"; // ===== PCR_PR 첨부파일 테이블 ===== export const pcrPrAttachment = pgTable("pcr_pr_attachment", { id: serial("id").primaryKey(), pcrPrId: integer("pcr_pr_id").notNull().references(() => pcrPr.id), // PCR_PR 참조 type: varchar("type", { length: 20 }).notNull(), // 'BEFORE' | 'AFTER' (변경전/변경후) fileName: varchar("file_name", { length: 255 }).notNull(), filePath: text("file_path").notNull(), fileSize: integer("file_size"), mimeType: varchar("mime_type", { length: 100 }), createdBy: integer("created_by").references(() => users.id), createdAt: timestamp("created_at").defaultNow().notNull(), updatedBy: integer("updated_by").references(() => users.id), updatedAt: timestamp("updated_at").defaultNow().notNull(), }); // ===== PCR_PO 테이블 (상단 테이블) ===== export const pcrPo = pgTable("pcr_po", { id: serial("id").primaryKey(), // 협력업체 정보 (EvcP 페이지에만 표시) vendorId: integer("vendor_id").references(() => vendors.id), // PCR 승인 상태 pcrApprovalStatus: varchar("pcr_approval_status", { length: 20 }) .default('PENDING'), // 변경 구분 changeType: varchar("change_type", { length: 20 }) .default('OTHER'), // 상세 details: text("details"), // 프로젝트 project: varchar("project", { length: 255 }), // PCR 요청 일자 pcrRequestDate: date("pcr_request_date", { mode: "date" }).notNull(), // PO/계약 번호 poContractNumber: varchar("po_contract_number", { length: 100 }).notNull(), // Rev./품번 revItemNumber: varchar("rev_item_number", { length: 100 }), // 구매/계약 담당자 purchaseContractManager: varchar("purchase_contract_manager", { length: 100 }), // PCR 생성자 pcrCreator: varchar("pcr_creator", { length: 100 }), // PO/계약 금액 (전) poContractAmountBefore: numeric("po_contract_amount_before", { precision: 15, scale: 2 }), // PO/계약 금액 (후) poContractAmountAfter: numeric("po_contract_amount_after", { precision: 15, scale: 2 }), // 계약 통화 contractCurrency: varchar("contract_currency", { length: 10 }).default("KRW"), // PCR 사유 pcrReason: text("pcr_reason"), // 상세 사유 detailsReason: text("details_reason"), // 거절 사유 rejectionReason: text("rejection_reason"), // PCR 회신 일 pcrResponseDate: date("pcr_response_date", { mode: "date" }), // 감사 필드 createdBy: integer("created_by") .notNull() .references(() => users.id, { onDelete: "set null" }), updatedBy: integer("updated_by") .notNull() .references(() => users.id, { onDelete: "set null" }), createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(), }, (table) => ({ // 인덱스 정의 poContractNumberIdx: index("pcr_po_po_contract_number_idx").on(table.poContractNumber), vendorIdIdx: index("pcr_po_vendor_id_idx").on(table.vendorId), pcrApprovalStatusIdx: index("pcr_po_approval_status_idx").on(table.pcrApprovalStatus), createdAtIdx: index("pcr_po_created_at_idx").on(table.createdAt), })); // ===== PCR_PR 테이블 (하단 테이블) ===== export const pcrPr = pgTable("pcr_pr", { id: serial("id").primaryKey(), // 자재번호 materialNumber: varchar("material_number", { length: 100 }).notNull(), // 자재내역 materialDetails: text("material_details"), // 수량 (변경전) quantityBefore: numeric("quantity_before", { precision: 12, scale: 3 }), // 수량 (변경후) quantityAfter: numeric("quantity_after", { precision: 12, scale: 3 }), // 중량 (변경전) weightBefore: numeric("weight_before", { precision: 12, scale: 3 }), // 중량 (변경후) weightAfter: numeric("weight_after", { precision: 12, scale: 3 }), // 사급중량 (변경전) subcontractorWeightBefore: numeric("subcontractor_weight_before", { precision: 12, scale: 3 }), // 사급중량 (변경후) subcontractorWeightAfter: numeric("subcontractor_weight_after", { precision: 12, scale: 3 }), // 도급중량 (변경전) supplierWeightBefore: numeric("supplier_weight_before", { precision: 12, scale: 3 }), // 도급중량 (변경후) supplierWeightAfter: numeric("supplier_weight_after", { precision: 12, scale: 3 }), // SPEC 도면 (변경전) specDrawingBefore: text("spec_drawing_before"), // SPEC 도면 (변경후) specDrawingAfter: text("spec_drawing_after"), // 최초 PO/계약 일 initialPoContractDate: date("initial_po_contract_date", { mode: "date" }), // SPEC 변경 일 specChangeDate: date("spec_change_date", { mode: "date" }), // PO/계약 수정 일 poContractModifiedDate: date("po_contract_modified_date", { mode: "date" }), // 확인 일 confirmationDate: date("confirmation_date", { mode: "date" }), // 설계 담당자 designManager: varchar("design_manager", { length: 100 }), // PO/계약 번호 (PCR_PO와 연결) poContractNumber: varchar("po_contract_number", { length: 100 }).notNull(), // 감사 필드 createdBy: integer("created_by") .notNull() .references(() => users.id, { onDelete: "set null" }), updatedBy: integer("updated_by") .notNull() .references(() => users.id, { onDelete: "set null" }), createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(), }, (table) => ({ // 인덱스 정의 poContractNumberIdx: index("pcr_pr_po_contract_number_idx").on(table.poContractNumber), materialNumberIdx: index("pcr_pr_material_number_idx").on(table.materialNumber), createdAtIdx: index("pcr_pr_created_at_idx").on(table.createdAt), })); // ===== Relations 정의 ===== export const pcrPoRelations = relations(pcrPo, ({ one, many }) => ({ // 생성자 관계 createdByUser: one(users, { fields: [pcrPo.createdBy], references: [users.id], relationName: "pcrPoCreatedBy", }), updatedByUser: one(users, { fields: [pcrPo.updatedBy], references: [users.id], relationName: "pcrPoUpdatedBy", }), // 협력업체 관계 vendor: one(vendors, { fields: [pcrPo.vendorId], references: [vendors.id], }), // 하위 PCR_PR 관계 pcrPrItems: many(pcrPr), })); export const pcrPrRelations = relations(pcrPr, ({ one }) => ({ // 생성자 관계 createdByUser: one(users, { fields: [pcrPr.createdBy], references: [users.id], relationName: "pcrPrCreatedBy", }), updatedByUser: one(users, { fields: [pcrPr.updatedBy], references: [users.id], relationName: "pcrPrUpdatedBy", }), // 상위 PCR_PO 관계 pcrPoItem: one(pcrPo, { fields: [pcrPr.poContractNumber], references: [pcrPo.poContractNumber], }), })); // ===== 타입 정의 ===== export type PcrPo = typeof pcrPo.$inferSelect; export type PcrPr = typeof pcrPr.$inferSelect; export type NewPcrPo = typeof pcrPo.$inferInsert; export type NewPcrPr = typeof pcrPr.$inferInsert;