diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-20 11:37:31 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-20 11:37:31 +0000 |
| commit | aa86729f9a2ab95346a2851e3837de1c367aae17 (patch) | |
| tree | b601b18b6724f2fb449c7fa9ea50cbd652a8077d /db/schema/techSales.ts | |
| parent | 95bbe9c583ff841220da1267630e7b2025fc36dc (diff) | |
(대표님) 20250620 작업사항
Diffstat (limited to 'db/schema/techSales.ts')
| -rw-r--r-- | db/schema/techSales.ts | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/db/schema/techSales.ts b/db/schema/techSales.ts index 334bf6bb..744d22cc 100644 --- a/db/schema/techSales.ts +++ b/db/schema/techSales.ts @@ -34,6 +34,8 @@ import { integer, numeric, date, + json, + index, } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; import { biddingProjects } from "./projects"; @@ -60,6 +62,7 @@ export const TECH_SALES_QUOTATION_STATUSES = { SUBMITTED: "Submitted", REVISED: "Revised", ACCEPTED: "Accepted", + REJECTED: "Rejected", } as const; export type TechSalesQuotationStatus = typeof TECH_SALES_QUOTATION_STATUSES[keyof typeof TECH_SALES_QUOTATION_STATUSES]; @@ -90,6 +93,12 @@ export const TECH_SALES_QUOTATION_STATUS_CONFIG = { description: "승인된 견적서", color: "text-green-600", }, + [TECH_SALES_QUOTATION_STATUSES.REJECTED]: { + label: "거절됨", + variant: "destructive" as const, + description: "거절된 견적서", + color: "text-red-600", + }, } as const; // ===== 스키마 정의 ===== @@ -241,6 +250,37 @@ export const techSalesVendorQuotations = pgTable( } ); +// 기술영업 벤더 견적서 revision 히스토리 테이블 (이전 버전 스냅샷 저장) +export const techSalesVendorQuotationRevisions = pgTable( + "tech_sales_vendor_quotation_revisions", + { + id: serial("id").primaryKey(), + quotationId: integer("quotation_id") + .notNull() + .references(() => techSalesVendorQuotations.id, { onDelete: "cascade" }), + + // 버전 정보 + version: integer("version").notNull(), + + // 이전 데이터 JSON 스냅샷 + snapshot: json("snapshot").notNull(), + + // 변경 사유 + changeReason: text("change_reason"), + revisionNote: text("revision_note"), + + // 변경자 정보 + revisedBy: integer("revised_by"), + revisedAt: timestamp("revised_at").defaultNow().notNull(), + }, + (table) => ({ + quotationVersionIdx: index("tech_sales_quotation_revisions_quotation_version_idx").on( + table.quotationId, + table.version + ), + }) +); + export const techSalesRfqComments = pgTable( "tech_sales_rfq_comments", { @@ -299,6 +339,28 @@ export const techSalesRfqCommentAttachments = pgTable("tech_sales_rfq_comment_at uploadedAt: timestamp("uploaded_at").defaultNow().notNull(), }); +// 기술영업 벤더 견적서 첨부파일 테이블 +export const techSalesVendorQuotationAttachments = pgTable("tech_sales_vendor_quotation_attachments", { + id: serial("id").primaryKey(), + quotationId: integer("quotation_id") + .notNull() + .references(() => techSalesVendorQuotations.id, { onDelete: "cascade" }), + fileName: varchar("file_name", { length: 255 }).notNull(), + originalFileName: varchar("original_file_name", { length: 255 }).notNull(), + fileSize: integer("file_size").notNull(), + fileType: varchar("file_type", { length: 100 }), + filePath: varchar("file_path", { length: 500 }).notNull(), + description: text("description"), // 파일 설명 + uploadedBy: integer("uploaded_by").references(() => users.id, { + onDelete: "set null", + }), + vendorId: integer("vendor_id").references(() => techVendors.id, { + onDelete: "set null", + }), + isVendorUpload: boolean("is_vendor_upload").default(true), // 벤더가 업로드한 파일인지 + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at").defaultNow().notNull(), +}); // 타입 정의 export type TechSalesVendorQuotations = @@ -390,6 +452,7 @@ export const techSalesVendorQuotationsRelations = relations(techSalesVendorQuota // 첨부파일 관계 attachments: many(techSalesRfqCommentAttachments), + quotationAttachments: many(techSalesVendorQuotationAttachments), })); export const techSalesAttachmentsRelations = relations(techSalesAttachments, ({ one }) => ({ @@ -474,4 +537,26 @@ export const techSalesRfqCommentAttachmentsRelations = relations(techSalesRfqCom fields: [techSalesRfqCommentAttachments.vendorId], references: [techVendors.id], }), +})); + +// 기술영업 벤더 견적서 첨부파일 relations +export const techSalesVendorQuotationAttachmentsRelations = relations(techSalesVendorQuotationAttachments, ({ one }) => ({ + // 견적서 관계 + quotation: one(techSalesVendorQuotations, { + fields: [techSalesVendorQuotationAttachments.quotationId], + references: [techSalesVendorQuotations.id], + }), + + // 업로드한 사용자 관계 + uploadedByUser: one(users, { + fields: [techSalesVendorQuotationAttachments.uploadedBy], + references: [users.id], + relationName: "techSalesQuotationAttachmentUploadedBy", + }), + + // 벤더 관계 + vendor: one(techVendors, { + fields: [techSalesVendorQuotationAttachments.vendorId], + references: [techVendors.id], + }), }));
\ No newline at end of file |
