fix: BCBS MA — identify patient by member ID + DOB, prevent overwriting subscriber
- Added getPatientByInsuranceIdAndDob to storage - Processor uses insuranceId + DOB as unique key instead of insuranceId alone - Dependent with same subscriber ID but different DOB gets a new patient record (bypasses createOrUpdatePatientByInsuranceId which would overwrite subscriber) - Name extraction anchored to "Relationship:" to scope Patient Info column only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,10 +63,45 @@ async function processBcbsMaResult(
|
||||
? seleniumResult.lastName.trim()
|
||||
: (formLastName ?? "");
|
||||
|
||||
await createOrUpdatePatientByInsuranceId({ insuranceId, firstName, lastName, dob: formDob, userId });
|
||||
|
||||
const normalizedInsuranceId = insuranceId.replace(/\s+/g, "");
|
||||
const patient = await storage.getPatientByInsuranceId(normalizedInsuranceId);
|
||||
|
||||
// Identify patient by member ID + DOB — not member ID alone.
|
||||
// Dependents (e.g. Maria) share the subscriber's member ID but have a different DOB.
|
||||
const dobDate = formDob ? new Date(formDob) : null;
|
||||
|
||||
let patient = dobDate
|
||||
? await storage.getPatientByInsuranceIdAndDob(normalizedInsuranceId, dobDate)
|
||||
: await storage.getPatientByInsuranceId(normalizedInsuranceId);
|
||||
|
||||
if (patient) {
|
||||
// Existing patient found by insuranceId + DOB — update name
|
||||
log("bcbs-ma-processor", `Patient matched by insuranceId+DOB id=${patient.id}`);
|
||||
await storage.updatePatient(patient.id, { firstName, lastName });
|
||||
} else {
|
||||
// No match — create a brand new patient record.
|
||||
// Do NOT use createOrUpdatePatientByInsuranceId here because it looks up by
|
||||
// insuranceId alone and would overwrite the subscriber (e.g. Hugo) instead of
|
||||
// creating a new record for the dependent (e.g. Maria).
|
||||
log("bcbs-ma-processor", "No patient matched by insuranceId+DOB — creating new patient record");
|
||||
try {
|
||||
await storage.createPatient({
|
||||
firstName,
|
||||
lastName,
|
||||
insuranceId: normalizedInsuranceId,
|
||||
dateOfBirth: dobDate ?? undefined,
|
||||
gender: "",
|
||||
phone: "",
|
||||
userId,
|
||||
} as any);
|
||||
} catch (createErr: any) {
|
||||
log("bcbs-ma-processor", `createPatient failed: ${createErr?.message}`, createErr);
|
||||
throw createErr;
|
||||
}
|
||||
patient = dobDate
|
||||
? await storage.getPatientByInsuranceIdAndDob(normalizedInsuranceId, dobDate)
|
||||
: await storage.getPatientByInsuranceId(normalizedInsuranceId);
|
||||
}
|
||||
|
||||
if (!patient?.id) {
|
||||
output.patientUpdateStatus = "Patient not found; no update performed";
|
||||
return output;
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface IStorage {
|
||||
// Patient methods
|
||||
getPatient(id: number): Promise<Patient | undefined>;
|
||||
getPatientByInsuranceId(insuranceId: string): Promise<Patient | null>;
|
||||
getPatientByInsuranceIdAndDob(insuranceId: string, dob: Date): Promise<Patient | null>;
|
||||
getAllPatients(): Promise<Patient[]>;
|
||||
getRecentPatients(limit: number, offset: number): Promise<Patient[]>;
|
||||
getPatientsByIds(ids: number[]): Promise<Patient[]>;
|
||||
@@ -60,6 +61,19 @@ export const patientsStorage: IStorage = {
|
||||
});
|
||||
},
|
||||
|
||||
async getPatientByInsuranceIdAndDob(insuranceId: string, dob: Date): Promise<Patient | null> {
|
||||
const startOfDay = new Date(dob);
|
||||
startOfDay.setHours(0, 0, 0, 0);
|
||||
const endOfDay = new Date(dob);
|
||||
endOfDay.setHours(23, 59, 59, 999);
|
||||
return db.patient.findFirst({
|
||||
where: {
|
||||
insuranceId,
|
||||
dateOfBirth: { gte: startOfDay, lte: endOfDay },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
async getRecentPatients(limit: number, offset: number): Promise<Patient[]> {
|
||||
return db.patient.findMany({
|
||||
skip: offset,
|
||||
|
||||
Reference in New Issue
Block a user