mirror of
https://github.com/open-reception/appointment-booking-software.git
synced 2026-08-17 21:25:52 +02:00
Fix notifications to show appointment data; reverting comming a65c00bb8c and adding permission check
This commit is contained in:
@@ -1,11 +1,142 @@
|
||||
import { json } from "@sveltejs/kit";
|
||||
import { AppointmentService } from "$lib/server/services/appointment-service";
|
||||
import { BackendError, InternalError, logError, ValidationError } from "$lib/server/utils/errors";
|
||||
import {
|
||||
BackendError,
|
||||
InternalError,
|
||||
logError,
|
||||
NotFoundError,
|
||||
ValidationError,
|
||||
} from "$lib/server/utils/errors";
|
||||
import type { RequestHandler } from "@sveltejs/kit";
|
||||
import { registerOpenAPIRoute } from "$lib/server/openapi";
|
||||
import logger from "$lib/logger";
|
||||
import { checkPermission } from "$lib/server/utils/permissions";
|
||||
|
||||
// Register OpenAPI documentation for GET
|
||||
registerOpenAPIRoute("/tenants/{id}/appointments/{appointmentId}", "GET", {
|
||||
summary: "Get appointment by ID",
|
||||
description:
|
||||
"Retrieves a specific appointment by its ID. Accessible to dashboard users. Required for notification previews.",
|
||||
tags: ["Appointments"],
|
||||
parameters: [
|
||||
{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string", format: "uuid" },
|
||||
description: "Tenant ID",
|
||||
},
|
||||
{
|
||||
name: "appointmentId",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string", format: "uuid" },
|
||||
description: "Appointment ID",
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
"200": {
|
||||
description: "Appointment retrieved successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
appointment: {
|
||||
type: "object",
|
||||
properties: {
|
||||
id: { type: "string", format: "uuid", description: "Appointment ID" },
|
||||
tunnelId: { type: "string", format: "uuid", description: "Client tunnel ID" },
|
||||
channelId: { type: "string", format: "uuid", description: "Channel ID" },
|
||||
appointmentDate: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
description: "Appointment date and time",
|
||||
},
|
||||
expiryDate: {
|
||||
type: "string",
|
||||
format: "date",
|
||||
description: "Data expiry date (nullable)",
|
||||
},
|
||||
status: {
|
||||
type: "string",
|
||||
enum: ["NEW", "CONFIRMED", "HELD", "REJECTED", "NO_SHOW"],
|
||||
description: "Appointment status",
|
||||
},
|
||||
encryptedPayload: {
|
||||
type: "string",
|
||||
description: "Encrypted appointment data (nullable)",
|
||||
},
|
||||
iv: {
|
||||
type: "string",
|
||||
description: "Initialization vector for encryption (nullable)",
|
||||
},
|
||||
authTag: {
|
||||
type: "string",
|
||||
description: "Authentication tag for encryption (nullable)",
|
||||
},
|
||||
createdAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
description: "Creation timestamp (nullable)",
|
||||
},
|
||||
updatedAt: {
|
||||
type: "string",
|
||||
format: "date-time",
|
||||
description: "Last update timestamp (nullable)",
|
||||
},
|
||||
},
|
||||
required: ["id", "tunnelId", "channelId", "appointmentDate", "status"],
|
||||
},
|
||||
},
|
||||
required: ["appointment"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"400": {
|
||||
description: "Invalid input data",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
"401": {
|
||||
description: "Authentication required",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
"403": {
|
||||
description: "Insufficient permissions",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
"404": {
|
||||
description: "Appointment not found",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
"500": {
|
||||
description: "Internal server error",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: { $ref: "#/components/schemas/Error" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Register OpenAPI documentation for DELETE
|
||||
registerOpenAPIRoute("/tenants/{id}/appointments/{appointmentId}", "DELETE", {
|
||||
summary: "Delete appointment",
|
||||
@@ -85,6 +216,52 @@ registerOpenAPIRoute("/tenants/{id}/appointments/{appointmentId}", "DELETE", {
|
||||
},
|
||||
});
|
||||
|
||||
export const GET: RequestHandler = async ({ params, locals }) => {
|
||||
const log = logger.setContext("API");
|
||||
|
||||
try {
|
||||
const tenantId = params.id;
|
||||
const appointmentId = params.appointmentId;
|
||||
|
||||
if (!tenantId || !appointmentId) {
|
||||
throw new ValidationError("Tenant ID and appointment ID are required");
|
||||
}
|
||||
|
||||
checkPermission(locals, tenantId, true);
|
||||
|
||||
log.debug("Getting appointment by ID", {
|
||||
tenantId,
|
||||
appointmentId,
|
||||
requestedBy: locals.user?.id,
|
||||
});
|
||||
|
||||
const appointmentService = await AppointmentService.forTenant(tenantId);
|
||||
const appointment = await appointmentService.getAppointmentById(appointmentId);
|
||||
|
||||
if (!appointment) {
|
||||
throw new NotFoundError("Appointment not found");
|
||||
}
|
||||
|
||||
log.debug("Appointment retrieved successfully", {
|
||||
tenantId,
|
||||
appointmentId,
|
||||
requestedBy: locals.user?.id,
|
||||
});
|
||||
|
||||
return json({
|
||||
appointment,
|
||||
});
|
||||
} catch (error) {
|
||||
logError(log)("Error getting appointment", error, locals.user?.id, params.id);
|
||||
|
||||
if (error instanceof BackendError) {
|
||||
return error.toJson();
|
||||
}
|
||||
|
||||
return new InternalError().toJson();
|
||||
}
|
||||
};
|
||||
|
||||
export const DELETE: RequestHandler = async ({ params, locals }) => {
|
||||
const log = logger.setContext("API");
|
||||
|
||||
|
||||
@@ -381,7 +381,9 @@ export const POST: RequestHandler = async ({ request, params }) => {
|
||||
(await notificationService).createNotification({
|
||||
type: "APPOINTMENT_REQUESTED",
|
||||
channelId: validatedData.channelId,
|
||||
metaData: { appointmentId: result.id },
|
||||
metaData: {
|
||||
appointmentId: result.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (validatedData.clientEmail) {
|
||||
|
||||
Reference in New Issue
Block a user