This commit is contained in:
Stefan Lazic committed 2026-08-03 21:15:24 +01:00
1 parent ec5583f972
commit 546613e677
189 files changed
+9873 -655

No files matched your search

+64 -3
View File
@@ -4,8 +4,10 @@
* every relation in the schema once, not a full demo dataset.
*/
import "dotenv/config";
import { PrismaClient, Permission, Weekday, RewardType } from "../generated/prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient, Permission, Weekday, RewardType, NotificationType } from "../generated/prisma/client";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import { buildMysqlPoolConfig } from "../src/lib/db/mysql-pool-config";
import { notifySafely } from "../src/services/notifications/notification.service";
import bcrypt from "bcryptjs";
/**
@@ -24,7 +26,7 @@ function minutesFromNow(minutes: number): Date {
return new Date(Date.now() + minutes * 60_000);
}
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
const adapter = new PrismaMariaDb(buildMysqlPoolConfig(process.env.DATABASE_URL));
const prisma = new PrismaClient({ adapter });
/**
@@ -952,6 +954,65 @@ async function main() {
}
}
// ── Phase 7: notification centre fixtures ──────────────────────────────
// Routed through the real notifySafely() rather than raw prisma.create()
// calls, so these get the exact same channel-resolution/idempotency
// behaviour a live booking would — a fresh checkout of this repo should
// show a populated notification bell for each role without needing to
// drive a real action first. Uses notifySafely (not notify) so a rerun
// of the seed never throws on the idempotency-key collision.
if (ownerUser.staffProfile && barberUser.staffProfile && registeredCustomer) {
await notifySafely(prisma, {
businessId: business.id,
type: NotificationType.BOOKING_CONFIRMED,
recipientUserId: registeredCustomerUser.id,
recipientCustomerId: registeredCustomer.id,
appointmentId: `${business.id}-appt-today-completed`,
subject: "Booking confirmed",
bodyText: `Your ${haircut.name} with ${ownerUser.name} is confirmed.`,
deepLinkPath: "/appointments",
idempotencyKey: `notify:booking-confirmed:${business.id}-appt-today-completed`,
});
await notifySafely(prisma, {
businessId: business.id,
type: NotificationType.LOYALTY_STAMP_ADDED,
recipientUserId: registeredCustomerUser.id,
recipientCustomerId: registeredCustomer.id,
subject: "You've earned a loyalty stamp",
bodyText: "You've earned a loyalty stamp. Keep it up!",
deepLinkPath: "/loyalty",
idempotencyKey: `notify:loyalty-stamp-added:seed-${registeredCustomer.id}`,
});
// Marked read immediately below — gives the notification centre a mix
// of read/unread state out of the box, matching real usage instead of
// "everything unread forever."
await prisma.notification.updateMany({
where: { idempotencyKey: `notify:loyalty-stamp-added:seed-${registeredCustomer.id}` },
data: { readAt: daysFromNow(-1, 9) },
});
await notifySafely(prisma, {
businessId: business.id,
type: NotificationType.STAFF_NEW_APPOINTMENT,
recipientUserId: barberUser.id,
appointmentId: `${business.id}-appt-today-checkedin`,
subject: "New appointment",
bodyText: `${secondCustomerUser.name ?? "A customer"} booked ${haircut.name}.`,
deepLinkPath: "/staff/current",
idempotencyKey: `notify:staff-new-appointment:${business.id}-appt-today-checkedin`,
});
await notifySafely(prisma, {
businessId: business.id,
type: NotificationType.OWNER_NEW_BOOKING,
recipientUserId: ownerUser.id,
appointmentId: `${business.id}-appt-today-checkedin`,
subject: "New booking",
bodyText: `${secondCustomerUser.name ?? "A customer"} booked ${haircut.name} with ${barberUser.name}.`,
deepLinkPath: "/owner/calendar",
idempotencyKey: `notify:owner-new-booking:${business.id}-appt-today-checkedin`,
});
}
console.log("Seed complete:", {
business: business.name,
roles: [ownerRole.name, barberRole.name],