All files / src/utils/generators payloadGenerator.ts

78.84% Statements 41/52
61.29% Branches 19/31
88.88% Functions 8/9
82.6% Lines 38/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                                4x         1x   17x   17x 2x       1x                 1x 1x     1x 1x           1x     4x 19x 19x     4x 2x 2x     4x 2x 2x   2x 2x   2x 2x   2x 2x       2x 2x   2x           2x   2x       2x   2x 2x 2x 2x                 2x     4x  
import { isCountryUSA } from "@components/Settings/BusinessDetails/components/MerchantInfoSection/utils/utils";
import { get } from "lodash";
 
type TRawData = Record<string, any>;
type TAttributeSchema = {
  name: string;
  apiKey?: string;
  parser?: (value: any) => any;
};
type TPayloadSchema = Array<TAttributeSchema>;
 
type DirtyFieldsSubSet = Partial<Record<string, boolean>>;
type GeneratorOptions = {
  dirtyFields?: Partial<Record<string, boolean | DirtyFieldsSubSet>>;
};
 
export const payloadGenerator = (
  data: TRawData,
  payloadSchema: TPayloadSchema,
  options?: GeneratorOptions,
) => {
  const payload: any = payloadSchema.reduce((acc, currentElement) => {
    const isNotDirty =
      options?.dirtyFields &&
      !getValueFromObject(currentElement.name, options?.dirtyFields);
    if (isNotDirty) return acc;
    return extendObject(acc, generateEntry(data, currentElement));
  }, {});
 
  // to update class description, 'class:"other"' field is also needed to be sent in payload
  Iif (
    data.classification === "other" &&
    (payload.classDescription || payload.class)
  ) {
    payload.class = "other";
    payload.classDescription = data.classDescription;
  }
  // if outside use BE expect this field as true and if the user enter USA we should not send.
  //bc based on serviceCountriesOutUSCanada return the error
  if (data.is_outside_usa && !isCountryUSA(data.countriesOutside)) {
    payload.serviceCountriesOutUSCanada = true;
  } else Epayload.serviceCountriesOutUSCanada = false;
  //this logic is to handle: if the countriesOutside is unchecked to reset the countris in BE as well
  if (data.is_outside_usa) {
    payload.countriesServicedOutside = data.countriesOutside;
  } else E{
    payload.countriesServicedOutside = "";
    payload.countriesOutside = "";
  }
 
  return payload;
};
 
const getValueFromObject = (attributeKey: string, obj: Record<any, any>) => {
  const accessKeys = attributeKey.split(".");
  return get(obj, accessKeys);
};
 
const checkValidity = (value: any) => {
  const validApiFalsyValues = [null, 0, ""];
  return !!value || validApiFalsyValues.some((a) => value === a);
};
 
const generateEntry = (data: TRawData, element: TAttributeSchema) => {
  const { name, apiKey, parser } = element;
  const attributeValue = getValueFromObject(name, data);
 
  const isValidAPIValue = checkValidity(attributeValue);
  Iif (!isValidAPIValue) return undefined;
 
  const value = parser ? parser(attributeValue) : attributeValue;
  const attributeKey = apiKey || name;
 
  const splits = attributeKey.split(".");
  return createNestedObject(splits, value);
};
 
function createNestedObject(keys: string[], value: any) {
  const obj: Record<any, any> = {};
  let currentObj = obj;
 
  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    currentObj[key] = {};
    currentObj = currentObj[key];
  }
 
  currentObj[keys[keys.length - 1]] = value;
 
  return obj;
}
 
function extendObject(target: Record<any, any>, obj?: Record<any, any>) {
  Iif (!isValidObject(obj)) return target;
 
  let returnTarget = target;
  for (const key in obj) {
    Eif (Object.prototype.hasOwnProperty.call(obj, key)) {
      returnTarget = {
        ...returnTarget,
        [key]:
          typeof obj[key] === "object"
            ? extendObject(target[key], obj[key])
            : obj[key],
      };
    }
  }
  return returnTarget;
}
 
const isValidObject = (obj: any) => !!obj && typeof obj === "object";