import { pgTable, serial, varchar, integer, date, timestamp, decimal, text, jsonb, boolean } from 'drizzle-orm/pg-core'; import { relations } from 'drizzle-orm'; import { users } from './users'; // users 테이블이 존재한다고 가정 import { vendors } from './vendors'; // vendors 테이블이 존재한다고 가정 export const generalContractTemplates = pgTable('general_contract_templates', { id: integer("id").primaryKey().generatedAlwaysAsIdentity(), contractTemplateType: varchar('contract_template_type', { length: 2 }).notNull(), contractTemplateName: text('contract_template_name').notNull(), revision: integer('revision').notNull().default(1), status: varchar('status', { length: 20 }).notNull().default('ACTIVE'), fileName: varchar("file_name", { length: 255 }), filePath: varchar("file_path", { length: 1024 }), legalReviewRequired: boolean('legal_review_required').notNull().default(false), createdAt: timestamp('created_at').defaultNow(), createdBy: integer('created_by').references(() => users.id), updatedAt: timestamp('updated_at').defaultNow(), updatedBy: integer('updated_by').references(() => users.id), disposedAt: timestamp('disposed_at'), restoredAt: timestamp('restored_at'), }); export const generalContracts = pgTable('general_contracts', { // ═══════════════════════════════════════════════════════════════ // 기본 식별 정보 // ═══════════════════════════════════════════════════════════════ id: serial('id').primaryKey(), // 계약 고유 ID contractNumber: varchar('contract_number', { length: 255 }).notNull().unique(), // 계약번호 (자동 채번) revision: integer('revision').notNull().default(0), // 계약 개정 번호 // ═══════════════════════════════════════════════════════════════ // 계약 분류 및 상태 // ═══════════════════════════════════════════════════════════════ status: varchar('status', { length: 50 }).notNull(), // 계약 상태 (Draft, Complete the Contract, Contract Delete 등) category: varchar('category', { length: 50 }).notNull(), // 계약구분 (단가계약, 일반계약, 매각계약) type: varchar('type', { length: 50 }).notNull(), // 계약종류 (UP, LE, IL, AL 등) executionMethod: varchar('execution_method', { length: 50 }).notNull(), // 체결방식 (단가계약, 일반계약 등) name: varchar('name', { length: 255 }).notNull(), // 계약명 selectionMethod: varchar('selection_method', { length: 50 }), // 업체선정방법 // ═══════════════════════════════════════════════════════════════ // 협력업체 및 계약 기간 // ═══════════════════════════════════════════════════════════════ vendorId: integer('vendor_id').notNull().references(() => vendors.id), // 협력업체 ID startDate: date('start_date').notNull(), // 계약 시작일 endDate: date('end_date').notNull(), // 계약 종료일 validityEndDate: date('validity_end_date').notNull(), // 계약 유효기간 종료일 // ═══════════════════════════════════════════════════════════════ // 연계 정보 // ═══════════════════════════════════════════════════════════════ linkedRfqOrItb: varchar('linked_rfq_or_itb', { length: 255 }), // 연계 RFQ/ITB 번호 linkedPoNumber: varchar('linked_po_number', { length: 255 }), // 연계 PO 번호 linkedBidNumber: varchar('linked_bid_number', { length: 255 }), // 연계 BID 번호 // ═══════════════════════════════════════════════════════════════ // 계약 범위 및 사양 // ═══════════════════════════════════════════════════════════════ contractScope: varchar('contract_scope', { length: 50 }), // 계약 범위 warrantyPeriod: jsonb('warranty_period').default({}), // 품질/하자 보증기간 specificationType: varchar('specification_type', { length: 50 }), // 사양 유형 specificationManualText: text('specification_manual_text'), // 사양 매뉴얼 텍스트 // ═══════════════════════════════════════════════════════════════ // 금액 정보 // ═══════════════════════════════════════════════════════════════ unitPriceType: varchar('unit_price_type', { length: 50 }), // 단가 유형 contractAmount: decimal('contract_amount', { precision: 15, scale: 2 }), // 계약 금액 currency: varchar('currency', { length: 10 }), // 통화 totalAmount: decimal('total_amount', { precision: 15, scale: 2 }), // 총 금액 availableBudget: decimal('available_budget', { precision: 15, scale: 2 }), // 가용 예산 // ═══════════════════════════════════════════════════════════════ // 지급조건 (Payment Condition) // ═══════════════════════════════════════════════════════════════ paymentBeforeDelivery: jsonb('payment_before_delivery').default({}), // 납품 전 지급조건 paymentDelivery: varchar('payment_delivery', { length: 50 }), // 납품 지급조건 paymentAfterDelivery: jsonb('payment_after_delivery').default({}), // 납품 외 지급조건 contractCurrency: varchar('contract_currency', { length: 10 }), // 계약통화 paymentTerm: varchar('payment_term', { length: 50 }), // 지불조건 (L003 등) taxType: varchar('tax_type', { length: 50 }), // 세금 (VV 등) liquidatedDamages: decimal('liquidated_damages', { precision: 15, scale: 2 }), // 지체상금 liquidatedDamagesPercent: decimal('liquidated_damages_percent', { precision: 5, scale: 2 }), // 지체상금 비율 claimAmount: jsonb('claim_amount').default({}), // 클레임금액 // ═══════════════════════════════════════════════════════════════ // 인도조건 (Delivery Condition) // ═══════════════════════════════════════════════════════════════ deliveryType: varchar('delivery_type', { length: 50 }), // 납기종류 (단일납기, 분할납기, 구간납기) deliveryTerm: varchar('delivery_term', { length: 50 }), // 인도조건 (FOB 등) shippingLocation: varchar('shipping_location', { length: 100 }), // 선적지 dischargeLocation: varchar('discharge_location', { length: 100 }), // 하역지 contractDeliveryDate: date('contract_delivery_date'), // 계약납기일 // ═══════════════════════════════════════════════════════════════ // 추가조건 (Additional Condition) // ═══════════════════════════════════════════════════════════════ contractEstablishmentConditions: jsonb('contract_establishment_conditions').default({}), // 계약성립조건 interlockingSystem: varchar('interlocking_system', { length: 10 }), // 연동제적용 (Y/N) mandatoryDocuments: jsonb('mandatory_documents').default({}), // 필수문서동의 contractTerminationConditions: jsonb('contract_termination_conditions').default({}), // 계약해지조건 // ═══════════════════════════════════════════════════════════════ // 기타 계약 조건 및 약관 (JSON 형태) // ═══════════════════════════════════════════════════════════════ terms: jsonb('terms').default({}), // 계약 조건 complianceChecklist: jsonb('compliance_checklist').default({}), // 컴플라이언스 체크리스트 communicationChannels: jsonb('communication_channels').default({}), // 커뮤니케이션 채널 locations: jsonb('locations').default({}), // 위치 정보 fieldServiceRates: jsonb('field_service_rates').default({}), // 현장 서비스 요금 offsetDetails: jsonb('offset_details').default({}), // 오프셋 세부사항 // ═══════════════════════════════════════════════════════════════ // 시스템 관리 정보 // ═══════════════════════════════════════════════════════════════ registeredById: integer('registered_by_id').notNull().references(() => users.id), // 등록자 ID registeredAt: timestamp('registered_at').notNull().defaultNow(), // 등록일시 signedAt: timestamp('signed_at'), // 계약 체결일시 lastUpdatedById: integer('last_updated_by_id').notNull().references(() => users.id), // 최종 수정자 ID lastUpdatedAt: timestamp('last_updated_at').notNull().defaultNow(), // 최종 수정일시 notes: text('notes'), // 비고 }); export const generalContractItems = pgTable('general_contract_items', { // ═══════════════════════════════════════════════════════════════ // 기본 식별 정보 // ═══════════════════════════════════════════════════════════════ id: serial('id').primaryKey(), // 품목 고유 ID contractId: integer('contract_id').notNull().references(() => generalContracts.id), // 계약 ID (외래키) // ═══════════════════════════════════════════════════════════════ // 품목 기본 정보 // ═══════════════════════════════════════════════════════════════ project: varchar('project', { length: 255 }), // 프로젝트 명 itemCode: varchar('item_code', { length: 100 }), // 품목코드 (PKG No.) itemInfo: varchar('item_info', { length: 500 }), // Item 정보 (자재그룹 / 자재코드) specification: varchar('specification', { length: 500 }), // 규격 // ═══════════════════════════════════════════════════════════════ // 수량 및 단가 정보 // ═══════════════════════════════════════════════════════════════ quantity: decimal('quantity', { precision: 15, scale: 3 }), // 수량 quantityUnit: varchar('quantity_unit', { length: 50 }), // 수량단위 contractDeliveryDate: date('contract_delivery_date'), // 계약납기일 contractUnitPrice: decimal('contract_unit_price', { precision: 15, scale: 2 }), // 계약단가 contractAmount: decimal('contract_amount', { precision: 15, scale: 2 }), // 계약금액 contractCurrency: varchar('contract_currency', { length: 10 }), // 계약통화 // ═══════════════════════════════════════════════════════════════ // 시스템 관리 정보 // ═══════════════════════════════════════════════════════════════ createdAt: timestamp('created_at').notNull().defaultNow(), // 생성일시 updatedAt: timestamp('updated_at').notNull().defaultNow(), // 수정일시 }); export const generalContractAttachments = pgTable('general_contract_attachments', { id: serial('id').primaryKey(), contractId: integer('contract_id').notNull().references(() => generalContracts.id), documentName: varchar('document_name', { length: 255 }).notNull(), // '사양 및 공급범위', '단가파일', '계약서 서명본' 등 fileName: varchar('file_name', { length: 255 }).notNull(), // 실제 파일명 filePath: varchar('file_path', { length: 512 }).notNull(), // 파일 저장 경로 (S3 URL 등) shiComment: text('shi_comment'), vendorComment: text('vendor_comment'), legalReview: boolean('legal_review').notNull().default(false), // 법무 검토 여부 uploadedAt: timestamp('uploaded_at').notNull().defaultNow(), uploadedById: integer('uploaded_by_id').notNull().references(() => users.id), }); export const generalContractAttachmentsRelations = relations(generalContractAttachments, ({ one }) => ({ contract: one(generalContracts, { fields: [generalContractAttachments.contractId], references: [generalContracts.id], }), })); export const generalContractItemsRelations = relations(generalContractItems, ({ one }) => ({ contract: one(generalContracts, { fields: [generalContractItems.contractId], references: [generalContracts.id], }), })); export const generalContractsRelations = relations(generalContracts, ({ one, many }) => ({ manager: one(users, { fields: [generalContracts.registeredById], references: [users.id], relationName: 'contract_manager', }), lastUpdatedBy: one(users, { fields: [generalContracts.lastUpdatedById], references: [users.id], relationName: 'contract_last_updated_by', }), vendor: one(vendors, { fields: [generalContracts.vendorId], references: [vendors.id], }), items: many(generalContractItems), attachments: many(generalContractAttachments), })); // TypeScript 타입 정의 export type GeneralContractTemplate = typeof generalContractTemplates.$inferSelect; export type NewGeneralContractTemplate = typeof generalContractTemplates.$inferInsert; export type GeneralContract = typeof generalContracts.$inferSelect; export type NewGeneralContract = typeof generalContracts.$inferInsert; export type GeneralContractItem = typeof generalContractItems.$inferSelect; export type NewGeneralContractItem = typeof generalContractItems.$inferInsert; export type GeneralContractAttachment = typeof generalContractAttachments.$inferSelect; export type NewGeneralContractAttachment = typeof generalContractAttachments.$inferInsert;