feat: save insurance PDFs (eligibility/claims/preauth) to Cloud Storage instead of Postgres blobs

New saves go into the patient's Cloud Storage folder under category subfolders
(Eligibility/Claims/PreAuth/Claim Status/Attachments) via a new
storage.savePdfToCloudStorage helper, instead of the legacy PdfGroup/PdfFile
Postgres blob tables. Old records and their read paths are left untouched for
backward compatibility; PDF list/content/delete endpoints and viewers now
transparently handle both legacy numeric ids and new "cloud:<id>" ids.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 00:20:37 -04:00
co-authored by Claude Sonnet 5
parent 1190bc0494
commit 99cdfa702a
36 changed files with 496 additions and 296 deletions
@@ -143,6 +143,24 @@ export interface IStorage {
patientId: number,
patientName: string
): Promise<CloudFolder>;
getOrCreateSubfolder(
userId: number,
parentId: number,
name: string
): Promise<CloudFolder>;
savePdfToCloudStorage(
userId: number,
patientId: number,
patientName: string,
category: "Eligibility" | "Claims" | "PreAuth" | "Claim Status" | "Attachments",
filename: string,
buffer: Buffer,
mimeType?: string
): Promise<CloudFile>;
listPatientCategoryCloudFiles(
patientId: number,
category: string
): Promise<CloudFile[]>;
}
/* ------------------------------- Implementation ------------------------------- */
@@ -546,6 +564,82 @@ export const cloudStorageStorage: IStorage = {
return created as unknown as CloudFolder;
},
async getOrCreateSubfolder(userId: number, parentId: number, name: string) {
const existing = await db.cloudFolder.findFirst({
where: { parentId, name },
});
if (existing) return existing as unknown as CloudFolder;
try {
return await cloudStorageStorage.createFolder(userId, name, parentId);
} catch (err: any) {
// unique constraint on [userId, parentId, name] - another request created it first
if (err?.code === "P2002") {
const race = await db.cloudFolder.findFirst({ where: { parentId, name } });
if (race) return race as unknown as CloudFolder;
}
throw err;
}
},
async savePdfToCloudStorage(
userId: number,
patientId: number,
patientName: string,
category: "Eligibility" | "Claims" | "PreAuth" | "Claim Status" | "Attachments",
filename: string,
buffer: Buffer,
mimeType: string = "application/pdf"
) {
const patientFolder = await cloudStorageStorage.getOrCreatePatientFolder(
userId,
patientId,
patientName
);
const subfolder = await cloudStorageStorage.getOrCreateSubfolder(
userId,
patientFolder.id!,
category
);
const cloudFile = await cloudStorageStorage.initializeFileUpload(
userId,
filename,
mimeType,
BigInt(buffer.length),
1,
subfolder.id!
);
await cloudStorageStorage.appendFileChunk(cloudFile.id!, 0, buffer);
await cloudStorageStorage.finalizeFileUpload(cloudFile.id!);
const finalFile = await cloudStorageStorage.getFile(cloudFile.id!);
if (!finalFile) throw new Error("Failed to finalize PDF upload to cloud storage");
return finalFile;
},
async listPatientCategoryCloudFiles(patientId: number, category: string) {
const patientFolder = await db.cloudFolder.findFirst({ where: { patientId } });
if (!patientFolder) return [];
const subfolder = await db.cloudFolder.findFirst({
where: { parentId: patientFolder.id, name: category },
});
if (!subfolder) return [];
const files = await db.cloudFile.findMany({
where: { folderId: subfolder.id, isComplete: true },
orderBy: { createdAt: "desc" },
select: {
id: true,
name: true,
mimeType: true,
fileSize: true,
folderId: true,
isComplete: true,
createdAt: true,
updatedAt: true,
},
});
return files.map(serializeFile) as unknown as CloudFile[];
},
// --- STREAM ---
async streamFileTo(resStream: NodeJS.WritableStream, fileId: number) {
const file = await db.cloudFile.findUnique({