565 lines
21 KiB
TypeScript
565 lines
21 KiB
TypeScript
/**
|
||
* SPEC SEED-31: Seed test data for purchases workflow visual testing
|
||
* Run: npx tsx tests/seed-test-data.ts
|
||
* Idempotent: safe to run multiple times
|
||
*/
|
||
import { PrismaClient, Prisma } from '@prisma/client';
|
||
|
||
const prisma = new PrismaClient();
|
||
|
||
async function main() {
|
||
console.log('=== SEED-31: Creating test data for purchases workflow ===');
|
||
|
||
// --- 1. Client OZON ---
|
||
const ozon = await prisma.client.upsert({
|
||
where: { inn: '7704217370' },
|
||
update: {},
|
||
create: {
|
||
companyName: 'OZON',
|
||
inn: '7704217370',
|
||
abbreviation: 'OZ',
|
||
isActive: true,
|
||
},
|
||
});
|
||
console.log(`Client OZON: id=${ozon.id}`);
|
||
|
||
// --- 2. Suppliers ---
|
||
const allianceOpt = await prisma.supplier.upsert({
|
||
where: { inn: '7701234567' },
|
||
update: {},
|
||
create: {
|
||
companyName: 'ООО Компания Альянс Опт',
|
||
inn: '7701234567',
|
||
contactEmail: 'sales@alliance-opt.ru',
|
||
status: 'ACTIVE',
|
||
},
|
||
});
|
||
console.log(`Supplier Альянс Опт: id=${allianceOpt.id}`);
|
||
|
||
const korolevTube = await prisma.supplier.upsert({
|
||
where: { inn: '5001234567' },
|
||
update: {},
|
||
create: {
|
||
companyName: 'ООО Королевский трубный завод',
|
||
inn: '5001234567',
|
||
contactEmail: 'info@korolev-tube.ru',
|
||
status: 'ACTIVE',
|
||
},
|
||
});
|
||
console.log(`Supplier Королевский трубный завод: id=${korolevTube.id}`);
|
||
|
||
// KraskaProm already exists (id=3), but with different INN — find it
|
||
let kraskaProm = await prisma.supplier.findFirst({ where: { inn: '7702345678' } });
|
||
if (!kraskaProm) {
|
||
kraskaProm = await prisma.supplier.findFirst({ where: { companyName: { contains: 'КраскаПром' } } });
|
||
}
|
||
if (!kraskaProm) {
|
||
kraskaProm = await prisma.supplier.create({
|
||
data: {
|
||
companyName: 'ООО КраскаПром',
|
||
inn: '7702345678',
|
||
contactEmail: 'info@kraska-prom.ru',
|
||
status: 'ACTIVE',
|
||
},
|
||
});
|
||
}
|
||
console.log(`Supplier КраскаПром: id=${kraskaProm.id}`);
|
||
|
||
// TLT internal supplier — already exists (id=7), just find it
|
||
let tlt = await prisma.supplier.findFirst({ where: { isInternal: true } });
|
||
if (!tlt) {
|
||
tlt = await prisma.supplier.upsert({
|
||
where: { inn: '0000000000' },
|
||
update: {},
|
||
create: {
|
||
companyName: 'ТЛТ (interne)',
|
||
inn: '0000000000',
|
||
isInternal: true,
|
||
status: 'ACTIVE',
|
||
},
|
||
});
|
||
}
|
||
console.log(`Supplier TLT: id=${tlt.id}`);
|
||
|
||
// --- 3. Get admin user for createdById ---
|
||
const admin = await prisma.user.findFirst({ where: { role: 'ADMIN' } });
|
||
if (!admin) throw new Error('No ADMIN user found');
|
||
const acheteur = await prisma.user.findFirst({ where: { role: 'ACHETEUR' } });
|
||
if (!acheteur) throw new Error('No ACHETEUR user found');
|
||
const commercial = await prisma.user.findFirst({ where: { role: 'COMMERCIAL' } });
|
||
if (!commercial) throw new Error('No COMMERCIAL user found');
|
||
|
||
// --- 4. Order ---
|
||
// Check if we have a suitable LAUNCHED/IN_PRODUCTION order, or create one
|
||
let order = await prisma.order.findFirst({
|
||
where: { status: { in: ['LAUNCHED', 'IN_PRODUCTION'] }, quantity: { gte: 50 } },
|
||
orderBy: { id: 'desc' },
|
||
});
|
||
|
||
if (!order) {
|
||
// Create new order
|
||
order = await prisma.order.create({
|
||
data: {
|
||
orderCode: 'OZ2603РК-170',
|
||
productName: 'O32603OZ113-1730 - 4 Ролл-кейдж Нонсорт',
|
||
quantity: 170,
|
||
status: 'LAUNCHED',
|
||
clientId: ozon.id,
|
||
managerId: commercial!.id,
|
||
executionUnit: 'MAIN_PRODUCTION',
|
||
launchDate: new Date('2026-03-20'),
|
||
},
|
||
});
|
||
// Create status history
|
||
await prisma.orderStatusHistory.create({
|
||
data: {
|
||
orderId: order.id,
|
||
fromStatus: 'VALIDATED',
|
||
toStatus: 'LAUNCHED',
|
||
changedById: admin.id,
|
||
},
|
||
});
|
||
console.log(`Created order: id=${order.id}, code=${order.orderCode}`);
|
||
} else {
|
||
console.log(`Using existing order: id=${order.id}, code=${order.orderCode}, status=${order.status}`);
|
||
}
|
||
|
||
// --- 5. Purchase Requirements (9 PRs) ---
|
||
// Check if PRs already exist for this order with ORDERED status
|
||
const existingOrderedPRs = await prisma.purchaseRequirement.count({
|
||
where: { orderId: order.id, status: 'ORDERED' },
|
||
});
|
||
|
||
if (existingOrderedPRs >= 5) {
|
||
console.log(`PRs already exist (${existingOrderedPRs} ORDERED), skipping PR creation`);
|
||
} else {
|
||
// Clean existing PRs for this order if any incomplete set
|
||
const existingPRs = await prisma.purchaseRequirement.findMany({
|
||
where: { orderId: order.id },
|
||
select: { id: true },
|
||
});
|
||
if (existingPRs.length > 0 && existingPRs.length < 9) {
|
||
// Cleanup incomplete PRs (only if safe)
|
||
const unsafe = await prisma.purchaseRequirement.count({
|
||
where: { orderId: order.id, status: { in: ['IN_TENDER', 'ORDERED', 'RECEIVED'] } },
|
||
});
|
||
if (unsafe === 0) {
|
||
await prisma.purchaseRequirement.deleteMany({ where: { orderId: order.id } });
|
||
console.log('Cleaned incomplete PRs');
|
||
}
|
||
}
|
||
|
||
const prData = [
|
||
// LASER_FLAT pieces (TLT)
|
||
{ materialCategory: 'LASER_FLAT' as const, description: 'Крюк-пряжка', quantity: 170, unit: 'шт', estimatedPrice: 45, status: 'ORDERED' as const },
|
||
{ materialCategory: 'LASER_FLAT' as const, description: 'Кронштейн', quantity: 340, unit: 'шт', estimatedPrice: 28, status: 'ORDERED' as const },
|
||
{ materialCategory: 'LASER_FLAT' as const, description: 'Стяжка основания', quantity: 170, unit: 'шт', estimatedPrice: 62, status: 'ORDERED' as const },
|
||
// LASER_TUBE (TLT)
|
||
{ materialCategory: 'LASER_TUBE' as const, description: 'Труба профильная 40x40x3', quantity: 1000, unit: 'м', estimatedPrice: 540, status: 'ORDERED' as const },
|
||
// PAINT
|
||
{ materialCategory: 'PAINT' as const, description: 'Краска RAL-5002', quantity: 1000, unit: 'кг', estimatedPrice: 385, status: 'ORDERED' as const },
|
||
// METAL
|
||
{ materialCategory: 'METAL' as const, description: 'Труба 20x20x1.5', quantity: 500, unit: 'м', estimatedPrice: 320, status: 'ORDERED' as const },
|
||
{ materialCategory: 'METAL' as const, description: 'Труба 25x25x1.5', quantity: 300, unit: 'м', estimatedPrice: 380, status: 'ORDERED' as const },
|
||
// FASTENERS
|
||
{ materialCategory: 'FASTENERS' as const, description: 'Болт M10x30', quantity: 680, unit: 'шт', estimatedPrice: 12, status: 'ORDERED' as const },
|
||
{ materialCategory: 'FASTENERS' as const, description: 'Гайка M10', quantity: 680, unit: 'шт', estimatedPrice: 5, status: 'ORDERED' as const },
|
||
];
|
||
|
||
const createdPRs: Array<{ id: number; description: string; materialCategory: string }> = [];
|
||
for (const pr of prData) {
|
||
const existing = await prisma.purchaseRequirement.findFirst({
|
||
where: { orderId: order.id, description: pr.description, materialCategory: pr.materialCategory },
|
||
});
|
||
if (existing) {
|
||
// Update status if needed
|
||
if (existing.status !== 'ORDERED') {
|
||
await prisma.purchaseRequirement.update({
|
||
where: { id: existing.id },
|
||
data: { status: 'ORDERED' },
|
||
});
|
||
}
|
||
createdPRs.push({ id: existing.id, description: existing.description, materialCategory: existing.materialCategory as string });
|
||
} else {
|
||
const created = await prisma.purchaseRequirement.create({
|
||
data: {
|
||
orderId: order.id,
|
||
materialCategory: pr.materialCategory,
|
||
description: pr.description,
|
||
quantity: new Prisma.Decimal(pr.quantity),
|
||
unit: pr.unit,
|
||
estimatedPrice: new Prisma.Decimal(pr.estimatedPrice),
|
||
budgetAmount: new Prisma.Decimal(pr.quantity * pr.estimatedPrice),
|
||
status: pr.status,
|
||
priority: 'NORMAL',
|
||
sourceType: 'SMETA_IMPORT',
|
||
},
|
||
});
|
||
createdPRs.push({ id: created.id, description: created.description, materialCategory: created.materialCategory });
|
||
}
|
||
}
|
||
console.log(`PRs created/updated: ${createdPRs.length}`);
|
||
|
||
// --- 6. Tender AWARDED + Offers + LineAwards ---
|
||
let tender = await prisma.tender.findFirst({
|
||
where: { referenceCode: 'T-2603-007' },
|
||
});
|
||
|
||
if (!tender) {
|
||
tender = await prisma.tender.create({
|
||
data: {
|
||
referenceCode: 'T-2603-007',
|
||
status: 'AWARDED',
|
||
description: 'Тендер на материалы и покраску для Ролл-кейдж',
|
||
createdById: acheteur!.id,
|
||
deadline: new Date('2026-04-01'),
|
||
awardedAt: new Date('2026-03-22'),
|
||
},
|
||
});
|
||
console.log(`Created tender: id=${tender.id}, ref=${tender.referenceCode}`);
|
||
|
||
// Link non-TLT PRs to tender
|
||
const nonTltPRs = createdPRs.filter(pr =>
|
||
!['LASER_FLAT', 'LASER_TUBE', 'PIPE_CUT'].includes(pr.materialCategory)
|
||
);
|
||
for (const pr of nonTltPRs) {
|
||
await prisma.purchaseRequirement.update({
|
||
where: { id: pr.id },
|
||
data: { tenderId: tender.id },
|
||
});
|
||
}
|
||
|
||
// Create TenderOffers
|
||
const offerAlliance = await prisma.tenderOffer.create({
|
||
data: {
|
||
tenderId: tender.id,
|
||
supplierId: allianceOpt.id,
|
||
proposedPrice: new Prisma.Decimal(396560),
|
||
deliveryDays: 14,
|
||
conditions: '100% предоплата',
|
||
receivedVia: 'EMAIL',
|
||
},
|
||
});
|
||
|
||
const offerKorolev = await prisma.tenderOffer.create({
|
||
data: {
|
||
tenderId: tender.id,
|
||
supplierId: korolevTube.id,
|
||
proposedPrice: new Prisma.Decimal(274000),
|
||
deliveryDays: 21,
|
||
conditions: '50/50',
|
||
receivedVia: 'EMAIL',
|
||
},
|
||
});
|
||
|
||
// Create TenderOfferLines
|
||
// Alliance: paint + fasteners
|
||
const paintPR = createdPRs.find(p => p.description === 'Краска RAL-5002')!;
|
||
const bolt = createdPRs.find(p => p.description === 'Болт M10x30')!;
|
||
const nut = createdPRs.find(p => p.description === 'Гайка M10')!;
|
||
|
||
for (const { pr, price, qty } of [
|
||
{ pr: paintPR, price: 385, qty: 1000 },
|
||
{ pr: bolt, price: 12, qty: 680 },
|
||
{ pr: nut, price: 5, qty: 680 },
|
||
]) {
|
||
await prisma.tenderOfferLine.create({
|
||
data: {
|
||
offerId: offerAlliance.id,
|
||
requirementId: pr.id,
|
||
unitPrice: new Prisma.Decimal(price),
|
||
quantity: new Prisma.Decimal(qty),
|
||
totalLinePrice: new Prisma.Decimal(price * qty),
|
||
available: true,
|
||
},
|
||
});
|
||
}
|
||
|
||
// Korolev: metal tubes
|
||
const tube20 = createdPRs.find(p => p.description === 'Труба 20x20x1.5')!;
|
||
const tube25 = createdPRs.find(p => p.description === 'Труба 25x25x1.5')!;
|
||
|
||
for (const { pr, price, qty } of [
|
||
{ pr: tube20, price: 320, qty: 500 },
|
||
{ pr: tube25, price: 380, qty: 300 },
|
||
]) {
|
||
await prisma.tenderOfferLine.create({
|
||
data: {
|
||
offerId: offerKorolev.id,
|
||
requirementId: pr.id,
|
||
unitPrice: new Prisma.Decimal(price),
|
||
quantity: new Prisma.Decimal(qty),
|
||
totalLinePrice: new Prisma.Decimal(price * qty),
|
||
available: true,
|
||
},
|
||
});
|
||
}
|
||
|
||
// Create TenderLineAwards
|
||
// Alliance wins: paint + fasteners
|
||
for (const { pr, price, qty } of [
|
||
{ pr: paintPR, price: 385, qty: 1000 },
|
||
{ pr: bolt, price: 12, qty: 680 },
|
||
{ pr: nut, price: 5, qty: 680 },
|
||
]) {
|
||
await prisma.tenderLineAward.create({
|
||
data: {
|
||
tenderId: tender.id,
|
||
requirementId: pr.id,
|
||
offerId: offerAlliance.id,
|
||
supplierId: allianceOpt.id,
|
||
unitPrice: new Prisma.Decimal(price),
|
||
quantity: new Prisma.Decimal(qty),
|
||
totalPrice: new Prisma.Decimal(price * qty),
|
||
awardedById: acheteur!.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
// Korolev wins: metal tubes
|
||
for (const { pr, price, qty } of [
|
||
{ pr: tube20, price: 320, qty: 500 },
|
||
{ pr: tube25, price: 380, qty: 300 },
|
||
]) {
|
||
await prisma.tenderLineAward.create({
|
||
data: {
|
||
tenderId: tender.id,
|
||
requirementId: pr.id,
|
||
offerId: offerKorolev.id,
|
||
supplierId: korolevTube.id,
|
||
unitPrice: new Prisma.Decimal(price),
|
||
quantity: new Prisma.Decimal(qty),
|
||
totalPrice: new Prisma.Decimal(price * qty),
|
||
awardedById: acheteur!.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
console.log('Tender offers and awards created');
|
||
} else {
|
||
console.log(`Tender already exists: id=${tender.id}`);
|
||
}
|
||
|
||
// --- 7. Purchase Orders ---
|
||
// PO-2603-010: Alliance Opt — Paint
|
||
let po1 = await prisma.purchaseOrder.findFirst({ where: { orderCode: 'PO-2603-010' } });
|
||
if (!po1) {
|
||
po1 = await prisma.purchaseOrder.create({
|
||
data: {
|
||
orderCode: 'PO-2603-010',
|
||
supplierId: allianceOpt.id,
|
||
clientOrderId: order.id,
|
||
tenderId: tender.id,
|
||
items: [{ description: 'Краска RAL-5002', quantity: 1000, unit: 'кг', estimatedPrice: 385 }] as unknown as Prisma.InputJsonValue,
|
||
totalAmount: new Prisma.Decimal(385000),
|
||
status: 'CONFIRMED',
|
||
createdById: acheteur!.id,
|
||
expectedDeliveryDate: new Date('2026-04-10'),
|
||
},
|
||
});
|
||
// PO Lines
|
||
await prisma.purchaseOrderLine.create({
|
||
data: {
|
||
purchaseOrderId: po1.id,
|
||
description: 'Краска RAL-5002',
|
||
quantity: new Prisma.Decimal(1000),
|
||
unit: 'кг',
|
||
estimatedPrice: new Prisma.Decimal(385),
|
||
},
|
||
});
|
||
// PurchaseLot
|
||
const paintPR = createdPRs.find(p => p.description === 'Краска RAL-5002')!;
|
||
await prisma.purchaseLot.create({
|
||
data: {
|
||
requirementId: paintPR.id,
|
||
lotNumber: 1,
|
||
quantity: new Prisma.Decimal(1000),
|
||
deliveryDate: new Date('2026-04-10'),
|
||
status: 'ORDERED',
|
||
purchaseOrderId: po1.id,
|
||
},
|
||
});
|
||
// Payment schedule
|
||
const schedule1 = await prisma.pOPaymentSchedule.create({
|
||
data: {
|
||
purchaseOrderId: po1.id,
|
||
paymentType: 'PREPAYMENT_FULL',
|
||
},
|
||
});
|
||
await prisma.pOInstallment.create({
|
||
data: {
|
||
scheduleId: schedule1.id,
|
||
percentage: new Prisma.Decimal(100),
|
||
label: 'Предоплата',
|
||
sortOrder: 0,
|
||
},
|
||
});
|
||
console.log(`Created PO-2603-010: id=${po1.id}, CONFIRMED, 385 000₽`);
|
||
} else {
|
||
console.log(`PO-2603-010 already exists: id=${po1.id}`);
|
||
}
|
||
|
||
// PO-2603-011: Королевский трубный завод — Metal tubes
|
||
let po2 = await prisma.purchaseOrder.findFirst({ where: { orderCode: 'PO-2603-011' } });
|
||
if (!po2) {
|
||
const tube20PR = createdPRs.find(p => p.description === 'Труба 20x20x1.5')!;
|
||
const tube25PR = createdPRs.find(p => p.description === 'Труба 25x25x1.5')!;
|
||
const total = 500 * 320 + 300 * 380; // 160000 + 114000 = 274000
|
||
|
||
po2 = await prisma.purchaseOrder.create({
|
||
data: {
|
||
orderCode: 'PO-2603-011',
|
||
supplierId: korolevTube.id,
|
||
clientOrderId: order.id,
|
||
tenderId: tender.id,
|
||
items: [
|
||
{ description: 'Труба 20x20x1.5', quantity: 500, unit: 'м', estimatedPrice: 320 },
|
||
{ description: 'Труба 25x25x1.5', quantity: 300, unit: 'м', estimatedPrice: 380 },
|
||
] as unknown as Prisma.InputJsonValue,
|
||
totalAmount: new Prisma.Decimal(total),
|
||
status: 'DRAFT',
|
||
createdById: acheteur!.id,
|
||
expectedDeliveryDate: new Date('2026-04-20'),
|
||
},
|
||
});
|
||
// PO Lines
|
||
await prisma.purchaseOrderLine.createMany({
|
||
data: [
|
||
{ purchaseOrderId: po2.id, description: 'Труба 20x20x1.5', material: 'С245', quantity: new Prisma.Decimal(500), unit: 'м', estimatedPrice: new Prisma.Decimal(320) },
|
||
{ purchaseOrderId: po2.id, description: 'Труба 25x25x1.5', material: 'С245', quantity: new Prisma.Decimal(300), unit: 'м', estimatedPrice: new Prisma.Decimal(380) },
|
||
],
|
||
});
|
||
// PurchaseLots — 1 per item
|
||
await prisma.purchaseLot.create({
|
||
data: {
|
||
requirementId: tube20PR.id,
|
||
lotNumber: 1,
|
||
quantity: new Prisma.Decimal(500),
|
||
deliveryDate: new Date('2026-04-15'),
|
||
status: 'PLANNED',
|
||
purchaseOrderId: po2.id,
|
||
},
|
||
});
|
||
await prisma.purchaseLot.create({
|
||
data: {
|
||
requirementId: tube25PR.id,
|
||
lotNumber: 1,
|
||
quantity: new Prisma.Decimal(300),
|
||
deliveryDate: new Date('2026-04-20'),
|
||
status: 'PLANNED',
|
||
purchaseOrderId: po2.id,
|
||
},
|
||
});
|
||
console.log(`Created PO-2603-011: id=${po2.id}, DRAFT, ${total}₽`);
|
||
} else {
|
||
console.log(`PO-2603-011 already exists: id=${po2.id}`);
|
||
}
|
||
|
||
// PO-2603-012: Alliance Opt — Fasteners
|
||
let po3 = await prisma.purchaseOrder.findFirst({ where: { orderCode: 'PO-2603-012' } });
|
||
if (!po3) {
|
||
const boltPR = createdPRs.find(p => p.description === 'Болт M10x30')!;
|
||
const nutPR = createdPRs.find(p => p.description === 'Гайка M10')!;
|
||
const total = 680 * 12 + 680 * 5; // 8160 + 3400 = 11560
|
||
|
||
po3 = await prisma.purchaseOrder.create({
|
||
data: {
|
||
orderCode: 'PO-2603-012',
|
||
supplierId: allianceOpt.id,
|
||
clientOrderId: order.id,
|
||
tenderId: tender.id,
|
||
items: [
|
||
{ description: 'Болт M10x30', quantity: 680, unit: 'шт', estimatedPrice: 12 },
|
||
{ description: 'Гайка M10', quantity: 680, unit: 'шт', estimatedPrice: 5 },
|
||
] as unknown as Prisma.InputJsonValue,
|
||
totalAmount: new Prisma.Decimal(total),
|
||
status: 'DRAFT',
|
||
createdById: acheteur!.id,
|
||
expectedDeliveryDate: new Date('2026-04-05'),
|
||
},
|
||
});
|
||
// PO Lines
|
||
await prisma.purchaseOrderLine.createMany({
|
||
data: [
|
||
{ purchaseOrderId: po3.id, description: 'Болт M10x30', quantity: new Prisma.Decimal(680), unit: 'шт', estimatedPrice: new Prisma.Decimal(12) },
|
||
{ purchaseOrderId: po3.id, description: 'Гайка M10', quantity: new Prisma.Decimal(680), unit: 'шт', estimatedPrice: new Prisma.Decimal(5) },
|
||
],
|
||
});
|
||
// PurchaseLot
|
||
await prisma.purchaseLot.create({
|
||
data: {
|
||
requirementId: boltPR.id,
|
||
lotNumber: 1,
|
||
quantity: new Prisma.Decimal(680),
|
||
deliveryDate: new Date('2026-04-05'),
|
||
status: 'PLANNED',
|
||
purchaseOrderId: po3.id,
|
||
},
|
||
});
|
||
await prisma.purchaseLot.create({
|
||
data: {
|
||
requirementId: nutPR.id,
|
||
lotNumber: 1,
|
||
quantity: new Prisma.Decimal(680),
|
||
deliveryDate: new Date('2026-04-05'),
|
||
status: 'PLANNED',
|
||
purchaseOrderId: po3.id,
|
||
},
|
||
});
|
||
console.log(`Created PO-2603-012: id=${po3.id}, DRAFT, ${total}₽`);
|
||
} else {
|
||
console.log(`PO-2603-012 already exists: id=${po3.id}`);
|
||
}
|
||
|
||
// Link TenderLineAwards to POs
|
||
if (po1 && tender) {
|
||
const paintPR = createdPRs.find(p => p.description === 'Краска RAL-5002')!;
|
||
await prisma.tenderLineAward.updateMany({
|
||
where: { tenderId: tender.id, requirementId: paintPR.id },
|
||
data: { purchaseOrderId: po1.id },
|
||
});
|
||
}
|
||
if (po2 && tender) {
|
||
const tube20PR = createdPRs.find(p => p.description === 'Труба 20x20x1.5')!;
|
||
const tube25PR = createdPRs.find(p => p.description === 'Труба 25x25x1.5')!;
|
||
await prisma.tenderLineAward.updateMany({
|
||
where: { tenderId: tender.id, requirementId: { in: [tube20PR.id, tube25PR.id] } },
|
||
data: { purchaseOrderId: po2.id },
|
||
});
|
||
}
|
||
if (po3 && tender) {
|
||
const boltPR = createdPRs.find(p => p.description === 'Болт M10x30')!;
|
||
const nutPR = createdPRs.find(p => p.description === 'Гайка M10')!;
|
||
await prisma.tenderLineAward.updateMany({
|
||
where: { tenderId: tender.id, requirementId: { in: [boltPR.id, nutPR.id] } },
|
||
data: { purchaseOrderId: po3.id },
|
||
});
|
||
}
|
||
}
|
||
|
||
// --- Summary ---
|
||
const poCount = await prisma.purchaseOrder.count();
|
||
const prCount = await prisma.purchaseRequirement.count({ where: { orderId: order.id } });
|
||
const lotCount = await prisma.purchaseLot.count();
|
||
const tenderCount = await prisma.tender.count();
|
||
const awardCount = await prisma.tenderLineAward.count();
|
||
const scheduleCount = await prisma.pOPaymentSchedule.count();
|
||
|
||
console.log('\n=== Summary ===');
|
||
console.log(`Orders: ${(await prisma.order.count())}`);
|
||
console.log(`PRs for order ${order.orderCode}: ${prCount}`);
|
||
console.log(`Tenders: ${tenderCount}`);
|
||
console.log(`TenderLineAwards: ${awardCount}`);
|
||
console.log(`POs: ${poCount}`);
|
||
console.log(`PO Lots: ${lotCount}`);
|
||
console.log(`Payment Schedules: ${scheduleCount}`);
|
||
console.log('\n=== Seed complete ===');
|
||
}
|
||
|
||
main()
|
||
.catch((e) => {
|
||
console.error('Seed failed:', e);
|
||
process.exit(1);
|
||
})
|
||
.finally(() => prisma.$disconnect());
|