اپ: نام برند در همهی صفحهها و پیامها یکسان شده و از یک تنظیم مرکزی خوانده میشود. اپ: کارت حسابداری در صفحهی مشتری بازطراحی شد؛ ماندهها و وضعیت لینک واضحتر نمایش داده میشوند. پنل: کارت حسابداری در پروندهی مشتری بازطراحی شد؛ ماندهها، آخرین ارسال و فرم لینک دستی واضحتر شدهاند. پنل: ستون «کد» در جدولها بهطور پیشفرض پنهان است و از انتخاب ستونها قابل نمایش است. پنل: تغییر نمایش ستونها در جدولها بلافاصله اعمال میشود. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
119 lines
5.4 KiB
JavaScript
119 lines
5.4 KiB
JavaScript
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const seedPath = path.join(__dirname, 'seed.ts');
|
||
let content = fs.readFileSync(seedPath, 'utf-8');
|
||
|
||
const marker = ' imageCount += 1;\n }\n\n // \u2500\u2500 Featured collection';
|
||
if (!content.includes(marker)) {
|
||
console.error('MARKER NOT FOUND');
|
||
process.exit(1);
|
||
}
|
||
|
||
const insertion = ` imageCount += 1;
|
||
}
|
||
|
||
// \u2500\u2500 200 mock products for a realistic-looking catalogue \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
||
// These are generated, not hand-authored like the 5 above (whose ids are
|
||
// referenced elsewhere in this seed, e.g. by orders \u2014 left untouched).
|
||
// Images: real product photography does not exist in this project, so each
|
||
// mock product cycles through 6 generated SVG placeholders per category
|
||
// (apps/user-app/public/img/products/<slug>-N.svg), giving the catalogue
|
||
// grid genuine visual variety instead of one repeated icon.
|
||
const MOCK_CATEGORIES = [
|
||
{ slug: 'rings', id: ringsCategory.id, nouns: ['انگشتر نگیندار', 'انگشتر سولیتر', 'انگشتر آویزدار', 'انگشتر پهن', 'انگشتر ظریف', 'انگشتر رینگی'] },
|
||
{ slug: 'bracelets', id: braceletsCategory.id, nouns: ['دستبند زنجیری', 'دستبند پاندول', 'دستبند بافت', 'دستبند تنیس', 'دستبند پلاکدار', 'دستبند چرمی طلاکوب'] },
|
||
{ slug: 'necklaces', id: necklacesCategory.id, nouns: ['گردنبند آویز قلب', 'گردنبند ماه و ستاره', 'گردنبند ظریف', 'گردنبند رولو', 'گردنبند صلیب', 'گردنبند اسم'] },
|
||
{ slug: 'earrings', id: earringsCategory.id, nouns: ['گوشواره حلقهای', 'گوشواره آویز', 'گوشواره میخی', 'گوشواره پروانهای', 'گوشواره مرواریدی', 'گوشواره هندسی'] },
|
||
{ slug: 'coins', id: coinsCategory.id, nouns: ['ربع سکه بهار آزادی', 'نیم سکه بهار آزادی', 'سکه امامی', 'سکه پارسیان', 'شمش طلای ۱۰ گرمی', 'شمش طلای ۵ گرمی'] },
|
||
];
|
||
const MOCK_ADJECTIVES = ['کلاسیک', 'مدرن', 'مینیمال', 'لوکس', 'دستساز', 'ظریف', 'خاص', 'شیک', 'سنتی', 'رزگلد'];
|
||
const MOCK_BRANDS = [brandMain.id, brandArtisan.id];
|
||
|
||
const MOCK_PRODUCT_COUNT = 200;
|
||
let mockImageCount = 0;
|
||
for (let i = 0; i < MOCK_PRODUCT_COUNT; i++) {
|
||
const cat = MOCK_CATEGORIES[i % MOCK_CATEGORIES.length];
|
||
const noun = cat.nouns[i % cat.nouns.length];
|
||
const adjective = MOCK_ADJECTIVES[i % MOCK_ADJECTIVES.length];
|
||
const brandId = MOCK_BRANDS[i % MOCK_BRANDS.length];
|
||
const productId = \`mock-product-\${i + 1}\`;
|
||
const title = \`\${noun} \${adjective} \${i + 1}\`;
|
||
// Deterministic but varied numeric fields \u2014 no randomness, so a re-seed
|
||
// is stable and diffable.
|
||
const baseWeight = 1.5 + ((i * 37) % 250) / 20; // ~1.5g .. ~14g
|
||
const wagePercent = (6 + ((i * 13) % 12)).toFixed(1); // 6.0% .. 17.9%
|
||
const qty = (i * 7) % 15; // 0..14, so some are genuinely out of stock
|
||
const isPreOrder = i % 9 === 0;
|
||
|
||
const product = await prisma.product.upsert({
|
||
where: { id: productId },
|
||
update: {},
|
||
create: {
|
||
id: productId,
|
||
title,
|
||
description: \`\${noun} با طراحی \${adjective}، مناسب استفاده روزمره یا هدیه.\`,
|
||
categoryId: cat.id,
|
||
brandId,
|
||
productCode: \`P-\${String(i + 1).padStart(4, '0')}\`,
|
||
},
|
||
});
|
||
|
||
const variantId = \`\${productId}-variant-1\`;
|
||
await prisma.productVariant.upsert({
|
||
where: { id: variantId },
|
||
update: {},
|
||
create: {
|
||
id: variantId,
|
||
productId: product.id,
|
||
title: 'استاندارد',
|
||
sku: \`MOCK-\${String(i + 1).padStart(4, '0')}\`,
|
||
rashWeightGrams: baseWeight.toFixed(3),
|
||
defaultWagePercent: wagePercent,
|
||
qty,
|
||
isPreOrder,
|
||
},
|
||
});
|
||
|
||
// A second variant on ~1 in 4 products, so the "\u062a\u0646\u0648\u0639 \u0648\u0632\u0646\u06cc" chip row has
|
||
// something real to show on more than the 5 hand-authored products.
|
||
if (i % 4 === 0) {
|
||
const variant2Id = \`\${productId}-variant-2\`;
|
||
await prisma.productVariant.upsert({
|
||
where: { id: variant2Id },
|
||
update: {},
|
||
create: {
|
||
id: variant2Id,
|
||
productId: product.id,
|
||
title: 'سایز بزرگ',
|
||
sku: \`MOCK-\${String(i + 1).padStart(4, '0')}-L\`,
|
||
rashWeightGrams: (baseWeight * 1.35).toFixed(3),
|
||
defaultWagePercent: wagePercent,
|
||
qty: (qty + 3) % 15,
|
||
isPreOrder,
|
||
},
|
||
});
|
||
}
|
||
|
||
const imgIndex = i % 6;
|
||
const imageUrl = \`/img/products/\${cat.slug}-\${imgIndex}.svg\`;
|
||
await prisma.productImage.upsert({
|
||
where: { id: \`\${productId}-img-1\` },
|
||
update: { url: imageUrl },
|
||
create: {
|
||
id: \`\${productId}-img-1\`,
|
||
productId: product.id,
|
||
url: imageUrl,
|
||
sortOrder: 0,
|
||
},
|
||
});
|
||
mockImageCount += 1;
|
||
}
|
||
imageCount += mockImageCount;
|
||
|
||
// \u2500\u2500 Featured collection`;
|
||
|
||
content = content.replace(marker, insertion);
|
||
fs.writeFileSync(seedPath, content, 'utf-8');
|
||
console.log('inserted mock product generator into seed.ts');
|