skip to Main Content

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:

enter image description here

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


  1. Chosen as BEST ANSWER

    I have since re-written my code in a better way;

    my new code:

            var valuePairs = [];
    var inc; var ex;
    var amounts = [ 5000, 2000, 2000, 1834.86, 1652.89, 1000, 961.5385, 15, 12,3,1];
    var btwTypes = [21,13,9,4];
    
    function tester(){
      // console.log(roundTo(5000,0));
      console.log("final output = [" + theBtwFinder(btwTypes) + "]");
    }
    
    function theBtwFinder(rates){
      while(rates.length>0){
        if (findValuePair(rates[0]) != undefined){
          valuePairs.push(findValuePair(rates[0])[0]); valuePairs.push(findValuePair(rates[0])[1])
    
          if(roundTo(sumArrayEvenIndices(valuePairs),0) == roundTo(amounts[0],0)){
          return valuePairs;
          }
          }
          btwTypes.shift(); //remove first item of 'btwTypes' Array since we're done checking for that btw percentage
        }
      }
    
    function findValuePair(deltaPercentage){
      for(i=0;i<amounts.length;i++){
        for(j=0;j<amounts.length;j++){
          if(i!=j){ //don't check value against itself
            if ( roundTo(amounts[i]/amounts[j], 2) == (1 + deltaPercentage/100) ){
              inc = amounts[i]; ex = amounts[j];
              return[inc, ex];
            }else if( roundTo(amounts[i]/amounts[j], 2) == (deltaPercentage/100) ){
              inc = amounts[i]+amounts[j]; ex = amounts[j];
              return[inc, ex];
            }
          }
        }
      }
      return undefined; //no pair found
    }
    
    // $$$ HELPER FUNCTIONS $$$
    function sumArrayEvenIndices(array){
      var sum = 0;
      for(index in array){
        if (!(index % 2)){ //of index is even
          sum += array[index];
        }
      }
        return sum; 
        }
    
    function roundTo(num, decimals) {
      return ( +num.toFixed(decimals));
    }
    

    Visual representation of what the code does:

    function input: enter image description here


  2. I hope this can help

    function findBtwPairs(taxRates, values) {
        let taxAmounts = [];
    
        for (let rate of taxRates) {
            let found = false;
    
            for (let i = 0; i < values.length; i++) {
                for (let j = i + 1; j < values.length; j++) {
                    let exTax = values[j];
                    let incTax = values[i] - exTax;
    
                    if (Math.abs(incTax / exTax * 100 - rate) < 0.01) {
                        taxAmounts.push([values[i], exTax]);
                        found = true;
                        break;
                    }
                }
                if (found) break;
            }
        }
        return taxAmounts;
    }
    
    // Example usage:
    let values = [4000, 2500, 2066.12, 2000, 1834.86];
    let taxRates = [9, 21];
    let result = findBtwPairs(taxRates, values);
    console.log(result);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search