// Fusion Accounting - Report Utility Functions // Copyright (C) 2026 Nexa Systems Inc. const LINE_ID_HIERARCHY_DELIMITER = "|"; const LINE_ID_GROUP_DELIMITER = "~"; /** * Constructs a hierarchical line identifier string from an array of * [markup, model, value] tuples, using delimiters for serialization. * @param {Array} current - Array of [markup, model, value] tuples * @returns {string} Serialized line ID */ export function buildLineId(current) { const convertNull = (value) => { if (value === null || value === undefined || value === false) { return ""; } else if (typeof value === "object") { // We're using the replaceAll to follow the python // behavior where we're stringify a dict. return JSON.stringify(value).replaceAll('":', '": '); } return value; }; return current .map(([markup, model, value]) => { const lineValues = [convertNull(markup), convertNull(model), convertNull(value)]; return lineValues.join(LINE_ID_GROUP_DELIMITER); }) .join(LINE_ID_HIERARCHY_DELIMITER); } /** * Parses a serialized line ID string back into an array of * [markup, model, value] tuples. * @param {string} lineID - The serialized line ID string * @param {boolean} markupAsString - If true, keeps markup as raw string * @returns {Array} Array of [markup, model, value] tuples */ export function parseLineId(lineID, markupAsString = false) { const parseMarkup = (markup) => { if (!markup) { return markup; } try { const result = JSON.parse(markup); return typeof result === "object" ? result : markup; } catch { return markup; } }; if (!lineID) { return []; } return lineID.split(LINE_ID_HIERARCHY_DELIMITER).map((key) => { const [markup, model, value] = key.split(LINE_ID_GROUP_DELIMITER); return [ (markupAsString ? markup : parseMarkup(markup)) || null, model || null, model && value ? parseInt(value) : value || null, ]; }); } /** * Removes tax grouping segments from a line ID, since tax grouping * is not relevant for annotations and other per-line operations. * @param {string} lineId - The line ID to filter * @returns {string} Line ID with tax group entries removed */ export function removeTaxGroupingFromLineId(lineId) { return buildLineId( parseLineId(lineId, true).filter(([markup, model, value]) => { return model !== "account.group"; }) ); }