diff options
Diffstat (limited to 'db/schema')
| -rw-r--r-- | db/schema/index.ts | 4 | ||||
| -rw-r--r-- | db/schema/menu-v2.ts | 88 |
2 files changed, 92 insertions, 0 deletions
diff --git a/db/schema/index.ts b/db/schema/index.ts index 6463e0ec..022431cc 100644 --- a/db/schema/index.ts +++ b/db/schema/index.ts @@ -29,7 +29,11 @@ export * from './evaluation'; export * from './evaluationTarget'; export * from './evaluationCriteria'; export * from './projectGtc'; +// 기존 menu 스키마 (deprecated - menu-v2로 대체됨) export * from './menu'; + +// 새로운 메뉴 트리 스키마 (v2) +export * from './menu-v2'; export * from './information'; export * from './qna'; export * from './notice'; diff --git a/db/schema/menu-v2.ts b/db/schema/menu-v2.ts new file mode 100644 index 00000000..2d0282fa --- /dev/null +++ b/db/schema/menu-v2.ts @@ -0,0 +1,88 @@ +// db/schema/menu-v2.ts +import { pgTable, pgEnum, integer, varchar, text, timestamp, boolean, index, uniqueIndex } from "drizzle-orm/pg-core"; +import { relations } from "drizzle-orm"; +import { users } from "./users"; + +export const menuTreeNodeTypeEnum = pgEnum('menu_tree_node_type', [ + 'menu_group', // 메뉴그룹 (1단계) - 헤더에 표시되는 드롭다운 트리거 + 'group', // 그룹 (2단계) - 드롭다운 내 구분 영역 + 'menu', // 메뉴 (3단계) - 드롭다운 내 링크 + 'additional' // 추가 메뉴 - 최상위 단일 링크 (Dashboard, QNA, FAQ 등) +]); + +export const menuDomainEnum = pgEnum('menu_domain', [ + 'evcp', // 내부 사용자용 + 'partners' // 협력업체용 +]); + +export const menuTreeNodes = pgTable("menu_tree_nodes", { + id: integer("id").primaryKey().generatedAlwaysAsIdentity(), + + // 도메인 구분 + domain: menuDomainEnum("domain").notNull(), + + // 트리 구조 + parentId: integer("parent_id").references((): any => menuTreeNodes.id, { onDelete: "cascade" }), + nodeType: menuTreeNodeTypeEnum("node_type").notNull(), + sortOrder: integer("sort_order").notNull().default(0), + + // 다국어 텍스트 (DB 직접 관리) + titleKo: varchar("title_ko", { length: 255 }).notNull(), + titleEn: varchar("title_en", { length: 255 }), + descriptionKo: text("description_ko"), + descriptionEn: text("description_en"), + + // 메뉴 전용 필드 (nodeType === 'menu' 또는 'additional'일 때) + menuPath: varchar("menu_path", { length: 255 }), // href 값 (예: /evcp/projects) + icon: varchar("icon", { length: 100 }), + + // 권한 연동 + // evcp: Oracle DB SCR_ID 참조 + // partners: 자체 권한 시스템 (TODO) + scrId: varchar("scr_id", { length: 100 }), + + // 상태 + isActive: boolean("is_active").default(true).notNull(), + + // 담당자 (evcp 전용) + manager1Id: integer("manager1_id").references(() => users.id, { onDelete: "set null" }), + manager2Id: integer("manager2_id").references(() => users.id, { onDelete: "set null" }), + + createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(), +}, (table) => ({ + domainIdx: index("menu_tree_domain_idx").on(table.domain), + parentIdx: index("menu_tree_parent_idx").on(table.parentId), + sortOrderIdx: index("menu_tree_sort_order_idx").on(table.sortOrder), + menuPathUnique: uniqueIndex("menu_tree_path_unique_idx").on(table.menuPath), + scrIdIdx: index("menu_tree_scr_id_idx").on(table.scrId), +})); + +// Relations 정의 +export const menuTreeNodesRelations = relations(menuTreeNodes, ({ one, many }) => ({ + parent: one(menuTreeNodes, { + fields: [menuTreeNodes.parentId], + references: [menuTreeNodes.id], + relationName: "parentChild", + }), + children: many(menuTreeNodes, { + relationName: "parentChild", + }), + manager1: one(users, { + fields: [menuTreeNodes.manager1Id], + references: [users.id], + relationName: "menuManager1", + }), + manager2: one(users, { + fields: [menuTreeNodes.manager2Id], + references: [users.id], + relationName: "menuManager2", + }), +})); + +// Type exports +export type MenuTreeNode = typeof menuTreeNodes.$inferSelect; +export type NewMenuTreeNode = typeof menuTreeNodes.$inferInsert; +export type NodeType = (typeof menuTreeNodeTypeEnum.enumValues)[number]; +export type MenuDomain = (typeof menuDomainEnum.enumValues)[number]; + |
