routes fixed - user based fixed done
This commit is contained in:
@@ -1,62 +1,14 @@
|
||||
import { Router } from "express";
|
||||
import type { Request, Response } from "express";
|
||||
import { storage } from "../storage";
|
||||
import {
|
||||
AppointmentUncheckedCreateInputObjectSchema,
|
||||
PatientUncheckedCreateInputObjectSchema,
|
||||
} from "@repo/db/usedSchemas";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
insertAppointmentSchema,
|
||||
updateAppointmentSchema,
|
||||
} from "@repo/db/types";
|
||||
|
||||
const router = Router();
|
||||
|
||||
//creating types out of schema auto generated.
|
||||
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
|
||||
|
||||
const insertAppointmentSchema = (
|
||||
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;
|
||||
|
||||
const updateAppointmentSchema = (
|
||||
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
)
|
||||
.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
})
|
||||
.partial();
|
||||
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;
|
||||
|
||||
const PatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
appointments: true,
|
||||
});
|
||||
type Patient = z.infer<typeof PatientSchema>;
|
||||
|
||||
const insertPatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
type InsertPatient = z.infer<typeof insertPatientSchema>;
|
||||
|
||||
const updatePatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
)
|
||||
.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
userId: true,
|
||||
})
|
||||
.partial();
|
||||
|
||||
type UpdatePatient = z.infer<typeof updatePatientSchema>;
|
||||
|
||||
// Get all appointments
|
||||
router.get("/all", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
@@ -162,9 +114,7 @@ router.get("/appointments/recent", async (req: Request, res: Response) => {
|
||||
const offset = Math.max(0, parseInt(req.query.offset as string) || 0);
|
||||
|
||||
const all = await storage.getRecentAppointments(limit, offset);
|
||||
const filtered = all.filter((a) => a.userId === req.user!.id);
|
||||
|
||||
res.json({ data: filtered, limit, offset });
|
||||
res.json({ data: all, limit, offset });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: "Failed to get recent appointments" });
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@ router.get("/recent", async (req: Request, res: Response) => {
|
||||
const offset = parseInt(req.query.offset as string) || 0;
|
||||
|
||||
const [claims, totalCount] = await Promise.all([
|
||||
storage.getRecentClaimsByUser(req.user!.id, limit, offset),
|
||||
storage.getTotalClaimCountByUser(req.user!.id),
|
||||
storage.getRecentClaims(limit, offset),
|
||||
storage.getTotalClaimCount(),
|
||||
]);
|
||||
|
||||
res.json({ claims, totalCount });
|
||||
@@ -210,13 +210,13 @@ router.get(
|
||||
}
|
||||
);
|
||||
|
||||
// Get all claims for the logged-in user
|
||||
// Get all claims count.
|
||||
router.get("/all", async (req: Request, res: Response) => {
|
||||
try {
|
||||
const claims = await storage.getTotalClaimCountByUser(req.user!.id);
|
||||
const claims = await storage.getTotalClaimCount();
|
||||
res.json(claims);
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to retrieve claims" });
|
||||
res.status(500).json({ message: "Failed to retrieve claims count" });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,45 +1,50 @@
|
||||
import express, { Request, Response, NextFunction } from "express";
|
||||
import express, { Request, Response } from "express";
|
||||
import { storage } from "../storage";
|
||||
import { InsuranceCredentialUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
insertInsuranceCredentialSchema,
|
||||
InsuranceCredential,
|
||||
} from "@repo/db/types";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// ✅ Types
|
||||
type InsuranceCredential = z.infer<typeof InsuranceCredentialUncheckedCreateInputObjectSchema>;
|
||||
|
||||
const insertInsuranceCredentialSchema = (
|
||||
InsuranceCredentialUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({ id: true });
|
||||
|
||||
type InsertInsuranceCredential = z.infer<typeof insertInsuranceCredentialSchema>;
|
||||
|
||||
// ✅ Get all credentials for a user
|
||||
router.get("/", async (req: Request, res: Response):Promise<any> => {
|
||||
router.get("/", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
if (!req.user || !req.user.id) {
|
||||
return res.status(401).json({ message: "Unauthorized: user info missing" });
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Unauthorized: user info missing" });
|
||||
}
|
||||
const userId = req.user.id;
|
||||
|
||||
const credentials = await storage.getInsuranceCredentialsByUser(userId);
|
||||
return res.status(200).json(credentials);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to fetch credentials", details: String(err) });
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to fetch credentials", details: String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Create credential for a user
|
||||
router.post("/", async (req: Request, res: Response):Promise<any> => {
|
||||
router.post("/", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
if (!req.user || !req.user.id) {
|
||||
return res.status(401).json({ message: "Unauthorized: user info missing" });
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Unauthorized: user info missing" });
|
||||
}
|
||||
const userId = req.user.id;
|
||||
|
||||
const parseResult = insertInsuranceCredentialSchema.safeParse({ ...req.body, userId });
|
||||
const parseResult = insertInsuranceCredentialSchema.safeParse({
|
||||
...req.body,
|
||||
userId,
|
||||
});
|
||||
if (!parseResult.success) {
|
||||
const flat = (parseResult as typeof parseResult & { error: z.ZodError<any> }).error.flatten();
|
||||
const flat = (
|
||||
parseResult as typeof parseResult & { error: z.ZodError<any> }
|
||||
).error.flatten();
|
||||
const firstError =
|
||||
Object.values(flat.fieldErrors)[0]?.[0] || "Invalid input";
|
||||
|
||||
@@ -49,20 +54,24 @@ router.post("/", async (req: Request, res: Response):Promise<any> => {
|
||||
});
|
||||
}
|
||||
|
||||
const credential = await storage.createInsuranceCredential(parseResult.data);
|
||||
const credential = await storage.createInsuranceCredential(
|
||||
parseResult.data
|
||||
);
|
||||
return res.status(201).json(credential);
|
||||
} catch (err:any) {
|
||||
} catch (err: any) {
|
||||
if (err.code === "P2002") {
|
||||
return res.status(400).json({
|
||||
message: `Credential with this ${err.meta?.target?.join(", ")} already exists.`,
|
||||
});
|
||||
}
|
||||
return res.status(500).json({ error: "Failed to create credential", details: String(err) });
|
||||
return res.status(400).json({
|
||||
message: `Credential with this ${err.meta?.target?.join(", ")} already exists.`,
|
||||
});
|
||||
}
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to create credential", details: String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Update credential
|
||||
router.put("/:id", async (req: Request, res: Response):Promise<any> => {
|
||||
router.put("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const id = Number(req.params.id);
|
||||
if (isNaN(id)) return res.status(400).send("Invalid credential ID");
|
||||
@@ -71,20 +80,45 @@ router.put("/:id", async (req: Request, res: Response):Promise<any> => {
|
||||
const credential = await storage.updateInsuranceCredential(id, updates);
|
||||
return res.status(200).json(credential);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to update credential", details: String(err) });
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to update credential", details: String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Delete a credential
|
||||
router.delete("/:id", async (req: Request, res: Response):Promise<any> => {
|
||||
router.delete("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = (req as any).user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const id = Number(req.params.id);
|
||||
if (isNaN(id)) return res.status(400).send("Invalid ID");
|
||||
|
||||
await storage.deleteInsuranceCredential(id);
|
||||
// 1) Check existence
|
||||
const existing = await storage.getInsuranceCredential(userId);
|
||||
if (!existing)
|
||||
return res.status(404).json({ message: "Credential not found" });
|
||||
|
||||
// 2) Ownership check
|
||||
if (existing.userId !== userId) {
|
||||
return res
|
||||
.status(403)
|
||||
.json({ message: "Forbidden: Not your credential" });
|
||||
}
|
||||
|
||||
// 3) Delete (storage method enforces userId + id)
|
||||
const ok = await storage.deleteInsuranceCredential(userId, id);
|
||||
if (!ok) {
|
||||
return res
|
||||
.status(404)
|
||||
.json({ message: "Credential not found or already deleted" });
|
||||
}
|
||||
return res.status(204).send();
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to delete credential", details: String(err) });
|
||||
return res
|
||||
.status(500)
|
||||
.json({ error: "Failed to delete credential", details: String(err) });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,34 +1,69 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { prisma } from "@repo/db/client";
|
||||
import { storage } from "../storage";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
const userId = (req as any).user?.id;
|
||||
const notifications = await prisma.notification.findMany({
|
||||
where: { userId },
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 20,
|
||||
});
|
||||
res.json(notifications);
|
||||
router.get("/", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = (req as any).user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const notifications = await storage.getNotifications(userId, 20, 0);
|
||||
res.json(notifications);
|
||||
} catch (err) {
|
||||
console.error("Failed to fetch notifications:", err);
|
||||
res.status(500).json({ message: "Failed to fetch notifications" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/:id/read", async (req, res) => {
|
||||
const userId = (req as any).user?.id;
|
||||
await prisma.notification.updateMany({
|
||||
where: { id: Number(req.params.id), userId },
|
||||
data: { read: true },
|
||||
});
|
||||
res.json({ success: true });
|
||||
// Mark one notification as read
|
||||
router.post("/:id/read", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = (req as any).user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const success = await storage.markNotificationRead(
|
||||
userId,
|
||||
Number(req.params.id)
|
||||
);
|
||||
|
||||
if (!success)
|
||||
return res.status(404).json({ message: "Notification not found" });
|
||||
res.json({ success: true });
|
||||
} catch (err) {
|
||||
console.error("Failed to mark notification as read:", err);
|
||||
res.status(500).json({ message: "Failed to mark notification as read" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/read-all", async (req, res) => {
|
||||
const userId = (req as any).user?.id;
|
||||
await prisma.notification.updateMany({
|
||||
where: { userId },
|
||||
data: { read: true },
|
||||
});
|
||||
res.json({ success: true });
|
||||
// Mark all notifications as read
|
||||
router.post("/read-all", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = (req as any).user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const count = await storage.markAllNotificationsRead(userId);
|
||||
res.json({ success: true, updatedCount: count });
|
||||
} catch (err) {
|
||||
console.error("Failed to mark all notifications read:", err);
|
||||
res.status(500).json({ message: "Failed to mark all notifications read" });
|
||||
}
|
||||
});
|
||||
|
||||
router.delete(
|
||||
"/delete-all",
|
||||
async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = (req as any).user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const deletedCount = await storage.deleteAllNotifications(userId);
|
||||
res.json({ success: true, deletedCount });
|
||||
} catch (err) {
|
||||
console.error("Failed to delete notifications:", err);
|
||||
res.status(500).json({ message: "Failed to delete notifications" });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,63 +1,11 @@
|
||||
import { Router } from "express";
|
||||
import type { Request, Response } from "express";
|
||||
import { storage } from "../storage";
|
||||
import {
|
||||
AppointmentUncheckedCreateInputObjectSchema,
|
||||
PatientUncheckedCreateInputObjectSchema,
|
||||
} from "@repo/db/usedSchemas";
|
||||
import { z } from "zod";
|
||||
import { extractDobParts } from "../utils/DobParts";
|
||||
import { insertPatientSchema, updatePatientSchema } from "@repo/db/types";
|
||||
|
||||
const router = Router();
|
||||
|
||||
//creating types out of schema auto generated.
|
||||
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
|
||||
|
||||
const insertAppointmentSchema = (
|
||||
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;
|
||||
|
||||
const updateAppointmentSchema = (
|
||||
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
)
|
||||
.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
})
|
||||
.partial();
|
||||
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;
|
||||
|
||||
const PatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
appointments: true,
|
||||
});
|
||||
type Patient = z.infer<typeof PatientSchema>;
|
||||
|
||||
const insertPatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
type InsertPatient = z.infer<typeof insertPatientSchema>;
|
||||
|
||||
const updatePatientSchema = (
|
||||
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||
)
|
||||
.omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
userId: true,
|
||||
})
|
||||
.partial();
|
||||
|
||||
type UpdatePatient = z.infer<typeof updatePatientSchema>;
|
||||
|
||||
// Patient Routes
|
||||
// Get all patients for the logged-in user
|
||||
router.get("/", async (req, res) => {
|
||||
@@ -100,9 +48,7 @@ router.get("/search", async (req: Request, res: Response): Promise<any> => {
|
||||
offset = "0",
|
||||
} = req.query as Record<string, string>;
|
||||
|
||||
const filters: any = {
|
||||
userId: req.user!.id,
|
||||
};
|
||||
const filters: any = {};
|
||||
|
||||
if (term) {
|
||||
filters.OR = [
|
||||
@@ -159,28 +105,30 @@ router.get("/search", async (req: Request, res: Response): Promise<any> => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// get patient by insurance id
|
||||
router.get("/by-insurance-id", async (req: Request, res: Response): Promise<any> => {
|
||||
const insuranceId = req.query.insuranceId?.toString();
|
||||
router.get(
|
||||
"/by-insurance-id",
|
||||
async (req: Request, res: Response): Promise<any> => {
|
||||
const insuranceId = req.query.insuranceId?.toString();
|
||||
|
||||
if (!insuranceId) {
|
||||
return res.status(400).json({ error: "Missing insuranceId" });
|
||||
}
|
||||
|
||||
try {
|
||||
const patient = await storage.getPatientByInsuranceId(insuranceId);
|
||||
|
||||
if (patient) {
|
||||
return res.status(200).json(patient);
|
||||
} else {
|
||||
return res.status(200).json(null);
|
||||
if (!insuranceId) {
|
||||
return res.status(400).json({ error: "Missing insuranceId" });
|
||||
}
|
||||
|
||||
try {
|
||||
const patient = await storage.getPatientByInsuranceId(insuranceId);
|
||||
|
||||
if (patient) {
|
||||
return res.status(200).json(patient);
|
||||
} else {
|
||||
return res.status(200).json(null);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to lookup patient:", err);
|
||||
return res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to lookup patient:", err);
|
||||
return res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
// Get a single patient by ID
|
||||
router.get(
|
||||
@@ -334,12 +282,12 @@ router.delete(
|
||||
}
|
||||
|
||||
if (existingPatient.userId !== req.user!.id) {
|
||||
console.warn(
|
||||
`User ${req.user!.id} tried to delete patient ${patientId} owned by ${existingPatient.userId}`
|
||||
);
|
||||
return res
|
||||
.status(403)
|
||||
.json({ message: "Forbidden: Patient belongs to a different user" });
|
||||
.json({
|
||||
message:
|
||||
"Forbidden: Patient belongs to a different user, you can't delete this.",
|
||||
});
|
||||
}
|
||||
|
||||
// Delete patient
|
||||
@@ -351,18 +299,6 @@ router.delete(
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Appointment Routes
|
||||
// Get all appointments for the logged-in user
|
||||
router.get("/appointments", async (req, res) => {
|
||||
try {
|
||||
const appointments = await storage.getAppointmentsByUserId(req.user!.id);
|
||||
res.json(appointments);
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Failed to retrieve appointments" });
|
||||
}
|
||||
});
|
||||
|
||||
// Get appointments for a specific patient
|
||||
router.get(
|
||||
"/:patientId/appointments",
|
||||
|
||||
@@ -46,15 +46,12 @@ const router = Router();
|
||||
// GET /api/payments/recent
|
||||
router.get("/recent", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const limit = parseInt(req.query.limit as string) || 10;
|
||||
const offset = parseInt(req.query.offset as string) || 0;
|
||||
|
||||
const [payments, totalCount] = await Promise.all([
|
||||
storage.getRecentPaymentsByUser(userId, limit, offset),
|
||||
storage.getTotalPaymentCountByUser(userId),
|
||||
storage.getRecentPayments(limit, offset),
|
||||
storage.getTotalPaymentCount(),
|
||||
]);
|
||||
|
||||
res.status(200).json({ payments, totalCount });
|
||||
@@ -69,9 +66,6 @@ router.get(
|
||||
"/claim/:claimId",
|
||||
async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const parsedClaimId = parseIntOrError(req.params.claimId, "Claim ID");
|
||||
|
||||
const payments = await storage.getPaymentsByClaimId(parsedClaimId);
|
||||
@@ -122,9 +116,6 @@ router.get(
|
||||
// GET /api/payments/filter
|
||||
router.get("/filter", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const validated = paymentFilterSchema.safeParse(req.query);
|
||||
if (!validated.success) {
|
||||
return res.status(400).json({
|
||||
@@ -148,9 +139,6 @@ router.get("/filter", async (req: Request, res: Response): Promise<any> => {
|
||||
// GET /api/payments/:id
|
||||
router.get("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user?.id;
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const id = parseIntOrError(req.params.id, "Payment ID");
|
||||
|
||||
const payment = await storage.getPaymentById(id);
|
||||
@@ -351,6 +339,19 @@ router.delete("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
if (!userId) return res.status(401).json({ message: "Unauthorized" });
|
||||
|
||||
const id = parseIntOrError(req.params.id, "Payment ID");
|
||||
|
||||
// Check if payment exists and belongs to this user
|
||||
const existingPayment = await storage.getPayment(id);
|
||||
if (!existingPayment) {
|
||||
return res.status(404).json({ message: "Payment not found" });
|
||||
}
|
||||
|
||||
if (existingPayment.userId !== req.user!.id) {
|
||||
return res.status(403).json({
|
||||
message:
|
||||
"Forbidden: Payment belongs to a different user, you can't delete this.",
|
||||
});
|
||||
}
|
||||
await storage.deletePayment(id, userId);
|
||||
|
||||
res.status(200).json({ message: "Payment deleted successfully" });
|
||||
|
||||
@@ -57,13 +57,43 @@ router.put("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
}
|
||||
});
|
||||
|
||||
const parseIdOr400 = (raw: any, label: string) => {
|
||||
const n = Number(raw);
|
||||
if (!Number.isFinite(n)) throw new Error(`${label} is invalid`);
|
||||
return n;
|
||||
};
|
||||
|
||||
router.delete("/:id", async (req: Request, res: Response): Promise<any> => {
|
||||
try {
|
||||
const userId = req.user!.id;
|
||||
const id = parseIdOr400(req.params.id, "Staff ID");
|
||||
const parsedStaffId = Number(req.params.id);
|
||||
if (isNaN(parsedStaffId)) {
|
||||
return res.status(400).send("Invalid staff ID");
|
||||
}
|
||||
|
||||
const existing = await storage.getStaff(id); // must include createdById
|
||||
if (!existing) return res.status(404).json({ message: "Staff not found" });
|
||||
|
||||
if (existing.userId !== userId) {
|
||||
return res.status(403).json({
|
||||
message:
|
||||
"Forbidden: Staff was created by a different user; you cannot delete it.",
|
||||
});
|
||||
}
|
||||
|
||||
const [apptCount, claimCount] = await Promise.all([
|
||||
storage.countAppointmentsByStaffId(id),
|
||||
storage.countClaimsByStaffId(id),
|
||||
]);
|
||||
|
||||
if (apptCount || claimCount) {
|
||||
return res.status(409).json({
|
||||
message: `Cannot delete staff with linked records. Appointment of this staff : ${apptCount} and Claims ${claimCount}`,
|
||||
hint: "Archive this staff, or reassign linked records, then delete.",
|
||||
});
|
||||
}
|
||||
|
||||
const deleted = await storage.deleteStaff(parsedStaffId);
|
||||
if (!deleted) return res.status(404).send("Staff not found");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user