import { formatISO } from 'date-fns'; import { Log } from 'lib/Log'; import { DB, client, paginate } from 'lib/DB'; import { ServerError, Status } from 'nice-grpc'; import { Global, Meta } from '@nextgenleads/dnc'; const log = Log.child({ module: 'grpc', service: 'Global', method: 'summary', }); export async function summary(request: Global.SummaryRequest): Promise { if (!request.params || !request.params.start || !request.params.end) { throw new ServerError(Status.INVALID_ARGUMENT, 'Missing required argument'); } const dRequest = { ...request, params: { ...request.params, verticals: request.params.verticals ? Global.decodeSummaryRequestSummaryParamsVerticals(request.params.verticals) : undefined, states: request.params.states ? Global.decodeSummaryRequestSummaryParamsStates(request.params.states) : undefined, }, }; const verticals = dRequest.params.verticals?.values || []; const states = dRequest.params.states?.values || []; const source_codes = request.params.source_codes?.values || []; const start = formatISO(request.params.start); const end = formatISO(request.params.end); log.info('Looking up summary for %s -> %s', start, end, { verticals, source_codes, states }); let pagination: Meta.Query_Pagination | undefined; let total_count = 0; const results = []; try { const query = ` WITH -- NOTE: Duplicate/Disqualified pulls from the entire history range of dncs, if they fall within the specific range duplicates AS ( SELECT DATE(du."createdAt") as date, d.vertical_id as vertical_id, d.source_code as source_code, d.state as state, COUNT(du.id)::int as duplicate_count FROM duplicates du LEFT JOIN dncs d ON (d.id = du."DNCId" and d.company_id is NULL) WHERE du."createdAt" >= '${start}' AND du."createdAt" <= '${end}' ${verticals.length > 0 ? `AND d.vertical_id in (${verticals.map((v) => `'${v}'`).join(', ')})` : ''} ${source_codes.length > 0 ? `AND d.source_code in (${source_codes.map((sc) => `'${sc}'`).join(', ')})` : ''} ${states.length > 0 ? `AND d.state in (${states.map((s) => `'${s}'`).join(', ')})` : ''} GROUP BY 1, 2, 3, 4 ), disqualified AS ( SELECT DATE(di."createdAt") as date, d.vertical_id as vertical_id, d.source_code as source_code, d.state as state, COUNT(di.id)::int as disqualified_count FROM disqualifications di LEFT JOIN dncs d ON (d.id = di."DNCId" AND d.company_id is NULL) WHERE di."createdAt" >= '${start}' AND di."createdAt" <= '${end}' ${verticals.length > 0 ? `AND d.vertical_id in (${verticals.map((v) => `'${v}'`).join(', ')})` : ''} ${source_codes.length > 0 ? `AND d.source_code in (${source_codes.map((sc) => `'${sc}'`).join(', ')})` : ''} ${states.length > 0 ? `AND d.state in (${states.map((s) => `'${s}'`).join(', ')})` : ''} GROUP BY 1, 2, 3, 4 ), -- NOTE: We include the specific range of dnc, to account for no duplicate/disqualified dnc AS ( SELECT * FROM dncs d WHERE d."createdAt" >= '${start}' AND d."createdAt" <= '${end}' AND d."company_id" is NULL ${verticals.length > 0 ? `AND d.vertical_id in (${verticals.map((v) => `'${v}'`).join(', ')})` : ''} ${source_codes.length > 0 ? `AND d.source_code in (${source_codes.map((sc) => `'${sc}'`).join(', ')})` : ''} ${states.length > 0 ? `AND d.state in (${states.map((s) => `'${s}'`).join(', ')})` : ''} ), final AS ( SELECT COALESCE(DATE(d."createdAt"), di.date, du.date) as date, COALESCE(d.vertical_id, di.vertical_id, du.vertical_id) as vertical_id, COALESCE(d.source_code, di.source_code, du.source_code) as source_code, COALESCE(d.state, di.state, du.state) as state, SUM(COALESCE(du.duplicate_count, 0)) as duplicate_count, SUM(COALESCE(di.disqualified_count, 0)) as disqualified_count, COUNT(d.id)::int as count FROM dnc d FULL JOIN disqualified di ON ( di.date = DATE(d."createdAt") AND di.vertical_id = d.vertical_id AND di.source_code = d.source_code AND di.state = d.state ) FULL JOIN duplicates du ON ( du.date = DATE(d."createdAt") AND du.vertical_id = d.vertical_id AND du.source_code = d.source_code AND du.state = d.state ) GROUP BY 1, 2, 3, 4 ) SELECT * FROM final `; let rows: { date: string; vertical_id?: string; source_code?: string; state?: string; count: number; duplicate_count: number; disqualified_count: number; }[]; if (request.query?.pagination) { // Page is 1-index on submission, we use as 0-index const page = request.query.pagination.$case === 'page' ? request.query.pagination.page - 1 : 0; const limit = request.query.limit || 25; const skip = request.query.skip; const result = await paginate(query, { page, limit, skip, }); rows = result.result; pagination = result.pagination; log.info('Paginating results for page %s', page); } else { rows = ((await client.query(query)) as [typeof rows, unknown])[0]; } log.info('Resolved %d rows for summary', rows.length); results.push(...rows.map((row) => ({ ...row, date: new Date(row.date) }))); total_count = await DB.DNC.count({ where: { company_id: null, }, }); } catch (err) { log.error('Failed to resolve summary', err); } return { total_count, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore result: results.map((result) => Global.encodeSummaryResponseSummaryRow(result as any)), pagination, }; }