summaryrefslogtreecommitdiff
path: root/db/schema/generalContract.ts
diff options
context:
space:
mode:
Diffstat (limited to 'db/schema/generalContract.ts')
-rw-r--r--db/schema/generalContract.ts209
1 files changed, 209 insertions, 0 deletions
diff --git a/db/schema/generalContract.ts b/db/schema/generalContract.ts
new file mode 100644
index 00000000..bb671494
--- /dev/null
+++ b/db/schema/generalContract.ts
@@ -0,0 +1,209 @@
+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; \ No newline at end of file