ori-data-pipeline/percent-divide.js

106 lines
3.7 KiB
JavaScript

import { parse as parseCSV, stringify as stringifyCSV } from "jsr:@std/csv";
import percentRound from './percent-round.js';
const [totalexpensefile, suppliertotals, indivusagefile] = Deno.args;
const totexpinput = await Deno.readTextFile(totalexpensefile);
const supptotinput = await Deno.readTextFile(suppliertotals);
const supptots = await parseCSV(supptotinput, {skipFirstRow: true});
const asntot = supptots.find(e => e.account === 'Bank').amount;
const ivbinput = await Deno.readTextFile(indivusagefile);
const txp = await parseCSV(totexpinput, {skipFirstRow: true});
const ivb = await parseCSV(ivbinput, {skipFirstRow: true});
const vbByPeriod = Object.groupBy(ivb, i => i.period);
const totalMonths = ivb.reduce((a,b) => a + parseInt(b.months),0)
const vbRowsByUser = Object.groupBy(ivb, i => i.account);
const entriesWithPercents = [];
//values is an array of objects with props 'months' and 'usages'.
for (const [key, values] of Object.entries(vbByPeriod)) {
const months = values.map(p => p.months);
const percents_mo = percentRound(months, 4);
const usages = values.map(p => p.usage);
const percents_us = percentRound(usages, 0);
for (let [index, value] of values.entries()) {
value.percent_mo = percents_mo[index];
value.percent_us = percents_us[index];
entriesWithPercents.push(value);
}
}
const userMonthsTotal = [];
for (const [key, value] of Object.entries(vbRowsByUser)) {
const monthssum = value.reduce((a,b) => a + parseInt(b.months),0);
userMonthsTotal.push({account: key, months: monthssum});
}
//oh, for ASN I need the total percentage for the whole dataset.
//create a single record for each user at the end and add it to the array created for var expenses.
const global_mo_perc = percentRound(userMonthsTotal.map(t => t.months), 2);
for (const [index, value] of userMonthsTotal.entries()) {
value.percent_mo = global_mo_perc[index];
}
const asnExpSrc = userMonthsTotal.map((entry) => {
entry.amount = bankersRound(entry.percent_mo / 100 * asntot);
return entry;
})
const totExpByPeriod = {};
for (const p of txp) {
totExpByPeriod[p.period] = p;
}
const withElecExp = entriesWithPercents.map((entry) => {
entry.fixed_exp = bankersRound(entry.percent_mo / 100 * parseFloat(totExpByPeriod[entry.period].exp_fixed));
entry.date = totExpByPeriod[entry.period].enddate;
entry.var_exp = bankersRound(entry.percent_us / 100 * parseFloat(totExpByPeriod[entry.period].exp_var));
return entry;
})
// console.log(withElecExp);
//
// I guess I could check whether these amounts add up ...
const output = [];
for (const {period, account, fixed_exp, date, var_exp} of withElecExp) {
const omschrijving_var = 'value of variable expenses';
const omschrijving_fixed = 'value of fixed expenses';
//fixed
output.push({id: `${period}_${account}_fixed`, datum: date, from: 'shared', amount: fixed_exp, to: account , omschrijving: omschrijving_fixed});
//var
output.push({id: `${period}_${account}_var`, datum: date, from: 'shared', amount: var_exp, to: account, omschrijving: omschrijving_var});
}
//emhans: var: 75537, fixed 33746
for (const {account, amount} of asnExpSrc) {
output.push({id: `${account}_asn`, datum: '2025-12-31', from: 'shared', amount, to: account , omschrijving: 'value of banking costs ASN'});
}
console.log(stringifyCSV(output, {columns: ['id', 'datum', 'from', 'amount', 'to', 'omschrijving']} ).replace(/\n$/, ""));
//from https://stackoverflow.com/a/49080858
function bankersRound(n, d=2) {
var x = n * Math.pow(10, d);
var r = Math.round(x);
var br = Math.abs(x) % 1 === 0.5 ? (r % 2 === 0 ? r : r-1) : r;
return br / Math.pow(10, d);
}
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}