feat: route batch-column claims by insurance type, fix eligibility UX
- claims.ts: batch-column now routes each patient to the correct portal
(MH/CCA/DDMA/TuftsSCO/UnitedSCO) based on patient.insuranceProvider
- appointments-page.tsx: eligibility badge falls back to patientStatus
for all insurance types, not just MassHealth
- unitedDHClaimProcessor/ddmaClaimProcessor/tuftsSCOClaimProcessor:
auto-save claim PDF when no socketId (batch-column path)
- unitedSCOEligibilityProcessor: unknown eligibility no longer stored as INACTIVE
- queues.ts: add tuftssco-claim-submit and uniteddh-claim-submit to SeleniumJobType
- selenium_UnitedSCO_eligibilityCheckWorker.py:
- step1: add Select Insurance OK click with staleness wait; Provider &
Location page just clicks Continue; skip first/last name input
- step2: extract name from eligibility details tab (ALL CAPS → title case);
skip "not available" guard; fix name regex to match only all-caps words
- .gitignore: ignore all chrome_profile_* directories
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,8 @@ import {
|
||||
} from "../../services/seleniumDDMAClaimClient";
|
||||
import { io } from "../../socket";
|
||||
import { storage } from "../../storage";
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
|
||||
function log(tag: string, msg: string, ctx?: any) {
|
||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||
@@ -86,6 +88,21 @@ async function pollUntilDone(
|
||||
throw new Error(`DDMA claim polling exhausted all attempts for session ${sessionId}`);
|
||||
}
|
||||
|
||||
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||
try {
|
||||
const filename = path.basename(new URL(pdf_url).pathname);
|
||||
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||
if (!group) group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||
log("ddma-claim-processor", "PDF saved", { patientId, filename });
|
||||
} catch (err: any) {
|
||||
log("ddma-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||
}
|
||||
}
|
||||
|
||||
export interface DDMAClaimProcessorInput {
|
||||
enrichedPayload: any;
|
||||
userId: number;
|
||||
@@ -139,6 +156,13 @@ export async function runDDMAClaimProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||
if (pdf_url && !socketId) {
|
||||
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||
}
|
||||
|
||||
emitToSocket(socketId, "selenium:ddma_claim_completed", {
|
||||
jobId,
|
||||
claimId,
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
} from "../../services/seleniumTuftsSCOClaimClient";
|
||||
import { io } from "../../socket";
|
||||
import { storage } from "../../storage";
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
|
||||
function log(tag: string, msg: string, ctx?: any) {
|
||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||
@@ -85,6 +87,21 @@ async function pollUntilDone(
|
||||
throw new Error(`Tufts SCO claim polling exhausted all attempts for session ${sessionId}`);
|
||||
}
|
||||
|
||||
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||
try {
|
||||
const filename = path.basename(new URL(pdf_url).pathname);
|
||||
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||
if (!group) group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||
log("tuftssco-claim-processor", "PDF saved", { patientId, filename });
|
||||
} catch (err: any) {
|
||||
log("tuftssco-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||
}
|
||||
}
|
||||
|
||||
export interface TuftsSCOClaimProcessorInput {
|
||||
enrichedPayload: any;
|
||||
userId: number;
|
||||
@@ -130,6 +147,13 @@ export async function runTuftsSCOClaimProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||
if (pdf_url && !socketId) {
|
||||
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||
}
|
||||
|
||||
emitToSocket(socketId, "selenium:tuftssco_claim_completed", {
|
||||
jobId,
|
||||
claimId,
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
} from "../../services/seleniumUnitedDHClaimClient";
|
||||
import { io } from "../../socket";
|
||||
import { storage } from "../../storage";
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
|
||||
function log(tag: string, msg: string, ctx?: any) {
|
||||
console.log(`${new Date().toISOString()} [${tag}] ${msg}`, ctx ?? "");
|
||||
@@ -97,6 +99,24 @@ async function pollUntilDone(
|
||||
throw new Error(`UnitedDH claim polling exhausted all attempts for session ${sessionId}`);
|
||||
}
|
||||
|
||||
async function savePdfFromSelenium(pdf_url: string, patientId: number) {
|
||||
try {
|
||||
const filename = path.basename(new URL(pdf_url).pathname);
|
||||
const seleniumPort = process.env.SELENIUM_PORT || "5002";
|
||||
const localUrl = `http://localhost:${seleniumPort}/downloads/${filename}`;
|
||||
const resp = await axios.get(localUrl, { responseType: "arraybuffer", timeout: 30000 });
|
||||
|
||||
let group = await storage.findPdfGroupByPatientTitleKey(patientId, "INSURANCE_CLAIM");
|
||||
if (!group) {
|
||||
group = await storage.createPdfGroup(patientId, "Claims", "INSURANCE_CLAIM");
|
||||
}
|
||||
await storage.createPdfFile(group.id!, filename, resp.data);
|
||||
log("uniteddh-claim-processor", "PDF saved", { patientId, filename });
|
||||
} catch (err: any) {
|
||||
log("uniteddh-claim-processor", "failed to save PDF (non-fatal)", { error: err?.message ?? err });
|
||||
}
|
||||
}
|
||||
|
||||
export interface UnitedDHClaimProcessorInput {
|
||||
enrichedPayload: any;
|
||||
userId: number;
|
||||
@@ -149,6 +169,13 @@ export async function runUnitedDHClaimProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-save PDF for batch-column calls (no socketId = no frontend listener)
|
||||
if (pdf_url && !socketId) {
|
||||
const claim = claimId ? await storage.getClaim(claimId).catch(() => null) : null;
|
||||
const patientId = claim?.patientId ?? enrichedPayload?.claim?.patientId ?? enrichedPayload?.patientId;
|
||||
if (patientId) await savePdfFromSelenium(pdf_url, Number(patientId));
|
||||
}
|
||||
|
||||
emitToSocket(socketId, "selenium:uniteddh_claim_completed", {
|
||||
jobId,
|
||||
claimId,
|
||||
|
||||
@@ -104,13 +104,21 @@ async function processUnitedSCOResult(
|
||||
|
||||
// 4) Determine eligibility status
|
||||
const eligStatus = (seleniumResult?.eligibility ?? "").toLowerCase();
|
||||
const newStatus = eligStatus === "active" || eligStatus === "y" ? "ACTIVE" : "INACTIVE";
|
||||
const newStatus =
|
||||
eligStatus === "active" || eligStatus === "y" ? "ACTIVE" :
|
||||
eligStatus === "inactive" ? "INACTIVE" : null;
|
||||
|
||||
await storage.updatePatient(patient.id, {
|
||||
status: newStatus,
|
||||
insuranceProvider: "United Healthcare SCO",
|
||||
});
|
||||
output.patientUpdateStatus = `Patient status updated to ${newStatus}`;
|
||||
if (newStatus) {
|
||||
await storage.updatePatient(patient.id, {
|
||||
status: newStatus,
|
||||
insuranceProvider: "United Healthcare SCO",
|
||||
});
|
||||
output.patientUpdateStatus = `Patient status updated to ${newStatus}`;
|
||||
} else {
|
||||
// Unknown eligibility — still update insuranceProvider but leave status unchanged
|
||||
await storage.updatePatient(patient.id, { insuranceProvider: "United Healthcare SCO" });
|
||||
output.patientUpdateStatus = `Eligibility unknown — status not changed`;
|
||||
}
|
||||
|
||||
// 5) Resolve PDF buffer from file path (same as DDMA)
|
||||
let pdfBuffer: Buffer | null = null;
|
||||
|
||||
@@ -14,6 +14,8 @@ export type SeleniumJobType =
|
||||
| "cca-claim-submit"
|
||||
| "cca-preauth-submit"
|
||||
| "ddma-claim-submit"
|
||||
| "tuftssco-claim-submit"
|
||||
| "uniteddh-claim-submit"
|
||||
| "tuftssco-eligibility-check"
|
||||
| "mh-eligibility-history-check"
|
||||
| "cmsp-eligibility-history-remaining-check";
|
||||
|
||||
@@ -9,6 +9,7 @@ import fs from "fs";
|
||||
import axios from "axios";
|
||||
import archiver from "archiver";
|
||||
import { seleniumQueue } from "../queue/queues";
|
||||
import { enqueueSeleniumJob } from "../queue/jobRunner";
|
||||
import { Prisma } from "@repo/db/generated/prisma";
|
||||
import { Decimal } from "decimal.js";
|
||||
import {
|
||||
@@ -415,6 +416,28 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
// Maps patient.insuranceProvider free-text → the siteKey stored in InsuranceCredential
|
||||
function batchColumnDeriveSiteKey(provider: string): string {
|
||||
const p = provider.toLowerCase().trim();
|
||||
if (!p || p.includes("masshealth") || p === "mh" || p === "mass health") return "MH";
|
||||
if (p.includes("commonwealth care alliance") || p === "cca") return "CCA";
|
||||
if (p.includes("ddma") || p.includes("delta dental ma")) return "DDMA";
|
||||
if (p.includes("tufts") || p.includes("dentaquest") || p === "tuftssco") return "TUFTS_SCO";
|
||||
if ((p.includes("united") && p.includes("sco")) || p.includes("dentalhub") || p === "united_sco") return "UNITED_SCO";
|
||||
return "MH"; // default fallback
|
||||
}
|
||||
|
||||
// Returns the canonical insuranceProvider name stored in the Claim record
|
||||
function batchColumnCanonicalName(siteKey: string): string {
|
||||
switch (siteKey) {
|
||||
case "CCA": return "CCA";
|
||||
case "DDMA": return "Delta Dental MA";
|
||||
case "TUFTS_SCO": return "Tufts SCO";
|
||||
case "UNITED_SCO": return "United/DentalHub";
|
||||
default: return "MassHealth";
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/claims/batch-column
|
||||
// Query params: date=YYYY-MM-DD (required), staffIds=1,2 (required)
|
||||
// For each appointment in the selected staff columns:
|
||||
@@ -555,10 +578,15 @@ router.post(
|
||||
continue;
|
||||
}
|
||||
|
||||
// MassHealth credentials
|
||||
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(req.user.id, "MH");
|
||||
// Always derive siteKey from the patient record — claim.insuranceProvider
|
||||
// may be stale (e.g. previously set to "MassHealth" by the old hardcoded path)
|
||||
const rawInsuranceProvider = (patient.insuranceProvider ?? "").trim();
|
||||
const siteKey = batchColumnDeriveSiteKey(rawInsuranceProvider);
|
||||
const canonicalInsuranceProvider = batchColumnCanonicalName(siteKey);
|
||||
|
||||
const credentials = await storage.getInsuranceCredentialByUserAndSiteKey(req.user.id, siteKey);
|
||||
if (!credentials) {
|
||||
resultItem.error = "No MassHealth credentials found — check Settings";
|
||||
resultItem.error = `No ${canonicalInsuranceProvider} credentials found — check Settings`;
|
||||
results.push(resultItem);
|
||||
continue;
|
||||
}
|
||||
@@ -573,7 +601,7 @@ router.post(
|
||||
// Priority: Select Procedures choice > existing claim > first provider
|
||||
const claimNpiProviderId = procNpiProviderId ?? activeClaim?.npiProviderId ?? npiProvider?.id ?? null;
|
||||
|
||||
console.log(`[batch-column] apt=${apt.id} procNpiId=${procNpiProviderId} claimNpiId=${activeClaim?.npiProviderId} resolved=${claimNpiProviderId}`);
|
||||
console.log(`[batch-column] apt=${apt.id} siteKey=${siteKey} procNpiId=${procNpiProviderId} claimNpiId=${activeClaim?.npiProviderId} resolved=${claimNpiProviderId}`);
|
||||
|
||||
const patientName = `${patient.firstName ?? ""} ${patient.lastName ?? ""}`.trim();
|
||||
|
||||
@@ -597,7 +625,7 @@ router.post(
|
||||
? Number(claimNpiProviderId)
|
||||
: null;
|
||||
|
||||
console.log(`[batch-column] creating claim: patientId=${patient.id} aptId=${apt.id} staffId=${safeStaffId} npiProviderId=${safeNpiId} serviceDate=${serviceDate} dobStr=${dobStr} lines=${serviceLines.length}`);
|
||||
console.log(`[batch-column] creating claim: patientId=${patient.id} aptId=${apt.id} staffId=${safeStaffId} npiProviderId=${safeNpiId} serviceDate=${serviceDate} dobStr=${dobStr} lines=${serviceLines.length} insurance=${canonicalInsuranceProvider}`);
|
||||
|
||||
const newClaim = await storage.createClaim({
|
||||
patientId: Number(patient.id),
|
||||
@@ -608,7 +636,7 @@ router.post(
|
||||
memberId,
|
||||
dateOfBirth: new Date(dobStr),
|
||||
serviceDate: new Date(serviceDate),
|
||||
insuranceProvider: "MassHealth",
|
||||
insuranceProvider: canonicalInsuranceProvider,
|
||||
remarks: "",
|
||||
missingTeethStatus: "No_missing",
|
||||
missingTeeth: {},
|
||||
@@ -643,33 +671,6 @@ router.post(
|
||||
if (saved) resolvedNpiProvider = saved;
|
||||
}
|
||||
|
||||
// Build enriched payload for selenium
|
||||
const enrichedPayload: any = {
|
||||
patientId: Number(patient.id),
|
||||
appointmentId: Number(apt.id),
|
||||
userId: req.user.id,
|
||||
staffId: Number(apt.staffId),
|
||||
patientName,
|
||||
memberId,
|
||||
dateOfBirth: dobStr,
|
||||
serviceDate,
|
||||
insuranceProvider: "MassHealth",
|
||||
insuranceSiteKey: "MH",
|
||||
missingTeethStatus: activeClaim?.missingTeethStatus ?? "No_missing",
|
||||
missingTeeth: activeClaim?.missingTeeth ?? {},
|
||||
remarks: activeClaim?.remarks ?? "",
|
||||
serviceLines,
|
||||
claimId,
|
||||
massdhpUsername: credentials.username,
|
||||
massdhpPassword: credentials.password,
|
||||
};
|
||||
if (resolvedNpiProvider) {
|
||||
enrichedPayload.npiProvider = {
|
||||
npiNumber: resolvedNpiProvider.npiNumber,
|
||||
providerName: resolvedNpiProvider.providerName,
|
||||
};
|
||||
}
|
||||
|
||||
// Collect attachments: appointment-level files + claim-level files
|
||||
const apptFiles = await storage.getAppointmentFiles(Number(apt.id));
|
||||
const claimFiles = (activeClaim as any)?.claimFiles ?? [];
|
||||
@@ -689,17 +690,120 @@ router.post(
|
||||
return [{ originalname: f.filename, bufferBase64, mimetype: f.mimeType ?? "application/octet-stream" }];
|
||||
});
|
||||
|
||||
// Enqueue selenium claim-submit job
|
||||
const job = await seleniumQueue.add("claim-submit", {
|
||||
jobType: "claim-submit",
|
||||
// Base claim data shared across all insurance pathways
|
||||
const baseClaimPayload: any = {
|
||||
patientId: Number(patient.id),
|
||||
appointmentId: Number(apt.id),
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
files: filesForQueue,
|
||||
staffId: Number(apt.staffId),
|
||||
patientName,
|
||||
memberId,
|
||||
dateOfBirth: dobStr,
|
||||
serviceDate,
|
||||
missingTeethStatus: activeClaim?.missingTeethStatus ?? "No_missing",
|
||||
missingTeeth: activeClaim?.missingTeeth ?? {},
|
||||
remarks: activeClaim?.remarks ?? "",
|
||||
serviceLines,
|
||||
claimId,
|
||||
});
|
||||
...(resolvedNpiProvider ? {
|
||||
npiProvider: {
|
||||
npiNumber: resolvedNpiProvider.npiNumber,
|
||||
providerName: resolvedNpiProvider.providerName,
|
||||
},
|
||||
} : {}),
|
||||
};
|
||||
|
||||
// Enqueue to the correct insurance pathway
|
||||
let jobId: string;
|
||||
if (siteKey === "MH") {
|
||||
const enrichedPayload = {
|
||||
...baseClaimPayload,
|
||||
insuranceProvider: "MassHealth",
|
||||
insuranceSiteKey: "MH",
|
||||
massdhpUsername: credentials.username,
|
||||
massdhpPassword: credentials.password,
|
||||
};
|
||||
const job = await seleniumQueue.add("claim-submit", {
|
||||
jobType: "claim-submit",
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
files: filesForQueue,
|
||||
claimId,
|
||||
});
|
||||
jobId = String(job.id);
|
||||
} else if (siteKey === "CCA") {
|
||||
const enrichedPayload = {
|
||||
claim: {
|
||||
...baseClaimPayload,
|
||||
insuranceProvider: "CCA",
|
||||
insuranceSiteKey: "CCA",
|
||||
cca_username: credentials.username,
|
||||
cca_password: credentials.password,
|
||||
},
|
||||
files: filesForQueue,
|
||||
};
|
||||
jobId = enqueueSeleniumJob({
|
||||
jobType: "cca-claim-submit",
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
claimId,
|
||||
});
|
||||
} else if (siteKey === "DDMA") {
|
||||
const enrichedPayload = {
|
||||
claim: {
|
||||
...baseClaimPayload,
|
||||
insuranceProvider: "Delta Dental MA",
|
||||
insuranceSiteKey: "DDMA",
|
||||
massddmaUsername: credentials.username,
|
||||
massddmaPassword: credentials.password,
|
||||
},
|
||||
};
|
||||
jobId = enqueueSeleniumJob({
|
||||
jobType: "ddma-claim-submit",
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
claimId,
|
||||
});
|
||||
} else if (siteKey === "TUFTS_SCO") {
|
||||
const enrichedPayload = {
|
||||
claim: {
|
||||
...baseClaimPayload,
|
||||
insuranceProvider: "Tufts SCO",
|
||||
insuranceSiteKey: "TuftsSCO",
|
||||
dentaquestUsername: credentials.username,
|
||||
dentaquestPassword: credentials.password,
|
||||
},
|
||||
};
|
||||
jobId = enqueueSeleniumJob({
|
||||
jobType: "tuftssco-claim-submit",
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
claimId,
|
||||
});
|
||||
} else if (siteKey === "UNITED_SCO") {
|
||||
const enrichedPayload = {
|
||||
claim: {
|
||||
...baseClaimPayload,
|
||||
insuranceProvider: "United/DentalHub",
|
||||
insuranceSiteKey: "UNITED_SCO",
|
||||
uniteddhUsername: credentials.username,
|
||||
uniteddhPassword: credentials.password,
|
||||
},
|
||||
};
|
||||
jobId = enqueueSeleniumJob({
|
||||
jobType: "uniteddh-claim-submit",
|
||||
userId: req.user.id,
|
||||
enrichedPayload,
|
||||
claimId,
|
||||
});
|
||||
} else {
|
||||
resultItem.error = `Unsupported insurance type: ${siteKey}`;
|
||||
results.push(resultItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
resultItem.processed = true;
|
||||
resultItem.jobId = String(job.id);
|
||||
resultItem.jobId = jobId;
|
||||
|
||||
} catch (aptErr: any) {
|
||||
console.error("[batch-column] apt error:", aptErr);
|
||||
|
||||
@@ -107,8 +107,7 @@ function appointmentCardColor(apt: ScheduledAppointment): string {
|
||||
function resolveAppointmentBadgeStatus(apt: ScheduledAppointment): PatientStatus {
|
||||
if (apt.eligibilityStatus === "ACTIVE") return "ACTIVE";
|
||||
if (apt.eligibilityStatus === "INACTIVE") return "INACTIVE";
|
||||
const isMassHealth = apt.patientInsuranceProvider?.toLowerCase().includes("masshealth");
|
||||
if (apt.eligibilityStatus === "UNKNOWN" && isMassHealth) {
|
||||
if (apt.eligibilityStatus === "UNKNOWN") {
|
||||
if (apt.patientStatus === "ACTIVE") return "ACTIVE";
|
||||
if (apt.patientStatus === "INACTIVE") return "INACTIVE";
|
||||
}
|
||||
|
||||
9
apps/SeleniumService/.gitignore
vendored
9
apps/SeleniumService/.gitignore
vendored
@@ -1,2 +1,9 @@
|
||||
.env
|
||||
/__pycache__
|
||||
/__pycache__
|
||||
**/__pycache__
|
||||
.last_credentials
|
||||
chrome_profile_unitedsco/
|
||||
chrome_profile_ddma/
|
||||
chrome_profile_dentaquest/
|
||||
chrome_profile_masshealth/
|
||||
chrome_profile_*/
|
||||
@@ -1 +0,0 @@
|
||||
[{"description":"treehash per file","signed_content":{"payload":"eyJjb250ZW50X2hhc2hlcyI6W3siYmxvY2tfc2l6ZSI6NDA5NiwiZGlnZXN0Ijoic2hhMjU2IiwiZmlsZXMiOlt7InBhdGgiOiJsaXN0ZGF0YS5qc29uIiwicm9vdF9oYXNoIjoiNmVJUlZmTTczUDJjbUxncUQ0UkRQMjU3a0Q5bWY1WUZscHlpREw1dUlfMCJ9LHsicGF0aCI6Im1hbmlmZXN0Lmpzb24iLCJyb290X2hhc2giOiItVlJhUzl1Q2xpeFJaSWR2c0VWMkxJb1l4UDREZHl1NTdUQUVfbUJ1dXBVIn1dLCJmb3JtYXQiOiJ0cmVlaGFzaCIsImhhc2hfYmxvY2tfc2l6ZSI6NDA5Nn1dLCJpdGVtX2lkIjoibmlub2RhYmNlanBlZ2xmamJraGRwbGFvZ2xwY2JmZmoiLCJpdGVtX3ZlcnNpb24iOiI4LjYyOTQuMjA1NyIsInByb3RvY29sX3ZlcnNpb24iOjF9","signatures":[{"header":{"kid":"publisher"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"jKit53qyELKtZdFmhNfr8UG21np9jbaiQqVos_AwfKv4_BgX2rGr9tFMYcixECPW2jWz3p_EXucBLRMppysx4tREaZvl9EEIh5rQOs4staXL4VU6ErcZemFbtGSoxxZIXi1xyIIliTA-qt1lzY_I5IrHjMMvCJCYlcElCyXxBseJ4qR0Ow9_VQqkaI9zIliBWVIAOt6c_-dL2hTkqoYCeXzIvqO4_0ui4wcj5WCAujTOc-zBl6WJeVZKtpc6_B5XI7flkjUnu5lGabghojB-Qc9Y-Fm1qZOz0zJPPj26EdqCMnyMpgDxssZyjO4P46Jjc_yMCXcKLpj5XmfoO1wRtScZPn3o4PSSVew305puVe2xJF-IhsbGSR1BWbRyMoQ0sCZkJC3VLdtW_w-emgNhgAGje-SwfkPckDe_vkrPpN6Rti_6J-SizkBUHDJMG-Dbl--_iiWOa_GwGvZx84WkWHxDRbkrhrGjgQcpXbrVtuZe8Fsx305sRj5qq5hxhlbguX_wYTK3Q_L7NjNHIkjOv6BuMF1Jo1EnCM1ey_PBx7z9pkZfRcHrCVhanvfpaXk_GeAuog1H5ESWetFgGuyvFjgApgPUycfo7c23bPIVMitpn8n1kjmUk7q11mzZANESmtDOQGDRlzhTXck6UC9DDP-AgbOMVryMRUS3MKxI58w"},{"header":{"kid":"webstore"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"Eh7dVhKTBXsgvpNfC3nIXqJpMFzZD9oXTcm9024Z8zEOFSEw1nHWGU4Yrg_4wCpb2EiSFg9aXcVH9GvpeGg0EcGKbozMqwwmYk8UlOU5jpMf7B-afAFFKngNCuyDThtcWvWY6oKEJSVN7V4NcQ1dfhhxZLCfI8wqTbzEWCDS5vTuG0qZBHtkH4-d7r7W3c8ey4V0HtboOSF7FbHm5pC9x6T-e1uqmU0Ek-0pfHyYh-RYENVKZJN9-w8JF4y5KNN08Cyrn3-GB4IbJ6U7tgwCFnbpQqAr9oSeEcXitN0NmKuKySzvuVdNh_jQdgAOf5fkajDXHdxAWyaU1AErMLrTqQ"}]}}]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "listdata.json",
|
||||
"version": "8.6294.2057"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
[{"description":"treehash per file","signed_content":{"payload":"eyJjb250ZW50X2hhc2hlcyI6W3siYmxvY2tfc2l6ZSI6NDA5NiwiZGlnZXN0Ijoic2hhMjU2IiwiZmlsZXMiOlt7InBhdGgiOiJoZXVyaXN0aWNfcmVnZXhlcy5iaW5hcnlwYiIsInJvb3RfaGFzaCI6Im9ROWwxLURWWndMVzhJaFF5TDdwdlZHdkZfUy1CUmtBX3l1SXlTRi1RbDgifSx7InBhdGgiOiJtYW5pZmVzdC5qc29uIiwicm9vdF9oYXNoIjoibGFLd2RJdXU1d2RBX3kxZHA0LVl0YUtaVUZZdm1KV1I4TEMxdnhNMVM0VSJ9XSwiZm9ybWF0IjoidHJlZWhhc2giLCJoYXNoX2Jsb2NrX3NpemUiOjQwOTZ9XSwiaXRlbV9pZCI6Imhhamlnb3BiYmpoZ2hiZmltZ2tmbXBlbmZrY2xtb2hrIiwiaXRlbV92ZXJzaW9uIjoiNCIsInByb3RvY29sX3ZlcnNpb24iOjF9","signatures":[{"header":{"kid":"publisher"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"mqnzWWPXdMmUXubyqBppOqxAY921JfSOK_NcvIfwW7mkskMg4BQz9pzkrCPEJkJVcG_XUzkx1ByskF-ZC03s0RRaghvq-xYyFIOeL8g1A6wge9NuIZiD_KGIFmjieufISG8gijhKXINUgo6aKiGVQXWlMIRluSkGYmcTDeGW87JI1CkybIDjk3BOyKewFQiPDoafqe0BtW6fW8904q-C4xrrQHyCbmOjqhmO4VIusYh3J_LA4so-B3O-nVC30XaISnRKYPDTQzsTkz_eJq9LJcPL5RORZUrRaiDLMINSJaOUtne_6CT-6tlEuaZdLpeL9oIIsAc6taHZsz8yJvHhaVnjQsXL6eJrBufupTRY5i_Q0ir_aAsiBIu5xcOirAeMknUhxmFCGW5h7xEdp-FBL2d4ukbSDhlv2qrhPzd0TjNshQoXBaZSvLVjv9sC4RSF4vwva8j9O81ZfmFyyyzBs_mYsM0cMrrRETTXg_KrYiF-CSYBM3cZQWFyJ-w_-G0kRiryB0tG9AYkDAo2DcPuHAO7pRibl7CwM9mxsD4SFjiN_dlPUfMHBUGhgPZofVb2c7nY7ztndNKPzNKwYOZLrhj8G6-TQgJL7QplhG761mrkUrZOGzAIBu8i4HN9SqfFIClGNjLYdmXruTveYMQV0RwO--7HT4Dvd2OEwa5shsw"},{"header":{"kid":"webstore"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"CG6KXxg_Mpqgw7XcrysRHH5F6HAql4JmenqcSzsnyja8z2d_cW6IfuHAmBQ78gE8HGIa4RUC3JQn08MN5zH2PlLfo4Lnr6NOyQGatRN7PZyK6gzaIMhK_0-CVEHR-A2mP9JpT9ksmxcURiKpAK44fTqod2KpzJMILYEFnB11MsZSEVYMYWQqT1mq4gRqo0uBne6paqZXKxLXIorweRX2KYPMYX9tHFt8CugLW5LmKPbReIJ4XJaLhLxRCHimnKtqx4r1_y7xPfitVCHIAfM5QVY6hv3xubPN2_bIPMeI6k2IlCZAH2tRptGgm9a80KlDpNQxMd9Eqi_z246ltVL2iA"}]}}]
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
<EFBFBD>
|
||||
<EFBFBD>(?:US\$|USD|\$)\s*\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?(?:\s*)(?:USD|US\$|\$)?|(?:USD|US\$|\$)?\s*\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?\s*(?:USD|US\$|\$)<12>^(?:\s*)(Due now \(USD\)|(Estimated )?(?:Order Total|Total:?)|TOTAL CHARGED TODAY \*|Final Total Price:|Flight total|grand total:?|Order Total(?: \(USD\))?:?|Price|Total(?:(?: \(USD\))?| Due| for Stay| Price| to be paid:| to pay|:)?|(Your )?(?:Payment Today|total(\s)price|Total:)|Show Order Summary:|Reservation Deposit Amount Due|Payment Due Now|Your Price|Total Due Now|Amount to pay|Total amount due|You pay today|Order Summary|TOTAL PAYMENT DUE|Payable Amount)(?:\s*)$
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Amount Extraction Heuristic Regexes",
|
||||
"version": "4"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"epochs": [ {
|
||||
"calculation_time": "13420944458137194",
|
||||
"config_version": 0,
|
||||
"model_version": "0",
|
||||
"padded_top_topics_start_index": 0,
|
||||
"taxonomy_version": 0,
|
||||
"top_topics_and_observing_domains": [ ]
|
||||
} ],
|
||||
"hex_encoded_hmac_key": "24AD0CEEC0277EA6C3A355C732190B3C481360D7BE0EC4B7BA1282A9D36C1DAA",
|
||||
"next_scheduled_calculation_time": "13421549258144341"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
MANIFEST-000001
|
||||
@@ -1,2 +0,0 @@
|
||||
2026/04/17-20:07:31.575 120577 Creating DB /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Rules since it was missing.
|
||||
2026/04/17-20:07:31.606 120577 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Rules/MANIFEST-000001
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
MANIFEST-000001
|
||||
@@ -1,2 +0,0 @@
|
||||
2026/04/17-20:07:31.607 120577 Creating DB /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Scripts since it was missing.
|
||||
2026/04/17-20:07:31.637 120577 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension Scripts/MANIFEST-000001
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
MANIFEST-000001
|
||||
@@ -1,3 +0,0 @@
|
||||
2026/04/17-23:41:41.932 9b79 Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension State/MANIFEST-000001
|
||||
2026/04/17-23:41:41.932 9b79 Recovering log #3
|
||||
2026/04/17-23:41:41.932 9b79 Reusing old log /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/Extension State/000003.log
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
MANIFEST-000001
|
||||
@@ -1,3 +0,0 @@
|
||||
2026/04/17-23:41:47.142 9b8d Reusing MANIFEST /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/GCM Store/MANIFEST-000001
|
||||
2026/04/17-23:41:47.143 9b8d Recovering log #3
|
||||
2026/04/17-23:41:47.143 9b8d Reusing old log /home/ee/Desktop/Gitead-DentalManagementMHnewff/apps/SeleniumService/chrome_profile_dentaquest/Default/GCM Store/000003.log
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"net":{"http_server_properties":{"servers":[{"anonymization":["FAAAABAAAABodHRwczovL2d2dDEuY29t",false,0],"server":"https://redirector.gvt1.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423536464638726","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACsAAABodHRwczovL29wdGltaXphdGlvbmd1aWRlLXBhLmdvb2dsZWFwaXMuY29tAA==",false,0],"network_stats":{"srtt":19423},"server":"https://optimizationguide-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423536489859725","port":443,"protocol_str":"quic"}],"anonymization":["FAAAABAAAABodHRwczovL2d2dDEuY29t",false,0],"network_stats":{"srtt":14112},"server":"https://r12---sn-jvhj5nu-cvnl7.gvt1.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549147852405","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":21402},"server":"https://www.gstatic.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://dpm.demdex.net","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",true,0],"server":"https://greatdentalplans.demdex.net","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302118900","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":35187},"server":"https://accounts.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302252025","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":29518},"server":"https://www.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302459934","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":31079},"server":"https://ogads-pa.clients6.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549302748269","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABUAAABjaHJvbWU6Ly9uZXctdGFiLXBhZ2UAAAA=",true,0],"network_stats":{"srtt":28176},"server":"https://play.google.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://assets.adobedtm.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://dentaquest.sc.omtrdc.net","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://zn1zsy47ahixog4rc-cxinsight.siteintercept.qualtrics.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://providers-login.dentaquest.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://siteintercept.qualtrics.com","supports_spdy":true},{"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"server":"https://providers.dentaquest.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549340838122","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACwAAABodHRwczovL3Bhc3N3b3Jkc2xlYWtjaGVjay1wYS5nb29nbGVhcGlzLmNvbQ==",false,0],"network_stats":{"srtt":23504},"server":"https://passwordsleakcheck-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549358008191","port":443,"protocol_str":"quic"}],"anonymization":["HAAAABYAAABodHRwczovL2RlbnRhcXVlc3QuY29tAAA=",false,0],"network_stats":{"srtt":34201},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13423549384945647","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":26030},"server":"https://android.clients.google.com","supports_spdy":true}],"supports_quic":{"address":"192.168.1.236","used_quic":true},"version":5},"network_qualities":{"CAESABiAgICA+P////8B":"4G"}}}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"preferred_apps":[],"version":1}
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
[]
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
{"protection":{"super_mac":"33F663353631B144EA660B5F809D89BA41CAF954EE5776BE5004BB589CA96BE1"}}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user