@accounter/client
Version:
Accounter client application
113 lines (100 loc) • 3.4 kB
text/typescript
import type { DynamicReportQuery } from '../../../../gql/graphql.js';
import { REPORT_ROOT } from './report-tree.js';
import type { CustomData, FlatNode } from './types.js';
export type LegacyTemplateNode = {
id: string | number;
parent: string | number;
text: string;
droppable: boolean;
data: {
isOpen: boolean;
hebrewText?: string;
sortCode?: number | null;
descendantFinancialEntities?: string[] | null;
descendantSortCodes?: number[] | null;
mergedSortCodes?: number[] | null;
};
};
type BusinessSum = Extract<
NonNullable<DynamicReportQuery['businessTransactionsSumFromLedgerRecords']>,
{ __typename?: 'BusinessTransactionsSumFromLedgerRecordsSuccessfulResult' }
>['businessTransactionsSum'][number];
export function isLegacyTemplateNodes(nodes: LegacyTemplateNode[]): boolean {
return nodes.some(n => 'descendantSortCodes' in n.data);
}
export function migrateLegacyTemplateNodes(
nodes: LegacyTemplateNode[],
businessSums: BusinessSum[],
): FlatNode<CustomData>[] {
const sumById = new Map<string, BusinessSum>();
for (const b of businessSums) {
sumById.set(b.business.id, b);
}
// Collect ids of explicit leaf nodes already present in the template
const explicitLeafIds = new Set<string>();
for (const n of nodes) {
if (!n.droppable) {
explicitLeafIds.add(String(n.id));
}
}
const result: FlatNode<CustomData>[] = [];
const processedIds = new Set<string>();
for (const node of nodes) {
const id = String(node.id);
if (processedIds.has(id)) continue;
const parent = node.parent === 0 || node.parent === '0' ? REPORT_ROOT : String(node.parent);
if (node.droppable) {
const nodeType: CustomData['nodeType'] =
node.data.sortCode == null ? 'synthetic-branch' : 'sort-code-branch';
result.push({
id,
parent,
text: node.text,
droppable: true,
data: {
nodeType,
isOpen: node.data.isOpen,
...(node.data.hebrewText == null ? {} : { hebrewText: node.data.hebrewText }),
...(node.data.sortCode == null ? {} : { sortCode: node.data.sortCode }),
},
});
processedIds.add(id);
// Expand descendantFinancialEntities into explicit leaf nodes
for (const uuid of node.data.descendantFinancialEntities ?? []) {
if (explicitLeafIds.has(uuid) || processedIds.has(uuid)) continue;
const bizSum = sumById.get(uuid);
if (!bizSum) continue;
processedIds.add(uuid);
result.push({
id: uuid,
parent: id,
text: bizSum.business.name,
droppable: false,
data: {
nodeType: 'financial-entity',
value: bizSum.total.raw * -1,
isOpen: false,
},
});
}
} else {
// Explicit leaf already in template — keep as-is (hydrated from businessSums if available)
const bizSum = sumById.get(id);
if (!bizSum) continue;
result.push({
id,
parent,
text: bizSum.business.name,
droppable: false,
data: {
nodeType: 'financial-entity',
value: bizSum.total.raw * -1,
isOpen: node.data.isOpen,
...(node.data.hebrewText == null ? {} : { hebrewText: node.data.hebrewText }),
},
});
processedIds.add(id);
}
}
return result;
}