Created
September 29, 2018 15:19
-
-
Save glenndevenish/036af94a5f22f23f27c96f5ce277b3f2 to your computer and use it in GitHub Desktop.
Parse Xero reports from their API into a nicer format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
As it stands, Xero reports from their API are not very nice to use. This function will return them in a flattened format. | |
This takes the Report data (so, `parseXeroReport(response.Reports)` where response is the raw response from the API), and parses it. | |
There's two formats it could take - one where it returns simply the value, and one where it returns an array of values. | |
{ | |
"Date": "30 Sep 2018", | |
"Sales": "12345.67", | |
"Total Income": "12345.67", | |
... | |
} | |
or | |
{ | |
"Date": [ | |
"30 Sep 2018", | |
"30 Sep 2017" | |
], | |
"Some Account Name": [ | |
"234567.89", | |
"123456.78" | |
], | |
"Total Bank": [ | |
"234567.89", | |
"123456.78" | |
] | |
... | |
} | |
You can then use things like: | |
const profitAndLoss = parseXeroReport(ProfitAndLossReport) | |
profitAndLoss["Gross Profit"] = "..." | |
*/ | |
function parseXeroReport (report) { | |
// Internal Functions | |
const arrays = el => Array.isArray(el) | |
const turnIntoObject = (final, el) => { | |
if (final.hasOwnProperty(el[0])) { // don't overwrite existing properties | |
el[0] += ' (copy)' | |
} | |
if (el.length === 2) { | |
final[el[0]] = el[1] | |
} else if (el.length > 2) { // returns 'title': [value1, value2, ...] | |
final[el[0]] = [ | |
...el.slice(1, el.length) | |
] | |
} else { // fail gracefully. set this to [] rather than '' if you are mapping the responses | |
final[el[0]] = '' | |
} | |
return final | |
} | |
const getHeaderValues = (header, cell) => { | |
cell.Value === '' | |
? header.push('Date') // the first one is normally blank, and is where the title goes. | |
: header.push(cell.Value) | |
return header | |
} | |
// Main Function | |
return [].concat(...report[0].Rows.map(row => { | |
if (row.RowType === 'Header') { | |
return [ // return it inside an array, for the reducer below | |
row.Cells.reduce(getHeaderValues, []) | |
] | |
} else if (row.hasOwnProperty('Rows')) { | |
return row.Rows.map(subRow => { | |
return subRow.Cells.map(cell => { | |
return cell.Value | |
}) | |
}) | |
} | |
})) | |
.filter(arrays) // make sure all properties are arrays, so we can reduce them | |
.reduce(turnIntoObject, {}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment