fix: dedupe claim attachments to prevent duplicate uploads to insurance

Claim attachments were being appended without checking for existing
duplicates, causing files (e.g. the same PDF) to be sent to the
insurance clearinghouse multiple times.
This commit is contained in:
2026-07-04 14:17:40 -04:00
parent e7d610b970
commit 79bae13f35

View File

@@ -740,13 +740,16 @@ router.post(
if (saved) resolvedNpiProvider = saved;
}
// Collect attachments: appointment-level files + claim-level files
// Collect attachments: appointment-level files + claim-level files (deduped by filename+path)
const apptFiles = await storage.getAppointmentFiles(Number(apt.id));
const claimFiles = (activeClaim as any)?.claimFiles ?? [];
const allFileMeta = [
...apptFiles,
...claimFiles,
] as Array<{ filename: string; mimeType?: string | null; filePath?: string | null }>;
const seenFileKeys = new Set<string>();
const allFileMeta = [...apptFiles, ...claimFiles].filter((f: any) => {
const key = `${f.filename ?? ""}::${f.filePath ?? ""}`;
if (seenFileKeys.has(key)) return false;
seenFileKeys.add(key);
return true;
}) as Array<{ filename: string; mimeType?: string | null; filePath?: string | null }>;
const filesForQueue = allFileMeta.flatMap((f) => {
if (!f.filePath) return [];
@@ -1276,17 +1279,33 @@ router.put("/:id", async (req: Request, res: Response): Promise<any> => {
await syncAppointmentType(existingClaim.appointmentId, updatedCodes);
}
// If new claimFiles are provided, append them (don't delete existing ones)
// If new claimFiles are provided, append only ones not already attached to this claim
if (Array.isArray(req.body.claimFiles) && req.body.claimFiles.length > 0) {
const { prisma: db } = await import("@repo/db/client");
await db.claimFile.createMany({
data: req.body.claimFiles.map((f: any) => ({
claimId,
filename: String(f.filename || ""),
mimeType: String(f.mimeType || f.mime || ""),
...(f.filePath ? { filePath: String(f.filePath) } : {}),
})),
const existingFiles = await db.claimFile.findMany({
where: { claimId },
select: { filename: true, filePath: true },
});
const existingKeys = new Set(
existingFiles.map((f: any) => `${f.filename}::${f.filePath ?? ""}`)
);
const seenKeys = new Set<string>();
const newFiles = req.body.claimFiles.filter((f: any) => {
const key = `${String(f.filename || "")}::${String(f.filePath || "")}`;
if (existingKeys.has(key) || seenKeys.has(key)) return false;
seenKeys.add(key);
return true;
});
if (newFiles.length > 0) {
await db.claimFile.createMany({
data: newFiles.map((f: any) => ({
claimId,
filename: String(f.filename || ""),
mimeType: String(f.mimeType || f.mime || ""),
...(f.filePath ? { filePath: String(f.filePath) } : {}),
})),
});
}
}
// Explicitly pick only scalar fields — skip serviceLines and claimFiles (handled above)