summaryrefslogtreecommitdiff
path: root/db/schema/vendorData.ts
diff options
context:
space:
mode:
Diffstat (limited to 'db/schema/vendorData.ts')
-rw-r--r--db/schema/vendorData.ts228
1 files changed, 138 insertions, 90 deletions
diff --git a/db/schema/vendorData.ts b/db/schema/vendorData.ts
index 03248fb8..36810e50 100644
--- a/db/schema/vendorData.ts
+++ b/db/schema/vendorData.ts
@@ -3,10 +3,21 @@ import {
text,
varchar,
timestamp,
- integer, numeric, date, unique, serial, jsonb, uniqueIndex
+ integer,
+ unique,
+ serial,
+ jsonb,
+ uniqueIndex,
+ primaryKey,
+ foreignKey,
+ pgView
} from "drizzle-orm/pg-core"
+import { and, eq} from "drizzle-orm";
+
import { contractItems } from "./contract"
+import { projects } from "./projects" // projects 테이블 임포트 가정
+// 기존 테이블들은 그대로 유지
export const forms = pgTable("forms", {
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
contractItemId: integer("contract_item_id")
@@ -14,13 +25,10 @@ export const forms = pgTable("forms", {
.references(() => contractItems.id, { onDelete: "cascade" }),
formCode: varchar("form_code", { length: 100 }).notNull(),
formName: varchar("form_name", { length: 255 }).notNull(),
- // tagType: varchar("tag_type", { length: 50 }).notNull(),
- // class: varchar("class", { length: 100 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
}, (table) => {
return {
- // contractItemId와 formCode의 조합을 유니크하게 설정
contractItemFormCodeUnique: uniqueIndex("contract_item_form_code_unique").on(
table.contractItemId,
table.formCode
@@ -28,25 +36,25 @@ export const forms = pgTable("forms", {
}
})
-export const formTemplates = pgTable("form_templates", {
- id: serial("id").primaryKey(),
- formId: integer("form_id").references(() => forms.id),
- fileName: varchar("file_name", { length: 255 }).notNull(),
- filePath: varchar("file_path", { length: 1024 }).notNull(),
-
- createdAt: timestamp("created_at").defaultNow().notNull(),
- udpatedAt: timestamp("updated_at").defaultNow().notNull(),
-
-});
-
-
+// formMetas에 projectId 추가
export const formMetas = pgTable("form_metas", {
id: serial("id").primaryKey(),
+ projectId: integer("project_id")
+ .notNull()
+ .references(() => projects.id, { onDelete: "cascade" }),
formCode: varchar("form_code", { length: 50 }).notNull(),
formName: varchar("form_name", { length: 255 }).notNull(),
columns: jsonb("columns").notNull(),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
+}, (table) => {
+ return {
+ // formCode는 프로젝트 내에서만 유니크하면 됨
+ formCodeProjectUnique: unique("form_code_project_unique").on(
+ table.projectId,
+ table.formCode
+ )
+ }
})
export const formEntries = pgTable("form_entries", {
@@ -60,148 +68,188 @@ export const formEntries = pgTable("form_entries", {
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
})
-
-// ============ tags (각 계약 아이템에 대한 Tag) ============
-// "어느 계약의 어느 아이템에 대한 태그"임을 나타내려면 contract_items를 참조
export const tags = pgTable("tags", {
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
-
- // 이 Tag가 속한 "계약 내 아이템" (즉 contract_items.id)
contractItemId: integer("contract_item_id")
.notNull()
.references(() => contractItems.id, { onDelete: "cascade" }),
-
formId: integer("form_id")
.references(() => forms.id, { onDelete: "set null" }),
-
tagNo: varchar("tag_no", { length: 100 }).notNull(),
tagType: varchar("tag_type", { length: 50 }).notNull(),
class: varchar("class", { length: 100 }).notNull(),
description: text("description"),
-
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
})
-export type Tag = typeof tags.$inferSelect
-export type Form = typeof forms.$inferSelect
-export type NewTag = typeof tags.$inferInsert
-
+// tagTypes에 projectId 추가 및 복합 기본키 생성
export const tagTypes = pgTable("tag_types", {
- code: varchar("code", { length: 50 }).primaryKey(),
+ code: varchar("code", { length: 50 }).notNull(),
+ projectId: integer("project_id")
+ .notNull()
+ .references(() => projects.id, { onDelete: "cascade" }),
description: text("description").notNull(),
-
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
+}, (table) => {
+ return {
+ // code는 더 이상 단독 PK가 아니고, projectId와 함께 복합 PK 구성
+ pk: primaryKey({ columns: [table.code, table.projectId] })
+ }
})
+// tagSubfields에 projectId 추가 및 FK/유니크 제약 업데이트
export const tagSubfields = pgTable("tag_subfields", {
id: serial("id").primaryKey(),
-
- // 외래키: tagTypeCode -> tagTypes.code
- tagTypeCode: varchar("tag_type_code", { length: 50 })
+ projectId: integer("project_id")
.notNull()
- .references(() => tagTypes.code, { onDelete: "cascade" }),
-
- /**
- * 나머지 필드
- */
- // tagTypeDescription: -> 이제 불필요. tagTypes.description로 join
+ .references(() => projects.id, { onDelete: "cascade" }),
+ tagTypeCode: varchar("tag_type_code", { length: 50 }).notNull(),
attributesId: varchar("attributes_id", { length: 50 }).notNull(),
attributesDescription: text("attributes_description").notNull(),
-
expression: text("expression"),
delimiter: varchar("delimiter", { length: 10 }),
-
sortOrder: integer("sort_order").default(0).notNull(),
-
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
}, (table) => {
return {
+ // 유니크 제약은 이제 projectId를 포함
uniqTagTypeAttribute: unique("uniq_tag_type_attribute").on(
+ table.projectId,
table.tagTypeCode,
table.attributesId
),
+ // tagTypes 참조를 위한 복합 FK (tagTypeCode, projectId)
+ tagTypeRef: foreignKey({
+ columns: [table.tagTypeCode, table.projectId],
+ foreignColumns: [tagTypes.code, tagTypes.projectId]
+ }).onDelete("cascade")
};
});
+// tagSubfieldOptions에 projectId 추가 및 FK/유니크 제약 업데이트
export const tagSubfieldOptions = pgTable("tag_subfield_options", {
id: serial("id").primaryKey(),
-
- // 어떤 subfield에 속하는 옵션인지
- attributesId: varchar("attributes_id", { length: 50 })
+ projectId: integer("project_id")
.notNull()
- .references(() => tagSubfields.attributesId, { onDelete: "cascade" }),
-
- /**
- * 실제 코드 (예: "PM", "AA", "VB", "VAR", "01", "02" ...)
- */
+ .references(() => projects.id, { onDelete: "cascade" }),
+ attributesId: varchar("attributes_id", { length: 50 }).notNull(),
code: varchar("code", { length: 50 }).notNull(),
-
- /**
- * 사용자에게 보여줄 레이블 (예: "Pump", "Pneumatic Motor", "Ball Valve", ...)
- */
label: text("label").notNull(),
-
- /**
- * 생성/수정 시각 (선택)
- */
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
+}, (table) => {
+ return {
+ // 코드는 projectId + attributesId 조합 내에서 유니크해야 함
+ uniqAttributeProjectCode: unique("uniq_attribute_project_code").on(
+ table.projectId,
+ table.attributesId,
+ table.code
+ ),
+ // tagSubfields 참조를 위한 복합 FK
+ // attributesId만으로는 더 이상 유니크하지 않으므로 projectId도 함께 참조
+ attributesRef: foreignKey({
+ columns: [table.attributesId, table.projectId],
+ // tagSubfields의 attributesId + projectId 참조
+ foreignColumns: [tagSubfields.attributesId, tagSubfields.projectId]
+ }).onDelete("cascade")
+ };
})
+// tagClasses에 projectId 추가 및 FK 업데이트
export const tagClasses = pgTable("tag_classes", {
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
-
- // 기존 code/label
+ projectId: integer("project_id")
+ .notNull()
+ .references(() => projects.id, { onDelete: "cascade" }),
code: varchar("code", { length: 100 }).notNull(),
label: text("label").notNull(),
-
- // 새 필드: tagTypeCode -> references tagTypes.code
- tagTypeCode: varchar("tag_type_code", { length: 50 })
- .notNull()
- .references(() => tagTypes.code, { onDelete: "cascade" }),
-
+ tagTypeCode: varchar("tag_type_code", { length: 50 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
+}, (table) => {
+ return {
+ // 코드는 프로젝트 내에서 유니크해야 함
+ uniqCodeInProject: unique("uniq_code_in_project").on(
+ table.projectId,
+ table.code
+ ),
+ // tagTypes 참조를 위한 복합 FK
+ tagTypeRef: foreignKey({
+ columns: [table.tagTypeCode, table.projectId],
+ foreignColumns: [tagTypes.code, tagTypes.projectId]
+ }).onDelete("cascade")
+ };
})
+// tagTypeClassFormMappings에 projectId 추가
export const tagTypeClassFormMappings = pgTable("tag_type_class_form_mappings", {
id: serial("id").primaryKey(),
-
+ projectId: integer("project_id")
+ .notNull()
+ .references(() => projects.id, { onDelete: "cascade" }),
tagTypeLabel: varchar("tag_type_label", { length: 255 }).notNull(),
classLabel: varchar("class_label", { length: 255 }).notNull(),
-
formCode: varchar("form_code", { length: 50 }).notNull(),
formName: varchar("form_name", { length: 255 }).notNull(),
-
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
+}, (table) => {
+ return {
+ // 매핑은 프로젝트 내에서 유니크해야 함
+ uniqMappingInProject: unique("uniq_mapping_in_project").on(
+ table.projectId,
+ table.tagTypeLabel,
+ table.classLabel,
+ table.formCode
+ )
+ };
})
+// view_tag_subfields에도 projectId 추가
+export const viewTagSubfields = pgView("view_tag_subfields").as((qb) => {
+ return qb
+ .select({
+ // id: tagSubfields.id,
+ // projectId: tagSubfields.projectId,
+ tagTypeCode: tagSubfields.tagTypeCode,
+ tagTypeDescription: tagTypes.description,
+ attributesId: tagSubfields.attributesId,
+ attributesDescription: tagSubfields.attributesDescription,
+ expression: tagSubfields.expression,
+ delimiter: tagSubfields.delimiter,
+ sortOrder: tagSubfields.sortOrder,
+ createdAt: tagSubfields.createdAt,
+ updatedAt: tagSubfields.updatedAt,
+ // 프로젝트 관련 정보 추가
+ projectId: projects.id,
+ projectCode: projects.code,
+ projectName: projects.name
+ })
+ .from(tagSubfields)
+ .innerJoin(
+ tagTypes,
+ and(
+ eq(tagSubfields.tagTypeCode, tagTypes.code),
+ eq(tagSubfields.projectId, tagTypes.projectId)
+ )
+ )
+ .innerJoin(
+ projects,
+ eq(tagSubfields.projectId, projects.id)
+ )
+ });
+
+// 타입 정의 업데이트
+export type Tag = typeof tags.$inferSelect
+export type Form = typeof forms.$inferSelect
+export type NewTag = typeof tags.$inferInsert
export type TagTypeClassFormMappings = typeof tagTypeClassFormMappings.$inferSelect
export type TagSubfields = typeof tagSubfields.$inferSelect
export type TagSubfieldOption = typeof tagSubfieldOptions.$inferSelect
export type TagClasses = typeof tagClasses.$inferSelect
-
-
-export const viewTagSubfields = pgTable("view_tag_subfields", {
- id: integer("id").primaryKey(),
-
- tagTypeCode: varchar("tag_type_code", { length: 50 }).notNull(),
- tagTypeDescription: text("tag_type_description"),
- attributesId: varchar("attributes_id", { length: 50 }).notNull(),
- attributesDescription: text("attributes_description").notNull(),
-
- expression: text("expression"),
- delimiter: varchar("delimiter", { length: 10 }),
- sortOrder: integer("sort_order").default(0).notNull(),
-
- createdAt: timestamp("created_at", { withTimezone: true }),
- updatedAt: timestamp("updated_at", { withTimezone: true }),
-})
-
export type ViewTagSubfields = typeof viewTagSubfields.$inferSelect
export const vendorDataReportTemps = pgTable("vendor_data_report_temps", {
@@ -217,9 +265,9 @@ export const vendorDataReportTemps = pgTable("vendor_data_report_temps", {
createdAt: timestamp("created_at", { withTimezone: true })
.defaultNow()
.notNull(),
- updatedAt: timestamp("updated_at", { withTimezone: true })
+ updatedAt: timestamp("updated_at", { withTimezone: true })
.defaultNow()
.notNull(),
- });
+});
- export type VendorDataReportTemps = typeof vendorDataReportTemps.$inferSelect; \ No newline at end of file
+export type VendorDataReportTemps = typeof vendorDataReportTemps.$inferSelect; \ No newline at end of file