feat: add provider column, commission tracking, and report provider filter
- Claims & Payments: save npiProviderId when submitting MH claim; sync between claim and payment on update - Claims table: add Provider column showing rendering provider name - Payments table: add Provider column + purple Commissioned badge on status - Claim edit modal: add Rendering Provider dropdown (defaults to Mary Scannell) - Payment edit modal: add Rendering Provider dropdown + Commissioned metadata display - Reports page: add Provider filter dropdown (dynamic from NPI providers settings) - Reports page: remove Collections by Doctor report type and Select Doctor dropdown - Commission section: new section in reports page with date range + provider filter, shows eligible paid claims/payments per provider, multi-select checkboxes, Pay Commission modal with print + save, marks payments as commissioned so they are excluded from future cycles - DB: add CommissionBatch and CommissionBatchItem tables; backfill Payment.npiProviderId from linked claims - Backend: PATCH /api/payments/:id/provider syncs to linked claim; PUT /api/claims/:id syncs to linked payment; new /api/commissions routes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,10 @@ import {
|
||||
} from "../../../../packages/db/types/payments-reports-types";
|
||||
|
||||
export interface IPaymentsReportsStorage {
|
||||
// summary now returns an extra field patientsWithBalance
|
||||
getSummary(
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<{
|
||||
totalPatients: number;
|
||||
totalOutstanding: number;
|
||||
@@ -16,44 +16,28 @@ export interface IPaymentsReportsStorage {
|
||||
patientsWithBalance: number;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Cursor-based pagination:
|
||||
* - limit: page size
|
||||
* - cursorToken: base64(JSON) token for last-seen row (or null for first page)
|
||||
* - from/to: optional date range filter applied to Payment."createdAt"
|
||||
*/
|
||||
getPatientsWithBalances(
|
||||
limit: number,
|
||||
cursorToken?: string | null,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<GetPatientBalancesResult>;
|
||||
|
||||
/**
|
||||
* Returns the paginated patient balances for a specific staff (doctor).
|
||||
* Same semantics / columns / ordering / cursor behavior as the previous combined function.
|
||||
*
|
||||
* - staffId required
|
||||
* - limit: page size
|
||||
* - cursorToken: optional base64 cursor (must have been produced for same staffId)
|
||||
* - from/to: optional date range applied to Payment."createdAt"
|
||||
*/
|
||||
getPatientsBalancesByDoctor(
|
||||
staffId: number,
|
||||
limit: number,
|
||||
cursorToken?: string | null,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<GetPatientBalancesResult>;
|
||||
|
||||
/**
|
||||
* Returns only the summary object for the given staff (doctor).
|
||||
* Same summary shape as getSummary(), but scoped to claims/payments associated with the given staffId.
|
||||
*/
|
||||
getSummaryByDoctor(
|
||||
staffId: number,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<{
|
||||
totalPatients: number;
|
||||
totalOutstanding: number;
|
||||
@@ -129,208 +113,72 @@ function decodeCursor(token?: string | null): {
|
||||
}
|
||||
|
||||
export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
async getSummary(from?: Date | null, to?: Date | null) {
|
||||
async getSummary(from?: Date | null, to?: Date | null, npiProviderId?: number | null) {
|
||||
try {
|
||||
const hasFrom = from !== undefined && from !== null;
|
||||
const hasTo = to !== undefined && to !== null;
|
||||
const fromStart = isoStartOfDayLiteral(from);
|
||||
const toNextStart = isoStartOfNextDayLiteral(to);
|
||||
|
||||
// Use inclusive start-of-day for 'from' and exclusive start-of-next-day for 'to'
|
||||
const fromStart = isoStartOfDayLiteral(from); // 'YYYY-MM-DDT00:00:00.000Z'
|
||||
const toNextStart = isoStartOfNextDayLiteral(to); // 'YYYY-MM-DDT00:00:00.000Z' of next day
|
||||
// Build a shared WHERE clause for Payment rows
|
||||
const conditions: string[] = [];
|
||||
if (from) conditions.push(`pay."createdAt" >= ${fromStart}`);
|
||||
if (to) conditions.push(`pay."createdAt" <= ${toNextStart}`);
|
||||
if (npiProviderId) conditions.push(`pay."npiProviderId" = ${Number(npiProviderId)}`);
|
||||
const payWhereClause = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
||||
|
||||
// totalPatients: distinct patients who had payments in the date range
|
||||
let patientsCountSql = "";
|
||||
if (hasFrom && hasTo) {
|
||||
patientsCountSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
`;
|
||||
} else if (hasFrom) {
|
||||
patientsCountSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
`;
|
||||
} else if (hasTo) {
|
||||
patientsCountSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
`;
|
||||
} else {
|
||||
patientsCountSql = `SELECT COUNT(DISTINCT "patientId")::int AS cnt FROM "Payment"`;
|
||||
}
|
||||
const patientsCntRows = (await prisma.$queryRawUnsafe(
|
||||
patientsCountSql
|
||||
)) as { cnt: number }[];
|
||||
const patientsCountSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id
|
||||
FROM "Payment" pay
|
||||
${payWhereClause}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
`;
|
||||
const patientsCntRows = (await prisma.$queryRawUnsafe(patientsCountSql)) as { cnt: number }[];
|
||||
const totalPatients = patientsCntRows?.[0]?.cnt ?? 0;
|
||||
|
||||
// totalOutstanding: totalBilled - mhPaidAmount - copayment - adjustment
|
||||
let outstandingSql = "";
|
||||
if (hasFrom && hasTo) {
|
||||
outstandingSql = `
|
||||
SELECT COALESCE(SUM(
|
||||
GREATEST(COALESCE(pm.total_charges,0) - COALESCE(pm.mh_paid,0) - COALESCE(pm.copayment,0) - COALESCE(pm.adjustment,0), 0)
|
||||
),0)::numeric(14,2) AS outstanding
|
||||
FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) pm
|
||||
`;
|
||||
} else if (hasFrom) {
|
||||
outstandingSql = `
|
||||
SELECT COALESCE(SUM(
|
||||
GREATEST(COALESCE(pm.total_charges,0) - COALESCE(pm.mh_paid,0) - COALESCE(pm.copayment,0) - COALESCE(pm.adjustment,0), 0)
|
||||
),0)::numeric(14,2) AS outstanding
|
||||
FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart}
|
||||
GROUP BY pay."patientId"
|
||||
) pm
|
||||
`;
|
||||
} else if (hasTo) {
|
||||
outstandingSql = `
|
||||
SELECT COALESCE(SUM(
|
||||
GREATEST(COALESCE(pm.total_charges,0) - COALESCE(pm.mh_paid,0) - COALESCE(pm.copayment,0) - COALESCE(pm.adjustment,0), 0)
|
||||
),0)::numeric(14,2) AS outstanding
|
||||
FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) pm
|
||||
`;
|
||||
} else {
|
||||
outstandingSql = `
|
||||
SELECT COALESCE(SUM(
|
||||
GREATEST(COALESCE(pm.total_charges,0) - COALESCE(pm.mh_paid,0) - COALESCE(pm.copayment,0) - COALESCE(pm.adjustment,0), 0)
|
||||
),0)::numeric(14,2) AS outstanding
|
||||
FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
GROUP BY pay."patientId"
|
||||
) pm
|
||||
`;
|
||||
}
|
||||
const outstandingRows = (await prisma.$queryRawUnsafe(
|
||||
outstandingSql
|
||||
)) as { outstanding: string }[];
|
||||
const outstandingSql = `
|
||||
SELECT COALESCE(SUM(
|
||||
GREATEST(COALESCE(pm.total_charges,0) - COALESCE(pm.mh_paid,0) - COALESCE(pm.copayment,0) - COALESCE(pm.adjustment,0), 0)
|
||||
),0)::numeric(14,2) AS outstanding
|
||||
FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
${payWhereClause}
|
||||
GROUP BY pay."patientId"
|
||||
) pm
|
||||
`;
|
||||
const outstandingRows = (await prisma.$queryRawUnsafe(outstandingSql)) as { outstanding: string }[];
|
||||
const totalOutstanding = Number(outstandingRows?.[0]?.outstanding ?? 0);
|
||||
|
||||
// totalCollected: mhPaidAmount + copayment (adjustment is write-off, not collected)
|
||||
let collSql = "";
|
||||
if (hasFrom && hasTo) {
|
||||
collSql = `SELECT COALESCE(SUM(COALESCE("mhPaidAmount",0) + "copayment"),0)::numeric(14,2) AS collected FROM "Payment" WHERE "createdAt" >= ${fromStart} AND "createdAt" <= ${toNextStart}`;
|
||||
} else if (hasFrom) {
|
||||
collSql = `SELECT COALESCE(SUM(COALESCE("mhPaidAmount",0) + "copayment"),0)::numeric(14,2) AS collected FROM "Payment" WHERE "createdAt" >= ${fromStart}`;
|
||||
} else if (hasTo) {
|
||||
collSql = `SELECT COALESCE(SUM(COALESCE("mhPaidAmount",0) + "copayment"),0)::numeric(14,2) AS collected FROM "Payment" WHERE "createdAt" <= ${toNextStart}`;
|
||||
} else {
|
||||
collSql = `SELECT COALESCE(SUM(COALESCE("mhPaidAmount",0) + "copayment"),0)::numeric(14,2) AS collected FROM "Payment"`;
|
||||
}
|
||||
const collRows = (await prisma.$queryRawUnsafe(collSql)) as {
|
||||
collected: string;
|
||||
}[];
|
||||
const collSql = `
|
||||
SELECT COALESCE(SUM(COALESCE(pay."mhPaidAmount",0) + pay."copayment"),0)::numeric(14,2) AS collected
|
||||
FROM "Payment" pay
|
||||
${payWhereClause}
|
||||
`;
|
||||
const collRows = (await prisma.$queryRawUnsafe(collSql)) as { collected: string }[];
|
||||
const totalCollected = Number(collRows?.[0]?.collected ?? 0);
|
||||
|
||||
// patientsWithBalance: patients where (billed - mhPaid - copayment - adjustment) > 0
|
||||
let patientsWithBalanceSql = "";
|
||||
if (hasFrom && hasTo) {
|
||||
patientsWithBalanceSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
WHERE (COALESCE(t.total_charges,0) - COALESCE(t.mh_paid,0) - COALESCE(t.copayment,0) - COALESCE(t.adjustment,0)) > 0
|
||||
`;
|
||||
} else if (hasFrom) {
|
||||
patientsWithBalanceSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" >= ${fromStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
WHERE (COALESCE(t.total_charges,0) - COALESCE(t.mh_paid,0) - COALESCE(t.copayment,0) - COALESCE(t.adjustment,0)) > 0
|
||||
`;
|
||||
} else if (hasTo) {
|
||||
patientsWithBalanceSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
WHERE pay."createdAt" <= ${toNextStart}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
WHERE (COALESCE(t.total_charges,0) - COALESCE(t.mh_paid,0) - COALESCE(t.copayment,0) - COALESCE(t.adjustment,0)) > 0
|
||||
`;
|
||||
} else {
|
||||
patientsWithBalanceSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
WHERE (COALESCE(t.total_charges,0) - COALESCE(t.mh_paid,0) - COALESCE(t.copayment,0) - COALESCE(t.adjustment,0)) > 0
|
||||
`;
|
||||
}
|
||||
const pwbRows = (await prisma.$queryRawUnsafe(
|
||||
patientsWithBalanceSql
|
||||
)) as { cnt: number }[];
|
||||
const patientsWithBalanceSql = `
|
||||
SELECT COUNT(*)::int AS cnt FROM (
|
||||
SELECT pay."patientId" AS patient_id,
|
||||
SUM(pay."totalBilled")::numeric(14,2) AS total_charges,
|
||||
SUM(COALESCE(pay."mhPaidAmount",0))::numeric(14,2) AS mh_paid,
|
||||
SUM(pay."copayment")::numeric(14,2) AS copayment,
|
||||
SUM(pay."adjustment")::numeric(14,2) AS adjustment
|
||||
FROM "Payment" pay
|
||||
${payWhereClause}
|
||||
GROUP BY pay."patientId"
|
||||
) t
|
||||
WHERE (COALESCE(t.total_charges,0) - COALESCE(t.mh_paid,0) - COALESCE(t.copayment,0) - COALESCE(t.adjustment,0)) > 0
|
||||
`;
|
||||
const pwbRows = (await prisma.$queryRawUnsafe(patientsWithBalanceSql)) as { cnt: number }[];
|
||||
const patientsWithBalance = pwbRows?.[0]?.cnt ?? 0;
|
||||
|
||||
return {
|
||||
totalPatients,
|
||||
totalOutstanding,
|
||||
totalCollected,
|
||||
patientsWithBalance,
|
||||
};
|
||||
return { totalPatients, totalOutstanding, totalCollected, patientsWithBalance };
|
||||
} catch (err) {
|
||||
console.error("[paymentsReportsStorage.getSummary] error:", err);
|
||||
throw err;
|
||||
@@ -348,7 +196,8 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
limit = 25,
|
||||
cursorToken?: string | null,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
) {
|
||||
try {
|
||||
type RawRow = {
|
||||
@@ -373,15 +222,12 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
const fromStart = isoStartOfDayLiteral(from); // 'YYYY-MM-DDT00:00:00.000Z'
|
||||
const toNextStart = isoStartOfNextDayLiteral(to); // 'YYYY-MM-DDT00:00:00.000Z' of next day
|
||||
|
||||
// Build payment subquery (aggregated payments by patient, filtered by createdAt if provided)
|
||||
const paymentWhereClause =
|
||||
hasFrom && hasTo
|
||||
? `WHERE pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}`
|
||||
: hasFrom
|
||||
? `WHERE pay."createdAt" >= ${fromStart}`
|
||||
: hasTo
|
||||
? `WHERE pay."createdAt" <= ${toNextStart}`
|
||||
: "";
|
||||
// Build payment subquery WHERE clause (date + optional provider filter)
|
||||
const payConditions: string[] = [];
|
||||
if (hasFrom) payConditions.push(`pay."createdAt" >= ${fromStart}`);
|
||||
if (hasTo) payConditions.push(`pay."createdAt" <= ${toNextStart}`);
|
||||
if (npiProviderId) payConditions.push(`pay."npiProviderId" = ${Number(npiProviderId)}`);
|
||||
const paymentWhereClause = payConditions.length ? `WHERE ${payConditions.join(" AND ")}` : "";
|
||||
|
||||
const pmSubquery = `
|
||||
(
|
||||
@@ -542,7 +388,8 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
limit = 25,
|
||||
cursorToken?: string | null,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<{
|
||||
balances: PatientBalanceRow[];
|
||||
totalCount: number;
|
||||
@@ -571,15 +418,14 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
const fromStart = isoStartOfDayLiteral(from);
|
||||
const toNextStart = isoStartOfNextDayLiteral(to);
|
||||
|
||||
// Filter payments by createdAt (time window) when provided
|
||||
const paymentTimeFilter =
|
||||
hasFrom && hasTo
|
||||
? `AND pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}`
|
||||
: hasFrom
|
||||
? `AND pay."createdAt" >= ${fromStart}`
|
||||
: hasTo
|
||||
? `AND pay."createdAt" <= ${toNextStart}`
|
||||
: "";
|
||||
// Filter payments by createdAt and/or provider
|
||||
const payAndConditions: string[] = [];
|
||||
if (hasFrom) payAndConditions.push(`pay."createdAt" >= ${fromStart}`);
|
||||
if (hasTo) payAndConditions.push(`pay."createdAt" <= ${toNextStart}`);
|
||||
if (npiProviderId) payAndConditions.push(`pay."npiProviderId" = ${Number(npiProviderId)}`);
|
||||
const paymentTimeFilter = payAndConditions.length
|
||||
? `AND ${payAndConditions.join(" AND ")}`
|
||||
: "";
|
||||
|
||||
// Keyset predicate — prefer numeric epoch-ms comparison for stability
|
||||
let pageKeysetPredicate = "";
|
||||
@@ -801,7 +647,8 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
async getSummaryByDoctor(
|
||||
staffId: number,
|
||||
from?: Date | null,
|
||||
to?: Date | null
|
||||
to?: Date | null,
|
||||
npiProviderId?: number | null
|
||||
): Promise<{
|
||||
totalPatients: number;
|
||||
totalOutstanding: number;
|
||||
@@ -818,14 +665,13 @@ export const paymentsReportsStorage: IPaymentsReportsStorage = {
|
||||
const fromStart = isoStartOfDayLiteral(from);
|
||||
const toNextStart = isoStartOfNextDayLiteral(to);
|
||||
|
||||
const paymentTimeFilter =
|
||||
hasFrom && hasTo
|
||||
? `AND pay."createdAt" >= ${fromStart} AND pay."createdAt" <= ${toNextStart}`
|
||||
: hasFrom
|
||||
? `AND pay."createdAt" >= ${fromStart}`
|
||||
: hasTo
|
||||
? `AND pay."createdAt" <= ${toNextStart}`
|
||||
: "";
|
||||
const drAndConditions: string[] = [];
|
||||
if (hasFrom) drAndConditions.push(`pay."createdAt" >= ${fromStart}`);
|
||||
if (hasTo) drAndConditions.push(`pay."createdAt" <= ${toNextStart}`);
|
||||
if (npiProviderId) drAndConditions.push(`pay."npiProviderId" = ${Number(npiProviderId)}`);
|
||||
const paymentTimeFilter = drAndConditions.length
|
||||
? `AND ${drAndConditions.join(" AND ")}`
|
||||
: "";
|
||||
|
||||
const summaryQuery = `
|
||||
WITH
|
||||
|
||||
Reference in New Issue
Block a user