department-of-veterans-affairs/vets-website

View on GitHub
src/applications/ivc-champva/10-10D/config/submitTransformer.js

Summary

Maintainability
B
4 hrs
Test Coverage
import { transformForSubmit as formsSystemTransformForSubmit } from 'platform/forms-system/src/js/helpers';
import { FILE_UPLOAD_ORDER } from './constants';
import {
  adjustYearString,
  concatStreets,
  getAgeInYears,
} from '../../shared/utilities';

// Rearranges date string from YYYY-MM-DD to MM-DD-YYYY
function fmtDate(date) {
  return date?.length && date.length === 10
    ? `${date.slice(5)}-${date.slice(0, 4)}`
    : date;
}

// Returns list of object keys where obj[key] === true. Used
// to get the list of relationships a certifier has w/ the applicants:
function trueKeysOnly(obj) {
  return Object.keys(obj ?? {}).filter(k => obj[k] === true);
}

// Simplify a relationship object from (potentially) multiple nested objects to a single string
function transformRelationship(obj) {
  if (typeof obj === 'string') return obj;
  let rel = obj?.relationshipToVeteran;
  // Check if relationshipToVeteran is an object
  if (typeof obj?.relationshipToVeteran === 'object') {
    // Iterate over keys in relationshipToVeteran object
    Object.keys(obj?.relationshipToVeteran).forEach(key => {
      // edge case for certifier relationship (generated by a checkboxgroup):
      if (obj?.relationshipToVeteran[key] === true) {
        rel = key; // e.g., `'spouse': true` yields `'spouse'`
      }
    });
  }
  // Check if otherRelationshipToVeteran is a string
  if (typeof obj?.otherRelationshipToVeteran === 'string') {
    rel = obj?.otherRelationshipToVeteran;
  }

  return rel;
}

// For each applicant, adjust organization of the object, add supporting documents array
function transformApplicants(applicants) {
  const applicantsPostTransform = [];
  applicants.forEach(app => {
    let transformedApp = {
      ...app,
      ssnOrTin: app.applicantSSN?.ssn ?? '',
      vetRelationship: transformRelationship(
        app.applicantRelationshipToSponsor || 'NA',
      ),
      // Grab any file upload properties from this applicant and combine into a
      // supporting documents array:
      applicantSupportingDocuments: FILE_UPLOAD_ORDER.map(
        property => app?.[property],
      ).filter(el => el), // Drop any undefineds/nulls
    };
    transformedApp = adjustYearString(transformedApp);
    transformedApp.applicantAddress = concatStreets(
      transformedApp.applicantAddress,
    );
    applicantsPostTransform.push(transformedApp);
  });
  return applicantsPostTransform;
}

export default function transformForSubmit(formConfig, form) {
  const transformedData = JSON.parse(
    formsSystemTransformForSubmit(formConfig, form),
  );

  if (transformedData.sponsorAddress)
    transformedData.sponsorAddress = concatStreets(
      transformedData.sponsorAddress,
    );

  if (transformedData.certifierAddress)
    transformedData.certifierAddress = concatStreets(
      transformedData.certifierAddress,
    );

  const currentDate =
    fmtDate(new Date().toISOString().replace(/T.*/, '')) || '';

  const dataPostTransform = {
    veteran: {
      fullName: transformedData?.veteransFullName || {},
      ssnOrTin: transformedData?.ssn?.ssn || '',
      vaClaimNumber: transformedData?.ssn?.vaFileNumber || '',
      dateOfBirth: fmtDate(transformedData?.sponsorDob) || '',
      phoneNumber: transformedData?.sponsorPhone || '',
      address: transformedData?.sponsorAddress || {},
      sponsorIsDeceased: transformedData?.sponsorIsDeceased,
      dateOfDeath: fmtDate(transformedData?.sponsorDOD) || '',
      // Find the first applicant with a date of marriage to sponsor
      dateOfMarriage:
        fmtDate(
          transformedData?.applicants?.find(
            a =>
              a?.applicantRelationshipToSponsor?.relationshipToVeteran ===
                'spouse' && a?.dateOfMarriageToSponsor !== undefined,
          )?.dateOfMarriageToSponsor,
        ) || '',
      isActiveServiceDeath: transformedData?.sponsorDeathConditions,
    },
    applicants: transformApplicants(transformedData.applicants ?? []),
    // If certifier is also applicant, we don't need to fill out the
    // bottom "Certification" section of the PDF:
    certification:
      transformedData?.certifierRole === 'applicant'
        ? { date: currentDate }
        : {
            date: currentDate,
            lastName: transformedData?.certifierName?.last || '',
            middleInitial: transformedData?.certifierName?.middle || '',
            firstName: transformedData?.certifierName?.first || '',
            phoneNumber: transformedData?.certifierPhone || '',
            // will produce string list of checkboxgroup keys (e.g., "spouse; child")
            relationship: trueKeysOnly(
              transformedData?.certifierRelationship?.relationshipToVeteran,
            ).join('; '),
            streetAddress:
              transformedData?.certifierAddress?.streetCombined || '',
            city: transformedData?.certifierAddress?.city || '',
            state: transformedData?.certifierAddress?.state || '',
            postalCode: transformedData?.certifierAddress?.postalCode || '',
          },
    supportingDocs: [],
    // Include everything we originally received
    rawData: transformedData,
  };

  // Flatten supporting docs for all applicants to a single array
  const supDocs = [];
  dataPostTransform.applicants.forEach(app => {
    if (app.applicantSupportingDocuments.length > 0) {
      app.applicantSupportingDocuments.forEach(doc => {
        if (doc !== undefined && doc !== null) {
          // doc is an array of files for a given input (e.g., insurance cards).
          // For clarity's sake, add applicant's name onto each file object:
          const files = doc.map(file => ({
            ...file,
            applicantName: app.applicantName,
          }));
          supDocs.push(...files);
        }
      });
    }
  });

  // Set a top-level boolean indicating if any applicants are over 65
  dataPostTransform.hasApplicantOver65 = dataPostTransform.applicants.some(
    app => getAgeInYears(app.applicantDob) >= 65,
  );

  dataPostTransform.supportingDocs = dataPostTransform.supportingDocs
    .flat()
    .concat(supDocs);
  dataPostTransform.certifierRole = transformedData.certifierRole;
  dataPostTransform.statementOfTruthSignature =
    transformedData.statementOfTruthSignature;
  // `primaryContactInfo` is who BE callback API emails if there's a notification event
  dataPostTransform.primaryContactInfo = {
    name: transformedData.certifierName,
    email: transformedData.certifierEmail,
    phone: transformedData.certifierPhone,
  };
  return JSON.stringify({
    ...dataPostTransform,
    formNumber: formConfig.formId,
  });
}