Google Apps Script:
I have an array with numbers.
The array contains monetary values extracted from an invoice.
Another array contains the applicable VAT/tax values.
For each tax value I want to find the applicable value pair(s) in the array.
Example input:
Resulting Input Arrays:
values = [4000, 2500, 2066.12, 2000, 1834.86];
taxRates = [9,21];
The desired output from these inputs would be:
taxAmounts = [[2000,2500][1834.86, 2066,12]];
indicated in the image above in colors where the numbers in the output came from;
taxAmounts[0][0] = 2000 = green = inc tax amount (for taxRates[0])
taxAmounts[1][0] = 1834.86 = brown = ex tax amount (for taxRates[0])
taxAmounts[0][1] = 2500 = yellow = inc tax amount (for taxRates[1])
taxAmounts[1][1] = 2066,12 = pink = ex tax amount (for taxRates[1])
in other words I want to find the following values:
inc tax amount for each taxRate in 'taxRates'
ex tax amount for each taxRate in 'taxRates'
My approach:(pseudo code)
Look for 2 items in array which differ by 21%
when found, check if the highest of these 2 numbers is the highest number in the array
if highest number --> return this number //if highest number then only 1 tax bracket
if not highest number //multiple tax brackets
check for matching value pair for next item in 'taxRates' Array (recursion)
if number found in 1st check + number found in 2nd check = highest number in array -->
return these 2 numbers
else
continue checking for lower % values e.g. 104% until...
...sum of all found values == highest num in array, then return these numbers
if no satisfactory match found after all checks
return undefined;
I have tried to write this in code but not getting correct output so must have made an error (or likely multiple logic errors in my code which I thus far have not been able to fix). Most likely there is a much smarter way to write this.
Any help will be greatly appreciated. Thank you!
my code:
function findBtwPairs(btwRates, amountsArr, incBtwArr, exBtwArr){
for(m=0 ; m < btwRates.length ; m++){
skipIndex = 0;
for (i=0;i<amountsArr.length;i++){
for (j=0;j<amountsArr.length;j++){
if (i!=j){
cond1 = (roundTo((amountsArr[i]/amountsArr[j]),2) == (1+btwRates[m]/100));
cond2 = (roundTo((amountsArr[i]/amountsArr[j]),2) == (btwRates[m]/100));
if (cond1 || cond2){ //inc btw and ex btw specified
if(cond1){incBtw = amountsArr[i]; exBtw = amountsArr[j];}else{incBtw = amountsArr[i]+amountsArr[j]; exBtw = amountsArr[j];};
if(roundTo(incBtw,0) == roundTo(amountsArr[0],0)){ //if found amount is highest number
return [[incBtw], [exBtw]];
}else{ //if found amount NOT highest number
incBtwArr = [incBtw]; exBtw = [exBtw]; //convert to arrays
functionOutput = findBtwPairs(btwRates, amountsArr, incBtw, exBtw);
if(functionOutput != undefined){
incBtwArr = incBtwArr + functionOutput[0]; console.log("functionOutput[0] =" + functionOutput[0]);
exBtwArr = exBtwArr + functionOutput[1]; console.log("functionOutput[1] =" + functionOutput[0]);
} //add found inc. and ex. btw values (e.g. 9% inc/ex value) to 'incBtw' and 'exBtw' Arrays
if (roundTo(sumArray(incBtwArr),0) == roundTo(amountsArr[0]),0){
return [incBtwArr, exBtwArr]
}
} // end of if/else
} // end of if(cond1 || cond2){
} // end of if (i!=j){
} // end of j loop
} // end of i loop
} //end of m loop
console.log( "BTW RATES NOT FOUND USING RATES IN 'btwRates' Array" );
} // end of fn 'findBtwPairs'
//$$ Helper functions $$
function sumArray(array){
return array.reduce(add, 0); // with initial value to avoid when the array is empty
}
function add(accumulator, a) {
return accumulator + a;
}
function roundTo(num, decimals) {
return ( +num.toFixed(decimals));
}
2
Answers
I have since re-written my code in a better way;
my new code:
Visual representation of what the code does:
function input:
I hope this can help