Files
boka-gasol247/prisma/seed.ts
2026-05-22 10:50:48 +02:00

122 lines
3.8 KiB
TypeScript
Raw Permalink 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 bcrypt from 'bcryptjs';
const prisma = new PrismaClient();
async function main() {
// -- Settings singleton --
await prisma.settings.upsert({
where: { id: 'singleton' },
update: {},
create: { id: 'singleton', pickupEnabled: true },
});
console.log('✓ Settings singleton ensured');
// -- Initial admin --
const email = (process.env.SEED_ADMIN_EMAIL ?? 'admin@example.com').toLowerCase();
const password = process.env.SEED_ADMIN_PASSWORD ?? 'change-me';
const name = process.env.SEED_ADMIN_NAME ?? 'Admin';
const passwordHash = await bcrypt.hash(password, 12);
await prisma.admin.upsert({
where: { email },
update: {},
create: { email, name, passwordHash },
});
console.log(`✓ Admin ensured: ${email}`);
// -- Products (example LPG cylinders) --
const products = [
{
sku: 'P6',
nameSv: 'Gasoltub P6',
nameEn: 'LPG cylinder P6',
descriptionSv: '6 kg gasol — för mindre kök och campingkök.',
descriptionEn: '6 kg LPG — for smaller stoves and camping cooktops.',
priceOre: 39900, // 399 kr
sortOrder: 10,
},
{
sku: 'P11',
nameSv: 'Gasoltub P11',
nameEn: 'LPG cylinder P11',
descriptionSv: '11 kg gasol — vanligaste storleken för matlagning på läger.',
descriptionEn: '11 kg LPG — most common size for cooking at camps.',
priceOre: 64900, // 649 kr
sortOrder: 20,
},
{
sku: 'P19',
nameSv: 'Gasoltub P19',
nameEn: 'LPG cylinder P19',
descriptionSv: '19 kg gasol — för större kök eller längre vistelse.',
descriptionEn: '19 kg LPG — for larger kitchens or longer stays.',
priceOre: 99900, // 999 kr
sortOrder: 30,
},
];
for (const p of products) {
await prisma.product.upsert({
where: { sku: p.sku },
update: {
nameSv: p.nameSv,
nameEn: p.nameEn,
descriptionSv: p.descriptionSv,
descriptionEn: p.descriptionEn,
priceOre: p.priceOre,
sortOrder: p.sortOrder,
},
create: { ...p, active: true, vatBp: 2500 },
});
}
console.log(`✓ Seeded ${products.length} products`);
// -- Pickup slots (example: 3 days × 2 slots) --
const existing = await prisma.pickupSlot.count();
if (existing === 0) {
const baseDay = new Date();
baseDay.setUTCHours(8, 0, 0, 0);
// Place slots ~6 months out so they don't expire immediately.
baseDay.setUTCMonth(baseDay.getUTCMonth() + 6);
const slots = [
{ offsetDays: 0, startH: 9, endH: 12, labelSv: 'Dag 1 — Förmiddag', labelEn: 'Day 1 — Morning' },
{ offsetDays: 0, startH: 13, endH: 17, labelSv: 'Dag 1 — Eftermiddag', labelEn: 'Day 1 — Afternoon' },
{ offsetDays: 1, startH: 9, endH: 12, labelSv: 'Dag 2 — Förmiddag', labelEn: 'Day 2 — Morning' },
{ offsetDays: 1, startH: 13, endH: 17, labelSv: 'Dag 2 — Eftermiddag', labelEn: 'Day 2 — Afternoon' },
{ offsetDays: 2, startH: 9, endH: 12, labelSv: 'Dag 3 — Förmiddag', labelEn: 'Day 3 — Morning' },
];
for (const s of slots) {
const startsAt = new Date(baseDay);
startsAt.setUTCDate(baseDay.getUTCDate() + s.offsetDays);
startsAt.setUTCHours(s.startH, 0, 0, 0);
const endsAt = new Date(startsAt);
endsAt.setUTCHours(s.endH, 0, 0, 0);
await prisma.pickupSlot.create({
data: {
labelSv: s.labelSv,
labelEn: s.labelEn,
startsAt,
endsAt,
capacity: 50,
active: true,
},
});
}
console.log(`✓ Seeded ${slots.length} pickup slots`);
} else {
console.log(`• Pickup slots already exist (${existing}) — skipping`);
}
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});