From 8d2da0ee06c9a626a1f0cca55884c0b8eff453a1 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev <572431+veikab@users.noreply.github.com> Date: Sun, 7 Jun 2026 10:43:12 +0700 Subject: [PATCH] Add demo seed command --- package.json | 3 +- scripts/seed-demo.ts | 167 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 scripts/seed-demo.ts diff --git a/package.json b/package.json index 17d30bb..73cf43c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "tsx watch src/index.ts", "build": "prisma generate && tsc", - "start": "prisma migrate deploy && node dist/index.js" + "start": "prisma migrate deploy && node dist/index.js", + "seed:demo": "tsx scripts/seed-demo.ts" }, "dependencies": { "@fastify/cors": "^11.2.0", diff --git a/scripts/seed-demo.ts b/scripts/seed-demo.ts new file mode 100644 index 0000000..0d81421 --- /dev/null +++ b/scripts/seed-demo.ts @@ -0,0 +1,167 @@ +import { Prisma } from '@prisma/client' +import { prisma } from '../src/db.js' + +const DEMO_TEAM_UUID = process.env.DEMO_TEAM_UUID ?? '11111111-1111-4111-8111-111111111111' +const DEMO_ORDER_COUNT = Number(process.env.DEMO_ORDER_COUNT ?? '120') + +function requiredEnv(name: string): string { + const value = process.env[name]?.trim() + if (!value) throw new Error(`${name} is required`) + return value +} + +function location(index: number, side: 'source' | 'destination') { + const source = { + uuid: `11111111-2222-4${String(index).padStart(3, '0').slice(-3)}-8${String(index).padStart(3, '0').slice(-3)}-111111${String(index).padStart(6, '0')}`, + name: `Demo address ${index + 1}`, + countryCode: 'KZ', + latitude: 43.238949 + Math.floor(index / 60) * 0.018 + (index % 5) * 0.002, + longitude: 76.889709 + (index % 60) * 0.021 + (Math.floor(index / 60) % 5) * 0.002, + } + const destination = { + uuid: `22222222-3333-4${String(index).padStart(3, '0').slice(-3)}-8${String(index).padStart(3, '0').slice(-3)}-222222${String(index).padStart(6, '0')}`, + name: `Client destination ${index + 1}`, + countryCode: index % 2 === 0 ? 'RU' : 'CN', + latitude: index % 2 === 0 ? 55.755826 + (index % 10) * 0.01 : 43.825592 + (index % 10) * 0.012, + longitude: index % 2 === 0 ? 37.6173 + (index % 10) * 0.01 : 87.616848 + (index % 10) * 0.012, + } + return side === 'source' ? source : destination +} + +const userId = requiredEnv('DEMO_LOGTO_USER_ID') + +const tariffs = [ + { + uuid: '11111111-aaaa-4111-8111-111111111111', + name: 'Demo auto tariff KZ-RU', + sourceCountryCode: 'KZ', + destinationCountryCode: 'RU', + transportTypeCode: 'AUTO', + amountUsd: new Prisma.Decimal(1800), + minPriceUsd: new Prisma.Decimal(1200), + etaDays: 7, + priority: 10, + }, + { + uuid: '11111111-aaaa-4111-8111-222222222222', + name: 'Demo rail tariff KZ-CN', + sourceCountryCode: 'KZ', + destinationCountryCode: 'CN', + transportTypeCode: 'RAIL', + amountUsd: new Prisma.Decimal(2400), + minPriceUsd: new Prisma.Decimal(1600), + etaDays: 10, + priority: 20, + }, +] + +for (const tariff of tariffs) { + await prisma.tariffReference.upsert({ + where: { uuid: tariff.uuid }, + create: { + ...tariff, + teamUuid: DEMO_TEAM_UUID, + createdByUserId: userId, + status: 'active', + currency: 'USD', + notes: 'Demo seed tariff', + }, + update: { + ...tariff, + teamUuid: DEMO_TEAM_UUID, + createdByUserId: userId, + status: 'active', + currency: 'USD', + notes: 'Demo seed tariff', + }, + }) +} + +for (let index = 0; index < DEMO_ORDER_COUNT; index += 1) { + const source = location(index, 'source') + const destination = location(index, 'destination') + const tariff = tariffs[index % tariffs.length] + const totalAmount = new Prisma.Decimal(1500 + (index % 17) * 125) + const quotationUuid = `33333333-4444-4${String(index).padStart(3, '0').slice(-3)}-8${String(index).padStart(3, '0').slice(-3)}-333333${String(index).padStart(6, '0')}` + const orderUuid = `44444444-5555-4${String(index).padStart(3, '0').slice(-3)}-8${String(index).padStart(3, '0').slice(-3)}-444444${String(index).padStart(6, '0')}` + const selectedTariff = await prisma.tariffReference.findUniqueOrThrow({ where: { uuid: tariff.uuid } }) + + const quotation = await prisma.quotation.upsert({ + where: { uuid: quotationUuid }, + create: { + uuid: quotationUuid, + teamUuid: DEMO_TEAM_UUID, + createdByUserId: userId, + title: `Demo quotation ${index + 1}`, + status: 'converted', + operationCode: 'IMPORT', + incotermsCode: index % 2 === 0 ? 'DAP' : 'FOB', + transportTypeCode: tariff.transportTypeCode, + sourceCountryCode: source.countryCode, + sourceLocationUuid: source.uuid, + sourceLocationName: source.name, + sourceLatitude: source.latitude, + sourceLongitude: source.longitude, + destinationCountryCode: destination.countryCode, + destinationLocationUuid: destination.uuid, + destinationLocationName: destination.name, + destinationLatitude: destination.latitude, + destinationLongitude: destination.longitude, + grossWeightKg: new Prisma.Decimal(18000 + index * 25), + volumeCbm: new Prisma.Decimal(70 + (index % 9) * 3), + unitsCount: 1 + (index % 4), + routeDistanceKm: 2800 + index * 11, + selectedTariffId: selectedTariff.id, + totalAmount, + currency: 'USD', + etaDays: selectedTariff.etaDays, + notes: 'Demo seed quotation', + }, + update: { + teamUuid: DEMO_TEAM_UUID, + createdByUserId: userId, + status: 'converted', + selectedTariffId: selectedTariff.id, + totalAmount, + currency: 'USD', + }, + }) + + await prisma.order.upsert({ + where: { uuid: orderUuid }, + create: { + uuid: orderUuid, + teamUuid: DEMO_TEAM_UUID, + quotationId: quotation.id, + createdByUserId: userId, + name: `Demo order ${index + 1}`, + status: index % 5 === 0 ? 'in_transit' : 'created', + totalAmount, + currency: 'USD', + sourceLocationUuid: source.uuid, + sourceLocationName: source.name, + sourceCountryCode: source.countryCode, + sourceLatitude: source.latitude, + sourceLongitude: source.longitude, + destinationLocationUuid: destination.uuid, + destinationLocationName: destination.name, + destinationCountryCode: destination.countryCode, + destinationLatitude: destination.latitude, + destinationLongitude: destination.longitude, + etaDays: selectedTariff.etaDays, + notes: 'Demo seed order', + }, + update: { + teamUuid: DEMO_TEAM_UUID, + quotationId: quotation.id, + createdByUserId: userId, + status: index % 5 === 0 ? 'in_transit' : 'created', + totalAmount, + currency: 'USD', + }, + }) +} + +console.log(`Seeded orders demo data for ${userId}: team ${DEMO_TEAM_UUID}, orders ${DEMO_ORDER_COUNT}`) + +await prisma.$disconnect()