diff options
| author | joonhoekim <26rote@gmail.com> | 2025-12-04 21:05:28 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-12-04 21:05:28 +0900 |
| commit | e5b36fa6a1b12446883f51fc5e7cd56d8df8d8f5 (patch) | |
| tree | c8f9fb50eb593dd5322d26d9276947c155997858 /db/schema/menu-v2.ts | |
| parent | 240f4f31b3b6ff6a46436978fb988588a1972721 (diff) | |
| parent | 04ed774ff60a83c00711d4e8615cb4122954dba5 (diff) | |
Merge branch 'jh-auth-menu' into dujinkim
Diffstat (limited to 'db/schema/menu-v2.ts')
| -rw-r--r-- | db/schema/menu-v2.ts | 88 |
1 files changed, 88 insertions, 0 deletions
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]; + |
