Add initial Prisma migration and catalog-based product seed
This commit is contained in:
1
prisma/migration_lock.toml
Normal file
1
prisma/migration_lock.toml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
provider = "postgresql"
|
||||||
293
prisma/migrations/0001_init/migration.sql
Normal file
293
prisma/migrations/0001_init/migration.sql
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
-- CreateSchema
|
||||||
|
CREATE SCHEMA IF NOT EXISTS "public";
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "UserRole" AS ENUM ('CLIENT', 'MANAGER');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "RegistrationStatus" AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "MessengerType" AS ENUM ('TELEGRAM', 'MAX');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "OrderKind" AS ENUM ('READY', 'CALCULATION');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "OrderStatus" AS ENUM ('NEW', 'MANAGER_PROCESSING', 'WAITING_DOUBLE_CONFIRM', 'CLIENT_REJECTED', 'MANAGER_REJECTED', 'MANAGER_BLOCKED', 'CONFIRMED', 'IN_PROGRESS', 'COMPLETED');
|
||||||
|
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "WithdrawalStatus" AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Company" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"inn" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Company_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "User" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"fullName" TEXT NOT NULL,
|
||||||
|
"role" "UserRole" NOT NULL,
|
||||||
|
"companyId" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "RegistrationRequest" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"companyName" TEXT NOT NULL,
|
||||||
|
"inn" TEXT,
|
||||||
|
"contactName" TEXT NOT NULL,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"status" "RegistrationStatus" NOT NULL DEFAULT 'PENDING',
|
||||||
|
"rejectionReason" TEXT,
|
||||||
|
"requesterId" TEXT,
|
||||||
|
"reviewedById" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "RegistrationRequest_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Invitation" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"token" TEXT NOT NULL,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"companyName" TEXT NOT NULL,
|
||||||
|
"managerId" TEXT NOT NULL,
|
||||||
|
"acceptedById" TEXT,
|
||||||
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"acceptedAt" TIMESTAMP(3),
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "Invitation_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "MessengerConnection" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"type" "MessengerType" NOT NULL,
|
||||||
|
"channelId" TEXT NOT NULL,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "MessengerConnection_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Product" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"sku" TEXT NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"description" TEXT,
|
||||||
|
"isCustomizable" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Product_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Warehouse" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"code" TEXT NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Warehouse_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "ProductStock" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"productId" TEXT NOT NULL,
|
||||||
|
"warehouseId" TEXT NOT NULL,
|
||||||
|
"availableQty" DECIMAL(14,3) NOT NULL,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "ProductStock_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Order" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"code" TEXT NOT NULL,
|
||||||
|
"kind" "OrderKind" NOT NULL,
|
||||||
|
"customerId" TEXT NOT NULL,
|
||||||
|
"managerId" TEXT,
|
||||||
|
"status" "OrderStatus" NOT NULL DEFAULT 'NEW',
|
||||||
|
"clientApproved" BOOLEAN,
|
||||||
|
"managerApproved" BOOLEAN,
|
||||||
|
"blockReason" TEXT,
|
||||||
|
"deliveryTerms" TEXT,
|
||||||
|
"deliveryFee" DECIMAL(14,2),
|
||||||
|
"totalPrice" DECIMAL(14,2),
|
||||||
|
"calculationPayload" JSONB,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Order_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "OrderItem" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"orderId" TEXT NOT NULL,
|
||||||
|
"productId" TEXT,
|
||||||
|
"productName" TEXT NOT NULL,
|
||||||
|
"quantity" DECIMAL(14,3) NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "OrderItem_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "OrderStatusEvent" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"orderId" TEXT NOT NULL,
|
||||||
|
"status" "OrderStatus" NOT NULL,
|
||||||
|
"actorUserId" TEXT NOT NULL,
|
||||||
|
"note" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "OrderStatusEvent_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "ReferralLink" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"referrerId" TEXT NOT NULL,
|
||||||
|
"refereeId" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "ReferralLink_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "BonusTransaction" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"amount" DECIMAL(14,2) NOT NULL,
|
||||||
|
"reason" TEXT NOT NULL,
|
||||||
|
"orderId" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "BonusTransaction_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "RewardWithdrawalRequest" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"requesterId" TEXT NOT NULL,
|
||||||
|
"amount" DECIMAL(14,2) NOT NULL,
|
||||||
|
"status" "WithdrawalStatus" NOT NULL DEFAULT 'PENDING',
|
||||||
|
"reviewedById" TEXT,
|
||||||
|
"reviewComment" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "RewardWithdrawalRequest_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Company_name_key" ON "Company"("name");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Company_inn_key" ON "Company"("inn");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Invitation_token_key" ON "Invitation"("token");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "MessengerConnection_userId_type_channelId_key" ON "MessengerConnection"("userId", "type", "channelId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Product_sku_key" ON "Product"("sku");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Warehouse_code_key" ON "Warehouse"("code");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "ProductStock_productId_warehouseId_key" ON "ProductStock"("productId", "warehouseId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Order_code_key" ON "Order"("code");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "ReferralLink_referrerId_refereeId_key" ON "ReferralLink"("referrerId", "refereeId");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "User" ADD CONSTRAINT "User_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "RegistrationRequest" ADD CONSTRAINT "RegistrationRequest_requesterId_fkey" FOREIGN KEY ("requesterId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "RegistrationRequest" ADD CONSTRAINT "RegistrationRequest_reviewedById_fkey" FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Invitation" ADD CONSTRAINT "Invitation_managerId_fkey" FOREIGN KEY ("managerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Invitation" ADD CONSTRAINT "Invitation_acceptedById_fkey" FOREIGN KEY ("acceptedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "MessengerConnection" ADD CONSTRAINT "MessengerConnection_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "ProductStock" ADD CONSTRAINT "ProductStock_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "ProductStock" ADD CONSTRAINT "ProductStock_warehouseId_fkey" FOREIGN KEY ("warehouseId") REFERENCES "Warehouse"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Order" ADD CONSTRAINT "Order_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "Order" ADD CONSTRAINT "Order_managerId_fkey" FOREIGN KEY ("managerId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "Order"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "OrderItem" ADD CONSTRAINT "OrderItem_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "OrderStatusEvent" ADD CONSTRAINT "OrderStatusEvent_orderId_fkey" FOREIGN KEY ("orderId") REFERENCES "Order"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "OrderStatusEvent" ADD CONSTRAINT "OrderStatusEvent_actorUserId_fkey" FOREIGN KEY ("actorUserId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "ReferralLink" ADD CONSTRAINT "ReferralLink_referrerId_fkey" FOREIGN KEY ("referrerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "ReferralLink" ADD CONSTRAINT "ReferralLink_refereeId_fkey" FOREIGN KEY ("refereeId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "BonusTransaction" ADD CONSTRAINT "BonusTransaction_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "RewardWithdrawalRequest" ADD CONSTRAINT "RewardWithdrawalRequest_requesterId_fkey" FOREIGN KEY ("requesterId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "RewardWithdrawalRequest" ADD CONSTRAINT "RewardWithdrawalRequest_reviewedById_fkey" FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
109
scripts/seed.js
109
scripts/seed.js
@@ -2,9 +2,98 @@ import 'dotenv/config';
|
|||||||
|
|
||||||
import { prisma } from '../src/prisma-client.js';
|
import { prisma } from '../src/prisma-client.js';
|
||||||
|
|
||||||
|
const CATALOG_PAGES = ['https://fregat.org/catalog/', 'https://fregat.org/catalog/page/2/'];
|
||||||
const managerEmail = 'manager@fregat.local';
|
const managerEmail = 'manager@fregat.local';
|
||||||
const clientEmail = 'client@fregat.local';
|
const clientEmail = 'client@fregat.local';
|
||||||
|
|
||||||
|
function decodeHtmlEntities(value) {
|
||||||
|
return value
|
||||||
|
.replaceAll(' ', ' ')
|
||||||
|
.replaceAll('&', '&')
|
||||||
|
.replaceAll('"', '"')
|
||||||
|
.replaceAll(''', "'")
|
||||||
|
.replaceAll('«', '«')
|
||||||
|
.replaceAll('»', '»')
|
||||||
|
.replaceAll('—', '—')
|
||||||
|
.replaceAll('–', '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeText(value) {
|
||||||
|
return decodeHtmlEntities(value.replaceAll(/<[^>]*>/g, ' ').replaceAll(/\s+/g, ' ')).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function skuFromHref(href, index) {
|
||||||
|
const pathname = href.replace(/^https?:\/\/[^/]+/i, '').split('?')[0] || '';
|
||||||
|
const segments = pathname.split('/').filter(Boolean);
|
||||||
|
const slug = segments[segments.length - 1] ?? '';
|
||||||
|
if (!slug) {
|
||||||
|
return `FREGAT-CATALOG-${String(index + 1).padStart(3, '0')}`;
|
||||||
|
}
|
||||||
|
const normalized = slug.toUpperCase().replaceAll(/[^A-Z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
||||||
|
return `FREGAT-${normalized || String(index + 1).padStart(3, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCatalogCards(html) {
|
||||||
|
const cards = [];
|
||||||
|
const cardRegex =
|
||||||
|
/<a[^>]*class="[^"]*product-card[^"]*"[^>]*href="([^"]+)"[^>]*>[\s\S]*?<div class="product-card__title">([\s\S]*?)<\/div>\s*<div class="product-card__type">([\s\S]*?)<\/div>/g;
|
||||||
|
|
||||||
|
let match;
|
||||||
|
while ((match = cardRegex.exec(html)) !== null) {
|
||||||
|
const href = match[1];
|
||||||
|
const title = normalizeText(match[2]);
|
||||||
|
const type = normalizeText(match[3]);
|
||||||
|
if (!title) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cards.push({ href, title, type });
|
||||||
|
}
|
||||||
|
|
||||||
|
return cards;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCatalogProducts() {
|
||||||
|
const parsed = [];
|
||||||
|
|
||||||
|
for (const pageUrl of CATALOG_PAGES) {
|
||||||
|
const response = await fetch(pageUrl, { redirect: 'follow' });
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Catalog request failed: ${pageUrl} (${response.status})`);
|
||||||
|
}
|
||||||
|
const html = await response.text();
|
||||||
|
const cards = parseCatalogCards(html);
|
||||||
|
if (!cards.length) {
|
||||||
|
throw new Error(`No product cards found at ${pageUrl}`);
|
||||||
|
}
|
||||||
|
parsed.push(...cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
const deduped = new Map();
|
||||||
|
for (const [index, card] of parsed.entries()) {
|
||||||
|
const sku = skuFromHref(card.href, index);
|
||||||
|
if (deduped.has(sku)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const descriptionParts = [];
|
||||||
|
if (card.type) {
|
||||||
|
descriptionParts.push(card.type);
|
||||||
|
}
|
||||||
|
descriptionParts.push(`Источник: ${card.href}`);
|
||||||
|
|
||||||
|
deduped.set(sku, {
|
||||||
|
sku,
|
||||||
|
name: card.title,
|
||||||
|
description: descriptionParts.join('. '),
|
||||||
|
isCustomizable: /логотип|печать/i.test(`${card.title} ${card.type}`),
|
||||||
|
qtyMain: 300 + index * 17,
|
||||||
|
qtyReserve: 120 + index * 9,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...deduped.values()];
|
||||||
|
}
|
||||||
|
|
||||||
const company = await prisma.company.upsert({
|
const company = await prisma.company.upsert({
|
||||||
where: { inn: '7701000000' },
|
where: { inn: '7701000000' },
|
||||||
update: {},
|
update: {},
|
||||||
@@ -47,24 +136,8 @@ const warehouseReserve = await prisma.warehouse.upsert({
|
|||||||
create: { code: 'SPB-01', name: 'Reserve warehouse' },
|
create: { code: 'SPB-01', name: 'Reserve warehouse' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const products = [
|
const products = await loadCatalogProducts();
|
||||||
{
|
console.log(`Loaded ${products.length} products from fregat.org catalog.`);
|
||||||
sku: 'FILM-100',
|
|
||||||
name: 'Пленка прозрачная 100мкм',
|
|
||||||
description: 'Готовая продукция для стандартной упаковки',
|
|
||||||
isCustomizable: false,
|
|
||||||
qtyMain: 1250,
|
|
||||||
qtyReserve: 420,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sku: 'FILM-200-COLOR',
|
|
||||||
name: 'Пленка цветная 200мкм',
|
|
||||||
description: 'Продукция с дополнительной окраской',
|
|
||||||
isCustomizable: true,
|
|
||||||
qtyMain: 860,
|
|
||||||
qtyReserve: 230,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const product of products) {
|
for (const product of products) {
|
||||||
const dbProduct = await prisma.product.upsert({
|
const dbProduct = await prisma.product.upsert({
|
||||||
|
|||||||
Reference in New Issue
Block a user