UNPKG

@accounter/client

Version:
99 lines (87 loc) 3.16 kB
import type { AllSortCodesQuery, DynamicReportQuery } from '../../../../gql/graphql.js'; import type { CustomData, FlatNode } from './types.js'; export const BANK_ROOT = 'bank'; type BusinessSum = Extract< NonNullable<DynamicReportQuery['businessTransactionsSumFromLedgerRecords']>, { __typename?: 'BusinessTransactionsSumFromLedgerRecordsSuccessfulResult' } >['businessTransactionsSum'][number]; /** * Builds the initial bank flat-tree from live GraphQL data. * * - Sort-code branches are ordered ascending by sortCode.key. * - Only emits a sort-code branch when at least one visible entity belongs to it. * - Entities with no sort code appear after all branches, sorted alphabetically. * - Excluded entity ids (already placed in the report tree) are omitted. * - If includeZeroed is false, entities with total.raw === 0 are omitted. */ export function buildInitialBankTree( sortCodes: AllSortCodesQuery['allSortCodesByBusiness'], businessSums: BusinessSum[], excludedIds: Set<string>, includeZeroed: boolean, ): FlatNode<CustomData>[] { // 1. Filter const filtered = businessSums.filter(b => { if (excludedIds.has(b.business.id)) return false; if (!includeZeroed && b.total.raw === 0) return false; return true; }); // 2. Group by sort code id const bySortCodeId = new Map< string, { key: number; name: string | null | undefined; entities: BusinessSum[] } >(); const noSortCode: BusinessSum[] = []; // Pre-index sort codes for O(1) lookup const sortCodeMap = new Map(sortCodes.map(sc => [sc.id, sc])); for (const b of filtered) { const sc = b.business.sortCode; if (sc) { if (!bySortCodeId.has(sc.id)) { // Prefer the richer name from the sortCodes param if available const scParam = sortCodeMap.get(sc.id); bySortCodeId.set(sc.id, { key: sc.key, name: scParam?.name ?? sc.name, entities: [], }); } bySortCodeId.get(sc.id)!.entities.push(b); } else { noSortCode.push(b); } } // 3. Sort branches ascending by key const sortedBranches = [...bySortCodeId.entries()].sort((a, b) => a[1].key - b[1].key); const result: FlatNode<CustomData>[] = []; for (const [scId, { key, name, entities }] of sortedBranches) { result.push({ id: scId, parent: BANK_ROOT, text: `${key}${name ?? ''}`, droppable: true, data: { nodeType: 'sort-code-branch', sortCode: key, isOpen: false }, }); for (const b of entities) { result.push({ id: b.business.id, parent: scId, text: b.business.name, droppable: false, data: { nodeType: 'financial-entity', value: b.total.raw * -1, isOpen: false }, }); } } // 4. No-sort-code entities — alphabetical noSortCode.sort((a, b) => a.business.name.localeCompare(b.business.name)); for (const b of noSortCode) { result.push({ id: b.business.id, parent: BANK_ROOT, text: b.business.name, droppable: false, data: { nodeType: 'financial-entity', value: b.total.raw * -1, isOpen: false }, }); } return result; }