Phase 7
This commit is contained in:
189 files changed
+9873
-655
No files matched your search
+64
-3
@@ -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],
|
||||
|
||||
Reference in new issue
Block a user