Files
tehran_taj/apps/api/scripts/seed-mock-orders.ts
T

200 lines
6.4 KiB
TypeScript
Raw Normal View History

/**
* Dev helper: seed >15 mock orders per OrderStatus so the Orders UI can be inspected.
* Run: npx tsx scripts/seed-mock-orders.ts
*/
import {
OrderChannel,
OrderStatus,
Prisma,
PrismaClient,
} from '@prisma/client'
const prisma = new PrismaClient()
const STATUSES: OrderStatus[] = [
OrderStatus.SUSPENDED,
OrderStatus.PLACED,
OrderStatus.ADMIN_APPROVED,
OrderStatus.SOURCING,
OrderStatus.PREPARING,
OrderStatus.DELIVERED_TO_AGENT,
OrderStatus.DELIVERED_TO_CUSTOMER,
OrderStatus.CANCELLED,
]
const PER_STATUS = 18
const TAG = 'MOCK-ORD'
function d(n: number | string) {
return new Prisma.Decimal(n)
}
function orderNumber(status: OrderStatus, i: number) {
// Unique, easy to spot/delete later
return `${TAG}-${status.slice(0, 4)}-${String(i).padStart(3, '0')}-${Date.now().toString(36)}`
}
async function main() {
const mobileOverride = process.env.MOCK_ORDERS_MOBILE?.trim()
const customer = mobileOverride
? await prisma.customer.findUnique({
where: { mobile: mobileOverride },
select: { id: true, mobile: true, fullName: true, referredByAgentId: true },
})
: await prisma.customer.findFirst({
orderBy: { updatedAt: 'desc' },
select: { id: true, mobile: true, fullName: true, referredByAgentId: true },
})
if (!customer) {
throw new Error(
mobileOverride
? `No customer with mobile=${mobileOverride}`
: 'No customers in DB — create/login a customer first',
)
}
const variants = await prisma.productVariant.findMany({
take: 30,
where: { isActive: true },
include: { product: { select: { title: true } } },
})
if (variants.length === 0) {
throw new Error('No product variants in DB — seed catalog first')
}
const branch = await prisma.branch.findFirst({ select: { id: true, name: true } })
console.log(
`Seeding ${PER_STATUS} orders × ${STATUSES.length} statuses for customer ${customer.mobile} (${customer.fullName}), ${variants.length} variants` +
(branch ? `, branch=${branch.name}` : ''),
)
let created = 0
for (const status of STATUSES) {
for (let i = 1; i <= PER_STATUS; i++) {
const variant = variants[i % variants.length]!
const qty = 1 + (i % 3)
const rash = Number(variant.rashWeightGrams ?? 1.25)
const wagePct = Number(variant.defaultWagePercent ?? 7)
const discountPct = 0
const computed = rash * (1 + (wagePct - discountPct) / 100)
const totalGold = computed * qty
const wageWeight = totalGold - rash * qty
const flatRial = i % 4 === 0 ? 150_000 * i : 0
const daysAgo = (STATUSES.indexOf(status) * PER_STATUS + i) % 40
const createdAt = new Date(Date.now() - daysAgo * 24 * 60 * 60 * 1000 - i * 60_000)
const deliveredAt =
status === OrderStatus.DELIVERED_TO_CUSTOMER
? new Date(createdAt.getTime() + 2 * 24 * 60 * 60 * 1000)
: null
// 1–2 line items so list/detail both look realistic
const second = variants[(i + 3) % variants.length]!
const useSecond = i % 3 === 0
const order = await prisma.order.create({
data: {
orderNumber: orderNumber(status, i),
customerId: customer.id,
branchId: branch?.id ?? null,
channel: i % 5 === 0 ? OrderChannel.WHOLESALE : OrderChannel.RETAIL,
status,
totalGoldWeightGrams: d(
(useSecond
? totalGold + Number(second.rashWeightGrams) * (1 + Number(second.defaultWagePercent) / 100)
: totalGold
).toFixed(4),
),
wageWeightGrams: d(Math.max(0, wageWeight).toFixed(4)),
flatRialCharge: d(flatRial),
isSuspendedOverCreditLimit: status === OrderStatus.SUSPENDED,
deliveredAt,
salesAgentId: customer.referredByAgentId ?? null,
createdAt,
updatedAt: createdAt,
items: {
create: [
{
productVariantId: variant.id,
quantity: qty,
rashWeightGramsSnapshot: d(rash.toFixed(4)),
wagePercentSnapshot: d(wagePct.toFixed(3)),
discountPercentSnapshot: d(discountPct.toFixed(3)),
computedWeightGrams: d(computed.toFixed(4)),
flatRialCharge: d(flatRial),
},
...(useSecond
? [
{
productVariantId: second.id,
quantity: 1,
rashWeightGramsSnapshot: d(Number(second.rashWeightGrams).toFixed(4)),
wagePercentSnapshot: d(Number(second.defaultWagePercent).toFixed(3)),
discountPercentSnapshot: d(0),
computedWeightGrams: d(
(
Number(second.rashWeightGrams) *
(1 + Number(second.defaultWagePercent) / 100)
).toFixed(4),
),
flatRialCharge: d(0),
},
]
: []),
],
},
statusEvents: {
create: [
{
fromStatus: null,
toStatus: OrderStatus.PLACED,
note: 'mock seed: placed',
createdAt,
},
...(status !== OrderStatus.PLACED
? [
{
fromStatus: OrderStatus.PLACED,
toStatus: status,
note: `mock seed: set to ${status}`,
createdAt: new Date(createdAt.getTime() + 60_000),
},
]
: []),
],
},
},
})
created++
if (i === 1) {
console.log(` ${status}: first=${order.orderNumber}`)
}
}
console.log(` ${status}: +${PER_STATUS}`)
}
const counts = await prisma.order.groupBy({
by: ['status'],
_count: { _all: true },
where: { orderNumber: { startsWith: TAG } },
})
console.log(`Done. Created ${created} mock orders (tag ${TAG}).`)
console.log(
'Mock counts:',
Object.fromEntries(counts.map((c) => [c.status, c._count._all])),
)
console.log(`Login as mobile ${customer.mobile} to see them in the app.`)
}
main()
.catch((e) => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})