import { pgView,pgTable, serial, varchar, boolean, date, text, timestamp, integer, decimal } from 'drizzle-orm/pg-core'; import { vendors } from './vendors'; import { eq , sql, relations} from "drizzle-orm"; import { basicContract } from './basicContractDocumnet'; // 법무 업무 테이블 export const legalWorks = pgTable('legal_works', { id: serial('id').primaryKey(), // 구분 (CP, GTC, 기타 등) category: varchar('category', { length: 50 }).notNull(), // 상태 (답변완료, 담당자배정, 검토요청 등) status: varchar('status', { length: 100 }).notNull(), vendorId: integer("company_id") .references(() => vendors.id, { onDelete: "set null" }), // 벤더 정보 vendorCode: varchar('vendor_code', { length: 50 }), vendorName: varchar('vendor_name', { length: 200 }).notNull(), // 긴급여부 isUrgent: boolean('is_urgent').default(false).notNull(), // 날짜 필드들 requestDate: date('request_date'), // 답변요청일 consultationDate: date('consultation_date'), // 의뢰일 expectedAnswerDate: date('expected_answer_date'), // 답변예정일 legalCompletionDate: date('legal_completion_date'), // 법무완료일 // 담당자 정보 reviewer: varchar('reviewer', { length: 100 }), // 검토요청자 legalResponder: varchar('legal_responder', { length: 100 }), // 법무답변자 // 첨부파일 여부 hasAttachment: boolean('has_attachment').default(false).notNull(), // 메타데이터 createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), basicContractId: integer("basic_contract_id") .references(() => basicContract.id, { onDelete: "set null" }), }); // 타입 정의 export type LegalWork = typeof legalWorks.$inferSelect; export type NewLegalWork = typeof legalWorks.$inferInsert; export type LegalWorkCategory = typeof LEGAL_WORK_CATEGORIES[number]; export type LegalWorkStatus = typeof LEGAL_WORK_STATUSES[number]; // 법무 검토 요청 테이블 export const legalWorkRequests = pgTable('legal_work_requests', { id: serial('id').primaryKey(), legalWorkId: integer('legal_work_id').references(() => legalWorks.id, { onDelete: 'cascade' }).notNull(), // 검토부문 (준법문의 or 법무검토) reviewDepartment: varchar('review_department', { length: 50 }).notNull(), // '준법문의' | '법무검토' // 문의종류 (법무검토 선택시만) inquiryType: varchar('inquiry_type', { length: 50 }), // '국내계약' | '국내자문' | '해외계약' | '해외자문' // 제목 title: varchar('title', { length: 500 }).notNull(), // 요청내용 requestContent: text('request_content').notNull(), // ===== 준법문의 관련 필드들 ===== // 공개여부 (준법문의 선택시) isPublic: boolean('is_public').default(false), // 기본값: 비공개 // ===== 법무검토 관련 공통 필드들 ===== // 계약명/프로젝트명 (국내계약/해외계약/해외자문 선택시) contractProjectName: varchar('contract_project_name', { length: 300 }), // 계약서 종류 (국내계약/해외계약/해외자문 선택시) contractType: varchar('contract_type', { length: 100 }), // 계약금액 (국내계약/해외계약/해외자문 선택시) contractAmount: decimal('contract_amount', { precision: 15, scale: 2 }), // ===== 국내계약 전용 필드들 ===== // 계약상대방 (국내계약 선택시) contractCounterparty: varchar('contract_counterparty', { length: 200 }), // 계약상대방 구분 (법인/개인) counterpartyType: varchar('counterparty_type', { length: 20 }), // '법인' | '개인' // 계약기간 (국내계약 선택시) contractPeriod: varchar('contract_period', { length: 200 }), // ===== 자문 관련 필드들 ===== // 사실관계 (국내자문/해외자문 선택시) factualRelation: text('factual_relation'), // ===== 해외 관련 필드들 ===== // 프로젝트번호 (해외계약/해외자문 선택시) projectNumber: varchar('project_number', { length: 100 }), // 선주/발주처 (해외계약/해외자문 선택시) shipownerOrderer: varchar('shipowner_orderer', { length: 200 }), // 준거법 (해외계약/해외자문 선택시) governingLaw: varchar('governing_law', { length: 100 }), // 프로젝트종류 (해외계약/해외자문 선택시) projectType: varchar('project_type', { length: 100 }), // 메타데이터 createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), }); // 법무 회신 테이블 export const legalWorkResponses = pgTable('legal_work_responses', { id: serial('id').primaryKey(), legalWorkId: integer('legal_work_id').references(() => legalWorks.id, { onDelete: 'cascade' }).notNull(), // 답변내용 responseContent: text('response_content').notNull(), // 답변 관련 담당자들 responseReviewer: varchar('response_reviewer', { length: 100 }), // 답변검토자 responseConfirmer: varchar('response_confirmer', { length: 100 }), // 답변확인자 responseApprover: varchar('response_approver', { length: 100 }), // 승인자 // 처리 시간들 reviewedAt: timestamp('reviewed_at'), // 검토시간 confirmedAt: timestamp('confirmed_at'), // 확인시간 approvedAt: timestamp('approved_at'), // 승인시간 // 공개여부 isPublic: boolean('is_public').default(false).notNull(), // 재검토 관련 isReRevision: boolean('is_re_revision').default(false).notNull(), // 재검토 여부 parentResponseId: integer('parent_response_id'), // 이전 답변 참조 // 메타데이터 createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(), }); // 첨부파일 테이블 export const legalWorkAttachments = pgTable('legal_work_attachments', { id: serial('id').primaryKey(), legalWorkId: integer('legal_work_id').references(() => legalWorks.id, { onDelete: 'cascade' }).notNull(), fileName: varchar('file_name', { length: 255 }).notNull(), originalFileName: varchar('original_file_name', { length: 255 }).notNull(), filePath: varchar('file_path', { length: 500 }).notNull(), fileSize: integer('file_size').notNull(), mimeType: varchar('mime_type', { length: 100 }).notNull(), // 자동 생성 파일 여부 (Case1에서 PDF 자동 생성) isAutoGenerated: boolean('is_auto_generated').default(false).notNull(), // 첨부파일 타입 (요청시 첨부 vs 답변시 첨부) attachmentType: varchar('attachment_type', { length: 50 }).default('request'), // 'request' | 'response' createdAt: timestamp('created_at').defaultNow().notNull(), }); export type LegalWorkRequest = typeof legalWorkRequests.$inferSelect; export type LegalWorkResponse = typeof legalWorkResponses.$inferSelect; export type LegalWorkAttachment = typeof legalWorkAttachments.$inferSelect; // 상수 정의 export const LEGAL_WORK_CATEGORIES = [ 'CP', 'GTC', '기타' ] as const; export const LEGAL_WORK_STATUSES = [ '신규등록', '검토요청', '담당자배정', '검토중', '답변완료', '재검토요청', '보류', '취소' ] as const; export const REVIEW_DEPARTMENTS = [ '준법문의', '법무검토' ] as const; export const INQUIRY_TYPES = [ '국내계약', '국내자문', '해외계약', '해외자문' ] as const; export const COUNTERPARTY_TYPES = [ '법인', '개인' ] as const; export const SOURCE_TYPES = [ 'interface', // 22번화면에서 이관 'manual' // 신규생성 ] as const; export const ATTACHMENT_TYPES = [ 'request', // 요청시 첨부 'response' // 답변시 첨부 ] as const; export const legalWorksDetailView = pgView("legal_works_detail_view").as((qb) => { return qb .select({ // legal_works 기본 필드들 id: legalWorks.id, category: legalWorks.category, status: legalWorks.status, vendorId: legalWorks.vendorId, vendorCode: legalWorks.vendorCode, vendorName: legalWorks.vendorName, isUrgent: legalWorks.isUrgent, requestDate: legalWorks.requestDate, consultationDate: legalWorks.consultationDate, expectedAnswerDate: legalWorks.expectedAnswerDate, legalCompletionDate: legalWorks.legalCompletionDate, reviewer: legalWorks.reviewer, legalResponder: legalWorks.legalResponder, hasAttachment: legalWorks.hasAttachment, createdAt: legalWorks.createdAt, updatedAt: legalWorks.updatedAt, // legal_work_requests 필드들 reviewDepartment: legalWorkRequests.reviewDepartment, inquiryType: legalWorkRequests.inquiryType, title: legalWorkRequests.title, requestContent: legalWorkRequests.requestContent, isPublicRequest: legalWorkRequests.isPublic, contractProjectName: legalWorkRequests.contractProjectName, contractType: legalWorkRequests.contractType, contractAmount: legalWorkRequests.contractAmount, // 최신 답변 정보 (서브쿼리) responseContent: sql`( SELECT response_content FROM legal_work_responses lwr_latest WHERE lwr_latest.legal_work_id = ${legalWorks.id} ORDER BY lwr_latest.created_at DESC LIMIT 1 )`.as('response_content'), // 첨부파일 개수 attachmentCount: sql`( SELECT COUNT(*)::integer FROM legal_work_attachments lwa WHERE lwa.legal_work_id = ${legalWorks.id} )`.as('attachment_count'), }) .from(legalWorks) .leftJoin(legalWorkRequests, sql`${legalWorks.id} = ${legalWorkRequests.legalWorkId}`) .leftJoin(vendors, sql`${legalWorks.vendorId} = ${vendors.id}`); }); // 타입 추출 export type LegalWorksDetailView = typeof legalWorksDetailView.$inferSelect;