department-of-veterans-affairs/vets-website

View on GitHub
src/applications/financial-status-report/actions/geographicMeansThreshold.js

Summary

Maintainability
A
0 mins
Test Coverage
/**
 * This module provides functionality to retrieve GMT (Geographical Mean Test) thresholds.
 * It supports fetching data from production, staging, or using mock data based on configuration toggles.
 *
 * @module geographicMeanTest
 */

import * as Sentry from '@sentry/browser';
import { apiRequest } from 'platform/utilities/api';
import environment from 'platform/utilities/environment';
import {
  USE_GEOGRAPHIC_MOCK_DATA,
  MOCK_GMT_VALUE,
  USE_STAGING_DATA,
} from '../mocks/development';

// Constants used for calculating thresholds
import {
  INCOME_UPPER_PERCENTAGE,
  ASSET_PERCENTAGE,
  DISCRETIONARY_INCOME_PERCENTAGE,
} from '../constants/gmtCalculationTypes';

const isLocalhost = environment.isLocalhost();

// only to be updated when downstream services are updated
//  check with sitewide-public-websites to confirm income_limits also contains
//  data for the new year from VES
const GMT_YEAR = 2024;

/**
 * Helper calculates and returns the income upper threshold, asset threshold, and discretionary income threshold
 * based on the given GMT value.
 *
 * @param {number} gmtValue - The GMT (Geographical Mean Test) value used for calculations.
 * @returns {Object} An object containing calculated thresholds.
 */

const calculateThresholds = gmtValue => {
  const incomeUpperThreshold = gmtValue * INCOME_UPPER_PERCENTAGE;
  const assetThreshold = gmtValue * ASSET_PERCENTAGE;
  const discretionaryIncomeThreshold =
    gmtValue * DISCRETIONARY_INCOME_PERCENTAGE;

  return {
    incomeUpperThreshold,
    assetThreshold,
    discretionaryIncomeThreshold,
  };
};

/**
 * Determines the appropriate data source based on configuration settings and environment.
 * Leverages GMT_YEAR constant for the year of the data being requested.
 *
 * @param {number} dependents - The number of dependents.
 * @param {string} zipCode - The ZIP code for which data is being requested.
 * @returns {string} The URL of the data source.
 */

const getDataUrl = (dependents, zipCode) => {
  if (isLocalhost && USE_GEOGRAPHIC_MOCK_DATA) {
    return null; // Return mock data directly
  }

  if (isLocalhost && USE_STAGING_DATA) {
    return `https://staging-api.va.gov/income_limits/v1/limitsByZipCode/${zipCode}/${GMT_YEAR}/${dependents}`;
  }

  return `${
    environment.API_URL
  }/income_limits/v1/limitsByZipCode/${zipCode}/${GMT_YEAR}/${dependents}`;
};

/**
 * Retrieves GMT thresholds data. Depending on configuration, it either fetches data from an API,
 * uses staging data, or returns mock data (if enabled).
 *
 * @param {number} dependents - The number of dependents.
 * @param {string} zipCode - The ZIP code for which data is being requested.
 * @returns {Promise<Object>} A promise resolving to the GMT thresholds data or error object.
 */
export const getGMT = async (dependents, zipCode) => {
  const dataUrl = getDataUrl(dependents, zipCode);

  if (dataUrl === null && isLocalhost) {
    // Mock data scenario
    return Promise.resolve({
      gmtThreshold: MOCK_GMT_VALUE,
      error: null,
      ...calculateThresholds(MOCK_GMT_VALUE),
    });
  }

  try {
    const { data } = await apiRequest(dataUrl);

    if (typeof data.gmtThreshold !== 'number') {
      throw new Error('GMT threshold is not a number');
    }

    return {
      ...data,
      ...calculateThresholds(data.gmtThreshold),
      error: null,
    };
  } catch (error) {
    Sentry.withScope(scope => {
      scope.setExtra('error', error);
      Sentry.captureMessage(`income_limits failed: ${error}`);
    });

    return { gmtThreshold: null, error };
  }
};