summaryrefslogtreecommitdiff
path: root/db/seeds/rfqSeed.ts
diff options
context:
space:
mode:
Diffstat (limited to 'db/seeds/rfqSeed.ts')
-rw-r--r--db/seeds/rfqSeed.ts147
1 files changed, 147 insertions, 0 deletions
diff --git a/db/seeds/rfqSeed.ts b/db/seeds/rfqSeed.ts
new file mode 100644
index 00000000..2d37393d
--- /dev/null
+++ b/db/seeds/rfqSeed.ts
@@ -0,0 +1,147 @@
+// db/seed/rfqSeed.ts
+import { faker } from "@faker-js/faker";
+import db from "@/db/db"
+import { eq, inArray } from "drizzle-orm";
+
+// 스키마 import
+import {
+ rfqs, rfqItems, rfqVendors, vendorQuotes, rfqAttachments, rfqComments, rfqEvaluations,
+ Rfq, RfqItem, RfqVendor, VendorQuote, RfqAttach, RfqComment, RfqEvaluation
+} from "../schema/rfq";
+import { vendors } from "../schema/vendors";
+
+export async function seedRfqData() {
+ // 1) 기존 데이터 삭제 (참조 순서 유의)
+ await db.delete(rfqEvaluations);
+ await db.delete(rfqComments);
+ await db.delete(rfqAttachments);
+ await db.delete(vendorQuotes);
+ await db.delete(rfqVendors);
+ await db.delete(rfqItems);
+ await db.delete(rfqs);
+
+ // (벤더 목록이 이미 존재한다고 가정)
+ // 혹은 필요한 경우 vendors도 시드할 수 있음
+ const existingVendors = await db.select().from(vendors);
+ if (existingVendors.length === 0) {
+ console.log("No vendors found. Please seed vendors first.");
+ return;
+ }
+
+ // 2) N개의 RFQ 생성
+ const rfqCount = 5;
+ const rfqIds: number[] = [];
+
+ for (let i = 0; i < rfqCount; i++) {
+ const newRfqData = {
+ rfqCode: `RFQ-${faker.string.alpha({ length: 4 }).toUpperCase()}-${faker.number.int({
+ min: 100,
+ max: 999,
+ })}`,
+ projectCode: `PRJ-${faker.number.int({ min: 1000, max: 9999 })}`,
+ projectName: faker.company.name(),
+ dueDate: faker.date.future(), // 임의 미래 날짜
+ status: faker.helpers.arrayElement(["DRAFT", "PUBLISHED", "EVALUATION", "AWARDED"]),
+ createdBy: faker.number.int({ min: 1, max: 10 }),
+ };
+
+ const [insertedRfq] = await db.insert(rfqs).values(newRfqData).returning();
+ rfqIds.push(insertedRfq.id);
+ }
+
+ // 3) For each RFQ, create items, vendors, quotes, attachments, comments, evaluations
+ for (const rfqId of rfqIds) {
+ // 3-1) RFQ Items
+ const itemCount = faker.number.int({ min: 1, max: 3 });
+ const rfqItemIds: number[] = [];
+ for (let j = 0; j < itemCount; j++) {
+ const newItem = {
+ rfqId,
+ itemCode: `ITEM-${faker.string.alphanumeric({ length: 5 }).toUpperCase()}`,
+ itemName: faker.commerce.productName(),
+ description: faker.commerce.productDescription(),
+ quantity: faker.number.float({ min: 1, max: 20, fractionDigits: 2 }),
+ uom: faker.helpers.arrayElement(["EA", "KG", "BOX"]),
+ };
+ const [insertedItem] = await db.insert(rfqItems).values(newItem).returning();
+ rfqItemIds.push(insertedItem.id);
+ }
+
+ // 3-2) RFQ Vendors
+ // - 랜덤으로 2~3개 벤더를 pick
+ const pickedVendors = faker.helpers.arrayElements(existingVendors, faker.number.int({ min: 2, max: 3 }));
+ for (const ven of pickedVendors) {
+ const newRfqVendor = {
+ rfqId,
+ vendorId: ven.id,
+ status: faker.helpers.arrayElement(["INVITED", "ACCEPTED", "REJECTED", "QUOTED"]),
+ };
+ const [insertedRfqVendor] = await db.insert(rfqVendors).values(newRfqVendor).returning();
+
+ // 3-3) 임의로 벤더 Quotes 생성 (50% 확률)
+ if (faker.datatype.boolean()) {
+ const newQuote = {
+ rfqId,
+ vendorId: ven.id,
+ totalAmount: faker.number.float({ min: 1000, max: 50000, fractionDigits: 2 }),
+ currency: faker.helpers.arrayElement(["USD", "EUR", "KRW"]),
+ leadTime: `${faker.number.int({ min: 10, max: 40 })} days`,
+ notes: faker.lorem.sentence(),
+ };
+ await db.insert(vendorQuotes).values(newQuote);
+ }
+ }
+
+ // 3-4) Attachments (랜덤 0~2개)
+ const attachCount = faker.number.int({ min: 0, max: 2 });
+ for (let a = 0; a < attachCount; a++) {
+ const newAttach = {
+ rfqId,
+ vendorId: null, // or pick some vendorId
+ fileName: faker.system.fileName(),
+ filePath: faker.system.filePath(),
+ // evaluationId: null,
+ };
+ await db.insert(rfqAttachments).values(newAttach);
+ }
+
+ // 3-5) Comments (랜덤 1~2개)
+ const commentCount = faker.number.int({ min: 1, max: 2 });
+ for (let c = 0; c < commentCount; c++) {
+ const newComment = {
+ rfqId,
+ vendorId: null,
+ commentText: faker.lorem.sentence(),
+ commentedBy: faker.number.int({ min: 1, max: 10 }),
+ // evaluationId: null,
+ };
+ await db.insert(rfqComments).values(newComment);
+ }
+
+ // 3-6) Evaluations (랜덤 0~1개)
+ if (faker.datatype.boolean()) {
+ const newEval = {
+ rfqId,
+ vendorId: faker.helpers.arrayElement(pickedVendors).id,
+ evalType: faker.helpers.arrayElement(["TBE", "CBE"]),
+ result: faker.helpers.arrayElement(["PASS", "FAIL", "ACCEPTABLE"]),
+ notes: faker.lorem.sentences(2),
+ };
+ await db.insert(rfqEvaluations).values(newEval);
+ }
+ }
+
+ console.log(`✅ Seeded ${rfqIds.length} RFQs (with items, vendors, quotes, attachments, comments, evaluations).`);
+}
+
+if (require.main === module) {
+ seedRfqData()
+ .then(() => {
+ console.log("RFQ seeding complete!");
+ process.exit(0);
+ })
+ .catch((err) => {
+ console.error("RFQ seeding failed:", err);
+ process.exit(1);
+ });
+} \ No newline at end of file