"use server"; import { auth } from "@/auth"; import { prisma } from "@/lib/db/prisma"; import { Permission } from "@/generated/prisma/enums"; import { assertOwnerPermission, OwnerPermissionDeniedError } from "@/features/owner/authorization"; import { writeAuditLog } from "@/lib/audit/write-audit-log"; import { setOpeningHours, updateBusinessProfile, updateBusinessSettings, } from "@/services/business/business.service"; import type { BusinessLocationInput, BusinessProfileInput, BusinessSettingsInput, OpeningHoursDayInput } from "@/services/business/business.service"; export interface BusinessActionResult { success: boolean; error?: string; } async function requireBusinessManager() { const session = await auth(); if (!session?.user) return { staff: null, error: "You must be signed in." } as const; try { await assertOwnerPermission(session.user.id, Permission.MANAGE_BUSINESS_PROFILE); } catch (error) { if (error instanceof OwnerPermissionDeniedError) return { staff: null, error: error.message } as const; throw error; } const staff = await prisma.staffProfile.findUnique({ where: { userId: session.user.id } }); if (!staff) return { staff: null, error: "You must be signed in as staff." } as const; return { staff, error: null } as const; } export async function updateBusinessProfileAction(params: { profile: BusinessProfileInput; location: BusinessLocationInput; }): Promise { const { staff, error } = await requireBusinessManager(); if (!staff) return { success: false, error: error ?? "Not authorized." }; const result = await updateBusinessProfile(prisma, { businessId: staff.businessId, ...params }); if (!result.success) { return { success: false, error: result.validation.issues[0]?.message ?? "Couldn't save business details." }; } await writeAuditLog(prisma, { actorUserId: staff.userId, action: "BUSINESS_PROFILE_UPDATED", entityType: "Business", entityId: staff.businessId, metadata: { name: params.profile.name }, }); return { success: true }; } export async function updateBusinessSettingsAction(settings: BusinessSettingsInput): Promise { const { staff, error } = await requireBusinessManager(); if (!staff) return { success: false, error: error ?? "Not authorized." }; await updateBusinessSettings(prisma, { businessId: staff.businessId, settings }); await writeAuditLog(prisma, { actorUserId: staff.userId, action: "BUSINESS_SETTINGS_UPDATED", entityType: "BusinessSettings", entityId: staff.businessId, }); return { success: true }; } export interface OpeningHoursActionResult { success: boolean; error?: string; conflicts?: { id: string; customerName: string; serviceNames: string; startAt: string; staffName: string }[]; } export async function updateOpeningHoursAction( days: OpeningHoursDayInput[], acknowledgeConflicts?: boolean, ): Promise { const { staff, error } = await requireBusinessManager(); if (!staff) return { success: false, error: error ?? "Not authorized." }; const business = await prisma.business.findUnique({ where: { id: staff.businessId }, select: { timezone: true } }); if (!business) return { success: false, error: "Business not found." }; const result = await setOpeningHours(prisma, { businessId: staff.businessId, businessTimezone: business.timezone, days, acknowledgeConflicts, }); if (!result.success) { return { success: false, error: result.validation.issues[0]?.message ?? "Couldn't save opening hours.", conflicts: result.conflicts.map((c) => ({ id: c.id, customerName: `${c.customer.firstName} ${c.customer.lastName}`, serviceNames: c.services.map((s) => s.service.name).join(" + "), startAt: c.startAt.toISOString(), staffName: c.staff.user.name ?? "Staff", })), }; } await writeAuditLog(prisma, { actorUserId: staff.userId, action: "BUSINESS_HOURS_UPDATED", entityType: "BusinessHours", entityId: staff.businessId, }); return { success: true }; }