tool/salarysacrifice/utils.js

import { Forecast } from '../forecast/forecast';

/**
 * salsac is based on an average over the period so get an average of the employer
 * NI
 * @param {array} arr_tax_years
 * @returns {number}
 */
const getAverageErNIrate = (
    arr_tax_years,
) => {
    const cnt_years = arr_tax_years.length;
    let total = 0;
    let months = 0;

    for (let i = 0; i < cnt_years; i += 1) {
        const { months_occupied } = arr_tax_years[i];
        months += months_occupied;
        const coverage_ratio = months_occupied / 12;
        const { skv_tax_charges } = arr_tax_years[i];
        total += (skv_tax_charges.national_insurance.employer.class1A * coverage_ratio);
    }

    return total / (months / 12);
};

/**
     * Do the forecast for the period covered
     * @param {struct} skv_config
     * @param {array} arr_tax_charges income tax, nic rates for the period retrieved from pluto
     * @param {array} arr_tax_company_vehicle vehicle benefit, co2 percentage charge for the period retrieved from pluto
     * @returns {array} Tax years
     */
const getTaxYears = (
    skv_config,
    arr_tax_charges,
    arr_tax_company_vehicle = [],
) => {
    const config = JSON.parse(JSON.stringify(skv_config));

    const skv_forecast_config = {
        start_month: config.start_month,
        start_year: config.start_year,
        period_months: config.months,
        region_code: config.tax_region_code,
        arr_injectors: [{
            type: 'salary',
            args: {
                salary: config.salary_pa,
            },
        }],
    };

    // if no tax info for company vehicle don't include the company vehicle injector
    // as we'll be calculating without salary sacrifice and no company vehicle
    if (arr_tax_company_vehicle.length) {
        skv_forecast_config.arr_injectors.push(
            {
                type: 'company_vehicle',
                args: {
                    co2_after_options: config.co2_after_options,
                    p11d_inc_taxable_options: config.p11d + config.num_total_options_taxable,
                    fuel_type: config.fuel_type,
                    explicit_zero_fuel: true,
                    with_fuel: config.with_private_fuel,
                },
            },
        );
    }

    const forecast = new Forecast(
        skv_forecast_config,
        arr_tax_charges,
        arr_tax_company_vehicle,
    );

    return forecast.calculateTaxes();
};

/**
 * calculate bch costs inc irrecoverable vat
 * @param {struct} skv_config
 * @returns {struct} bch cost and irrecoverable vat
 */
const calculateBCHcost = (
    skv_config,
) => {
    const skv_return = {};

    // if employer can reclaim vat, they'll be able to reclaim half the vat
    // otherwise they put the full amount of vat
    const non_recoverable_vat_rate = skv_config.vat_percentage / (skv_config.employer_can_reclaim_vat_on_bch ? 2 : 1);
    const non_recoverable_vat_rate_dec = non_recoverable_vat_rate / 100;

    const { finance_cost, service_fee, num_options_net } = skv_config;

    // work out bch cost portion that company can't reclaim
    const bch_cost = finance_cost + num_options_net;

    skv_return.non_recoverable_vat = bch_cost * non_recoverable_vat_rate_dec;

    // company can't reclaim vat on service fee so tack that on top
    skv_return.bch_cost = bch_cost + service_fee;

    return skv_return;
};

/**
 * Description
 * @param {data_type} param_name Description
 * @returns {data_type} Description
 */
const applyEmployerKeepsNIpercentage = (
    status,
    employer_keeps_ni,
    employer_keeps_ni_percentage,
    employer_break_even_avg_yr,
    arr_tax_years_no_salsac,
) => {
    // handle employer keeps ni net option so we can get a percentage
    const temp_employer_keeps_ni_percentage = employer_keeps_ni === 'net' ? 100 : employer_keeps_ni_percentage;
    // the salsac is an average over the period and the employer ni rate may
    // have changed over the period so get an average
    const avg_rate_dec = (getAverageErNIrate(arr_tax_years_no_salsac) / 100) + 1;
    // i.e if its 100% ni kept on top of employer_break_even_avg_yr
    const full_ni_kept = employer_break_even_avg_yr * avg_rate_dec;
    // work out how much of it is additional ni for the employer
    let amount_ni_kept = full_ni_kept - employer_break_even_avg_yr;
    // apply the % the employer keeps
    amount_ni_kept *= (temp_employer_keeps_ni_percentage / 100);

    return employer_break_even_avg_yr + amount_ni_kept;
};

export {
    getAverageErNIrate,
    getTaxYears,
    calculateBCHcost,
    applyEmployerKeepsNIpercentage,
};