canina/backend/prisma/seed-products.ts
parsa aghaei 7615aa0e51 fix: resolve seed encoding, search param, and wiki data source issues
- Fix seed-products.ts TS error (implicit any) and BOM handling
- Re-run full seed to restore correct Persian encoding in DB
- Fix productService query→search param mismatch
- Fix IngredientWiki hardcoded port 4000→use settingsStore
- Restore seed-products-data.json from git after accidental corruption
2026-07-11 15:40:49 +03:30

255 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { PrismaClient } from '@prisma/client';
import * as fs from 'fs';
import * as path from 'path';
const prisma = new PrismaClient();
function slugify(text: string): string {
return text
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^a-z0-9\u0600-\u06FF\-]/g, '')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '');
}
function determineSuitableFor(name: string, description: string): string {
const text = (name + ' ' + description).toLowerCase();
const hasCat = text.includes('گربه') || text.includes('katzen') || text.includes('cat');
const hasDog = text.includes('سگ') || text.includes('hund') || text.includes('توله') || text.includes('dog');
if (hasCat && hasDog) return 'هر دو';
if (hasCat) return 'گربه';
if (hasDog) return 'سگ';
return 'هر دو';
}
function parseSize(size: string): { unit: string; packageSize: number } {
const mlMatch = size.match(/([\d.]+)\s*ml/i);
if (mlMatch) return { unit: 'ml', packageSize: parseFloat(mlMatch[1]) };
const gMatch = size.match(/([\d.]+)\s*g/i);
if (gMatch) return { unit: 'g', packageSize: parseFloat(gMatch[1]) };
const tabMatch = size.match(/([\d.]+)\s*(tablet|tab)/i);
if (tabMatch) return { unit: 'tablet', packageSize: parseFloat(tabMatch[1]) };
return { unit: 'g', packageSize: 100 };
}
async function findOrCreateCategory(slug: string): Promise<{ id: string; slug: string }> {
const CATEGORY_NAMES: Record<string, string> = {
'joints': 'مفاصل و استخوان',
'immune': 'تقویت سیستم ایمنی و گوارش',
'energy': 'ویتامین‌ها و انرژی‌بخش‌ها',
'special-care': 'مراقبت‌های ویژه (پوست، دندان و چشم)',
'general': 'تقویت عمومی',
'nutrition': 'تغذیه تخصصی',
'supplements': 'مکمل‌های غذایی و درمانی',
};
const name = CATEGORY_NAMES[slug] || slug;
return await prisma.category.upsert({
where: { slug },
update: { name },
create: { slug, name, description: name },
});
}
async function main() {
console.log('Seeding products from seed-products-data.json...');
// 2. Read JSON data
const dataPath = path.join(__dirname, 'seed-products-data.json');
if (!fs.existsSync(dataPath)) {
console.error('seed-products-data.json not found at', dataPath);
process.exit(1);
}
const productsData = JSON.parse(fs.readFileSync(dataPath, 'utf-8').replace(/^\ufeff/, ''));
let variantCount = 0;
for (const item of productsData) {
const baseName = item.name;
const cleanDesc = item.description;
const cleanIngredients = item.ingredients || '';
const cleanDosage = item.usage_and_dosage || '';
const suitableFor = determineSuitableFor(baseName, cleanDesc);
const baseSlug = slugify(baseName);
const categorySlug = item.category_slug || 'supplements';
const category = await findOrCreateCategory(categorySlug);
for (const variant of item.variants) {
const artNo = variant.art_no;
const barcode = variant.barcode;
const sellPrice = variant.sell_price || 0;
const buyPrice = variant.buy_price || 0;
const sizeLabel = variant.size;
const { unit, packageSize } = parseSize(sizeLabel);
// Build variant-specific slug
const sizeSlug = slugify(sizeLabel);
const slug = `${baseSlug}-${sizeSlug}`;
// Build display name with size
const displayName = `${baseName} - ${sizeLabel}`;
const priceDisplay = `${sellPrice.toLocaleString()} T`;
const product = await prisma.product.upsert({
where: { artNo },
update: {
barcode,
slug,
productGroup: baseSlug,
name: displayName,
description: cleanDesc,
ingredients: cleanIngredients,
categoryId: category.id,
categorySlug: category.slug,
priceValue: sellPrice,
buyPrice,
priceDisplay,
unit,
packageSize,
dosageLogic: cleanDosage,
suitableFor,
imageUrl: `/products/${baseSlug}.png`,
},
create: {
artNo,
barcode,
slug,
productGroup: baseSlug,
name: displayName,
description: cleanDesc,
ingredients: cleanIngredients,
categoryId: category.id,
categorySlug: category.slug,
priceValue: sellPrice,
buyPrice,
priceDisplay,
unit,
packageSize,
dosageLogic: cleanDosage,
suitableFor,
imageUrl: `/products/${baseSlug}.png`,
}
});
// Seed ingredients (split by '،' or '، ')
await prisma.productIngredient.deleteMany({ where: { productId: product.id } });
if (cleanIngredients) {
const parts = cleanIngredients.split(/[،,]/).map((s: string) => s.trim()).filter(Boolean);
// Only take the first meaningful items (up to ~20)
const meaningful = parts.slice(0, 20);
for (const ing of meaningful) {
const truncated = ing.substring(0, 150);
if (truncated.length > 0) {
await prisma.productIngredient.create({
data: { productId: product.id, ingredient: truncated }
});
}
}
}
variantCount++;
}
}
console.log(`Seeded ${variantCount} product variants.`);
// Create admin user for blogs
const adminId = '12345678-1234-1234-1234-123456789012';
await prisma.user.upsert({
where: { id: adminId },
update: { role: 'ADMIN' },
create: {
id: adminId,
mobile: '09120000000',
email: 'admin@canino-iran.com',
firstName: 'Admin',
lastName: 'User',
role: 'ADMIN'
}
});
// 3. Seed some Blogs
const blog1Content = [
'<p><strong>تغذیه صحیح سگ‌های بالغ</strong> یکی از مهم‌ترین عوامل در حفظ سلامت و افزایش طول عمر آن‌هاست. برند کانینا (Canina) با بیش از ۴۰ سال سابقه در تولید مکمل‌های دامپزشکی در آلمان، استاندارد طلایی تغذیه تکمیلی را تعریف کرده است.</p>',
'',
'<h2>اصول تغذیه سگ بالغ</h2>',
'<p>سگ‌های بالغ به رژیم غذایی متعادل حاوی پروتئین، چربی، کربوهیدرات، ویتامین‌ها و مواد معدنی نیاز دارند. نسبت Ca:P (کلسیم به فسفر) باید در محدوده ۱.۲:۱ تا ۱.۵:۱ باشد. هرگونه عدم تعادل در این نسبت می‌تواند منجر به مشکلات کلیوی و استخوانی شود.</p>',
'',
'<h2>نقش مکمل‌ها در رژیم غذایی</h2>',
'<p>حتی با بهترین رژیم غذایی، ممکن است برخی مواد مغذی به اندازه کافی تأمین نشوند. محصولات کانینا مانند <strong>Petvital Vitamin-Tabs</strong> (کمپلکس کامل A تا K3) و <strong>Biotin-Tabs</strong> (۱ میلیون میکروگرم بیوتین) نیازهای تغذیه‌ای را پوشش می‌دهند.</p>',
'',
'<h2>اسیدهای چرب ضروری</h2>',
'<p>روغن سالمون کانینا (Lachs-Öl) با ۱۴٪ امگا ۳ (EPA/DHA) به روش Cold Press استخراج می‌شود و تمام ویتامین‌های حساس به حرارت را حفظ می‌کند. EPA پیش‌ماده رزولوین‌های ضدالتهابی و DHA ۳۰٪ وزن خشک مغز را تشکیل می‌دهد.</p>',
'',
'<h2>مراقبت از مفاصل</h2>',
'<p>با افزایش سن سگ، غضروف مفصلی تحلیل می‌رود. گلیکوزآمینوگلیکان‌های صدف لب سبز (GAG) با جذب مولکول‌های آب در ماتریکس غضروفی، خاصیت بافری مفاصل را بازیابی می‌کنند. <strong>CANHYDROX GAG</strong> و <strong>FLEXAN</strong> حاوی این ترکیبات حیاتی هستند.</p>',
'',
'<h2>هشدارهای مهم تغذیه‌ای</h2>',
'<ul>',
'<li>مصرف همزمان ویتامین D3 با D2 مجاز نیست</li>',
'<li>روغن سیاه دانه در بارداری و شیردهی ممنوع است</li>',
'<li>روغن‌های با غلظت بالا باید تدریجاً به رژیم اضافه شوند تا از پانکراتیت جلوگیری شود</li>',
'<li>تورین برای گربه‌ها اسید آمینه ضروری است و بدن آن‌ها قادر به سنتز آن نیست</li>',
'</ul>'
].join('\n');
const blog2Content = [
'<p><strong>کانینا (Canina)</strong> نماینده رسمی برند <strong>Canina pharma GmbH</strong> در ایران است. این شرکت آلمانی در سال ۱۹۸۴ توسط <strong>پتر و کریستین کرشن‌مایر</strong> در شهر برگیش گلادباخ تأسیس شد و به یکی از پیشگامان تولید مکمل‌های طبیعی دامپزشکی در اروپا تبدیل شده است.</p>',
'',
'<h2>فلسفه Canina: "مادر طبیعت بهترین نسخه را می‌داند"</h2>',
'<p>تمام محصولات کانینا بر پایه مواد اولیه طبیعی و با فرآیندهای پیشرفته تولید می‌شوند. این شرکت دارای گواهی‌های معتبر <strong>IFS (International Featured Standard)</strong> و <strong>HACCP</strong> است و محصولات آن در بیش از ۴۰ کشور جهان توزیع می‌شود.</p>',
'',
'<h2>چرا مکمل‌های کانینا در ایران؟</h2>',
'<ul>',
'<li><strong>کیفیت آلمانی:</strong> تمام محصولات در کارخانه برگیش گلادباخ تحت نظارت دامپزشکان تولید می‌شوند</li>',
'<li><strong>بدون مواد مصنوعی:</strong> فاقد رنگ، طعم و نگهدارنده مصنوعی</li>',
'<li><strong>فرمولاسیون تخصصی:</strong> هر محصول برای نیاز خاصی مانند مفاصل، ایمنی، پوست و مو یا گوارش طراحی شده</li>',
'<li><strong>تأیید دامپزشکان:</strong> محصولات با مشورت دامپزشکان و متخصصان تغذیه حیوانات فرموله شده‌اند</li>',
'</ul>',
'',
'<h2>محصولات پرفروش در ایران</h2>',
'<p><strong>مفاصل و استخوان:</strong> CANHYDROX GAG (استاندارد طلایی ارتوپدی)، FLEXAN (کلاژن خالص)، Petvital GAG و Velox Gelenkenergie (کنسانتره صدف لب سبز)</p>',
'<p><strong>سیستم ایمنی و گوارش:</strong> Immun-Booster (خمیر آغوز)، Moor-Tränke (عصاره پیت)، Ballaststoff Mix (فیبر گیاهی)</p>',
'<p><strong>پوست و مو:</strong> Lachs-Öl (روغن سالمون)، Biotin-Tabs، Seealgen (جلبک دریایی)</p>',
'<p><strong>قلب و انرژی:</strong> Herz Vital (ال-کارنیتین و زالزالک)، Energy-Gel (ویتامین‌های گروه B)</p>',
'',
'<h2>تعهد به سلامت حیوانات</h2>',
'<p>کانینا به عنوان نماینده رسمی کانینا در ایران، متعهد به ارائه محصولات اصل با ضمانت اصالت و پروانه دامپزشکی است. تمام محصولات دارای بسته‌بندی اصلی آلمان و بارکد اختصاصی هستند.</p>'
].join('\n');
const blogs = [
{
title: 'راهنمای جامع تغذیه سگ‌های بالغ',
slug: 'adult-dog-nutrition-guide',
content: blog1Content,
authorId: adminId,
isPublished: true,
},
{
title: 'چرا مکمل‌های کانینا؟',
slug: 'why-canino-supplements',
content: blog2Content,
authorId: adminId,
isPublished: true,
}
];
for (const b of blogs) {
await prisma.blog.upsert({
where: { slug: b.slug },
update: {},
create: b
});
}
console.log('Seeded blogs.');
}
main()
.catch(e => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});