Add tagged catalog import
This commit is contained in:
2363
data/catalog-import-2026-04-08.json
Normal file
2363
data/catalog-import-2026-04-08.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,8 @@
|
|||||||
"prisma:migrate": "prisma migrate deploy",
|
"prisma:migrate": "prisma migrate deploy",
|
||||||
"prisma:push": "prisma db push",
|
"prisma:push": "prisma db push",
|
||||||
"seed": "node scripts/seed.js",
|
"seed": "node scripts/seed.js",
|
||||||
"seed:demo": "node scripts/seed-demo.js"
|
"seed:demo": "node scripts/seed-demo.js",
|
||||||
|
"import:catalog": "node scripts/import-catalog.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|||||||
3
prisma/migrations/0010_add_product_tags/migration.sql
Normal file
3
prisma/migrations/0010_add_product_tags/migration.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Product" ADD COLUMN "tags" TEXT[] DEFAULT ARRAY[]::TEXT[];
|
||||||
|
|
||||||
@@ -179,6 +179,7 @@ model Product {
|
|||||||
thicknessMicron Int?
|
thicknessMicron Int?
|
||||||
sleeveBrand String?
|
sleeveBrand String?
|
||||||
quantityPerBox String?
|
quantityPerBox String?
|
||||||
|
tags String[] @default([])
|
||||||
description String?
|
description String?
|
||||||
isCustomizable Boolean @default(false)
|
isCustomizable Boolean @default(false)
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
|
|||||||
105
scripts/import-catalog.js
Normal file
105
scripts/import-catalog.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
|
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
|
||||||
|
import { prisma } from '../src/prisma-client.js';
|
||||||
|
|
||||||
|
const IMPORT_DESCRIPTION_PREFIX = 'Импорт каталога 2026-04-08: ';
|
||||||
|
const dataset = JSON.parse(
|
||||||
|
readFileSync(new URL('../data/catalog-import-2026-04-08.json', import.meta.url), 'utf8'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const warehouses = [
|
||||||
|
{ code: 'MSK-01', name: 'Склад Москва' },
|
||||||
|
{ code: 'SPB-01', name: 'Склад СПб' },
|
||||||
|
];
|
||||||
|
|
||||||
|
function formatQuantity(value) {
|
||||||
|
return Number(value ?? 0).toFixed(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const warehouse of warehouses) {
|
||||||
|
await prisma.warehouse.upsert({
|
||||||
|
where: { code: warehouse.code },
|
||||||
|
update: { name: warehouse.name },
|
||||||
|
create: warehouse,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const warehouseIds = Object.fromEntries(
|
||||||
|
await Promise.all(
|
||||||
|
warehouses.map(async (warehouse) => {
|
||||||
|
const persistedWarehouse = await prisma.warehouse.findUniqueOrThrow({
|
||||||
|
where: { code: warehouse.code },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
return [warehouse.code, persistedWarehouse.id];
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await prisma.product.updateMany({
|
||||||
|
data: {
|
||||||
|
isActive: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let importedCount = 0;
|
||||||
|
|
||||||
|
for (const item of dataset) {
|
||||||
|
const product = await prisma.product.upsert({
|
||||||
|
where: { sku: item.sku },
|
||||||
|
update: {
|
||||||
|
name: item.name,
|
||||||
|
productType: item.productType,
|
||||||
|
widthMm: item.widthMm,
|
||||||
|
lengthM: item.lengthM,
|
||||||
|
thicknessMicron: item.thicknessMicron,
|
||||||
|
sleeveBrand: item.sleeveBrand,
|
||||||
|
quantityPerBox: item.quantityPerBox,
|
||||||
|
tags: item.tags,
|
||||||
|
description: `${IMPORT_DESCRIPTION_PREFIX}${item.rawName}`,
|
||||||
|
isCustomizable: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
sku: item.sku,
|
||||||
|
name: item.name,
|
||||||
|
productType: item.productType,
|
||||||
|
widthMm: item.widthMm,
|
||||||
|
lengthM: item.lengthM,
|
||||||
|
thicknessMicron: item.thicknessMicron,
|
||||||
|
sleeveBrand: item.sleeveBrand,
|
||||||
|
quantityPerBox: item.quantityPerBox,
|
||||||
|
tags: item.tags,
|
||||||
|
description: `${IMPORT_DESCRIPTION_PREFIX}${item.rawName}`,
|
||||||
|
isCustomizable: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const warehouse of warehouses) {
|
||||||
|
await prisma.productStock.upsert({
|
||||||
|
where: {
|
||||||
|
productId_warehouseId: {
|
||||||
|
productId: product.id,
|
||||||
|
warehouseId: warehouseIds[warehouse.code],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
availableQty: formatQuantity(item.balances[warehouse.code]),
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
productId: product.id,
|
||||||
|
warehouseId: warehouseIds[warehouse.code],
|
||||||
|
availableQty: formatQuantity(item.balances[warehouse.code]),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
importedCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Imported ${importedCount} catalog products from 2026-04-08 stock reports.`);
|
||||||
|
await prisma.$disconnect();
|
||||||
@@ -242,6 +242,7 @@ type Product {
|
|||||||
thicknessMicron: Int
|
thicknessMicron: Int
|
||||||
sleeveBrand: String
|
sleeveBrand: String
|
||||||
quantityPerBox: String
|
quantityPerBox: String
|
||||||
|
tags: [String!]!
|
||||||
isCustomizable: Boolean!
|
isCustomizable: Boolean!
|
||||||
isActive: Boolean!
|
isActive: Boolean!
|
||||||
availableInWarehouses: [ProductWarehouseBalance!]!
|
availableInWarehouses: [ProductWarehouseBalance!]!
|
||||||
|
|||||||
Reference in New Issue
Block a user