Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
19 kB
1
Indexable
Never
const { sanitizeEntity } = require("strapi-utils");
const { respond, respondWithError, translation } = require("@macromo/tools");
const {
  TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_ANCESTRY,
  TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_DISEASES,
  TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_TRAITS,
  TRANSLATION_INSIGHTS_SYSTEMS_DESCRIPTION_ANCESTRY,
} = require("@macromo/enums");
const {
  responses: { FORBIDDEN, INTERNAL_SERVER_ERROR },
} = strapi.config.get("server");
const {
  responses: {
    INSIGHTS_DISEASE_NOT_FOUND,
    INSIGHTS_MACROMO_ID_NOT_DEFINED,
    INSIGHTS_MEDICATION_NOT_FOUND,
    INSIGHTS_SYSTEM_ID_NOT_DEFINED,
    INSIGHTS_SYSTEM_NOT_FOUND,
    INSIGHTS_TRAIT_NOT_FOUND,
  },
} = strapi.config.get("insights");

module.exports = {
  async getAncestry(ctx) {
    const {
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const { ancestry: ancestryGroups = {} } = medicalResultsState.toJSON();
      const ancestryIds = Object.keys(ancestryGroups);

      const ancestryState = await strapi
        .query("ancestry")
        .model.fetchAll(strapi.services["insights-schema"].ancestryBasic);
      const ancestry = ancestryState.toJSON();

      const payload = {
        description: {
          key: TRANSLATION_INSIGHTS_SYSTEMS_DESCRIPTION_ANCESTRY,
        },
        origins: ancestry.reduce((acc, { displayName, macromoId }) => {
          if (ancestryIds.includes(macromoId)) {
            acc.push(
              sanitizeEntity(
                { displayName, value: ancestryGroups[macromoId] },
                { model: strapi.models.ancestry }
              )
            );
          }

          return acc;
        }, []),
      };

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },
  async getDiseases(ctx) {
    const {
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const diseasesState = await strapi
        .query("disease")
        .model.fetchAll(strapi.services["insights-schema"].diseasesBasic);
      const diseases = diseasesState.toJSON();

      const medicalResultsIds =
        medicalResults.results?.insights?.map(({ macromoId }) => macromoId) ||
        [];

      const payload = diseases.reduce((acc, cur) => {
        if (medicalResultsIds.includes(cur.macromoId)) {
          const level = medicalResults.results?.insights?.find(
            ({ macromoId }) => macromoId === cur.macromoId
          )?.riskScore;

          return [
            ...acc,
            sanitizeEntity({ ...cur, level }, { model: strapi.models.disease }),
          ];
        }

        return acc;
      }, []);

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getDiseaseById(ctx) {
    const {
      params: { macromoId },
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });
    if (!macromoId) {
      return respondWithError({ ctx, data: INSIGHTS_MACROMO_ID_NOT_DEFINED });
    }

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const diseaseState = await strapi
        .query("disease")
        .model.query((q) => {
          q.where("macromoId", macromoId);
        })
        .fetch(strapi.services["insights-schema"].diseaseDetails);

      if (!diseaseState) {
        return respondWithError({ ctx, data: INSIGHTS_DISEASE_NOT_FOUND });
      }

      const { ...disease } = diseaseState.toJSON();

      const level = medicalResults.results?.insights?.find(
        (insight) => insight.macromoId === macromoId
      )?.riskScore;

      const payload = sanitizeEntity(
        {
          ...disease,
          level,
        },
        { model: strapi.models.disease }
      );

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getInsightsOverview(ctx) {
    const {
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });

    try {
      const questionnairesState = await strapi
        .query("questionnaire")
        .model.query((q) =>
          q.where("userId", userId).whereNotNull("questionnaireId")
        )
        .fetchAll();
      const questionnaires = questionnairesState.toJSON();

      const questionnaireTemplateState = await strapi
        .query("questionnaire_template")
        .model.fetchAll();
      const questionnaireTemplate = questionnaireTemplateState.toJSON();

      const kitsState = await strapi
        .query("kit")
        .model.query((q) => q.where("userId", userId))
        .fetchAll();
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const onboarding = {
        "health-profile": questionnaireTemplate.length
          ? Math.round(
              (questionnaires.length / questionnaireTemplate.length +
                Number.EPSILON) *
                100
            ) / 100
          : 0,
        insights: 0,
        kit: +!!kits.length,
      };

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({
          ctx,
          data: {
            payload: {
              categories: [],
              diseases: [],
              onboarding,
            },
          },
        });
      }

      const medicalResults = medicalResultsState.toJSON();
      const medicalResultsIds =
        medicalResults.results?.insights?.map(({ macromoId }) => macromoId) ||
        [];
      const ancestryIds = Object.keys(medicalResults.ancestry || {});

      const ancestryState = await strapi
        .query("ancestry")
        .model.fetchAll(strapi.services["insights-schema"].ancestryBasic);

      const diseasesState = await strapi
        .query("disease")
        .model.fetchAll(strapi.services["insights-schema"].diseasesBasic);
      const diseases = diseasesState.toJSON();

      const traitsState = await strapi
        .query("trait")
        .model.fetchAll(strapi.services["insights-schema"].traitsBasic);
      const traits = traitsState.toJSON();

      const ancestry = ancestryState.toJSON();

      const payload = {
        categories: [
          {
            count: ancestry.filter(({ macromoId }) =>
              ancestryIds.includes(macromoId)
            ).length,
            displayName: {
              key: TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_ANCESTRY,
            },
          },
          {
            count: traits.filter(({ macromoId }) =>
              medicalResultsIds.includes(macromoId)
            ).length,
            displayName: {
              key: TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_TRAITS,
            },
          },
          {
            count: diseases.filter(({ macromoId }) =>
              medicalResultsIds.includes(macromoId)
            ).length,
            displayName: {
              key: TRANSLATION_INSIGHTS_SYSTEMS_CATEGORY_DISEASES,
            },
          },
        ],
        diseases: diseases.reduce((acc, cur) => {
          if (medicalResultsIds.includes(cur.macromoId)) {
            const level = medicalResults.results?.insights?.find(
              (insight) => insight.macromoId === cur.macromoId
            )?.riskScore;

            return [
              ...acc,
              sanitizeEntity(
                { ...cur, level },
                { model: strapi.models.disease }
              ),
            ];
          }

          return acc;
        }, []),
        onboarding: {
          ...onboarding,
          insights: +!!medicalResults,
        },
      };

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getMedications(ctx) {
    const {
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const medicationsState = await strapi
        .query("medication")
        .model.fetchAll(strapi.services["insights-schema"].medicationsBasic);
      const medications = medicationsState.toJSON();

      const medicalResultsIds =
        medicalResults?.results?.insights?.map(({ macromoId }) => macromoId) ||
        [];

      const payload = medications.reduce((acc, cur) => {
        if (medicalResultsIds.includes(cur.macromoId)) {
          const level = medicalResults?.results?.insights?.find(
            (insight) => insight.macromoId === cur.macromoId
          )?.riskScore;

          return [
            ...acc,
            sanitizeEntity(
              { ...cur, level },
              { model: strapi.models.medication }
            ),
          ];
        }

        return acc;
      }, []);

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getMedicationById(ctx) {
    const {
      params: { macromoId },
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });
    if (!macromoId) {
      return respondWithError({ ctx, data: INSIGHTS_MACROMO_ID_NOT_DEFINED });
    }

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const medicationState = await strapi
        .query("medication")
        .model.query((q) => {
          q.where("macromoId", macromoId);
        })
        .fetch(strapi.services["insights-schema"].medicationDetails);

      if (!medicationState) {
        return respondWithError({ ctx, data: INSIGHTS_MEDICATION_NOT_FOUND });
      }

      const medication = medicationState.toJSON();

      const level = medicalResults?.results?.insights?.find(
        (insight) => insight.macromoId === macromoId
      )?.riskScore;

      const payload = sanitizeEntity(
        {
          ...medication,
          level,
        },
        { model: strapi.models.medication }
      );

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getTraits(ctx) {
    const {
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!userId) return respondWithError({ ctx, data: FORBIDDEN });

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const traitsState = await strapi
        .query("trait")
        .model.fetchAll(strapi.services["insights-schema"].traitsBasic);
      const traits = traitsState.toJSON();

      const medicalResultsIds =
        medicalResults.results?.insights?.map(({ macromoId }) => macromoId) ||
        [];

      const payload = traits.reduce((acc, cur) => {
        if (medicalResultsIds.includes(cur.macromoId)) {
          const level = medicalResults.results?.insights?.find(
            (insight) => insight.macromoId === cur.macromoId
          )?.riskScore;

          return [
            ...acc,
            sanitizeEntity({ ...cur, level }, { model: strapi.models.trait }),
          ];
        }

        return acc;
      }, []);

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  async getTraitById(ctx) {
    const {
      params: { macromoId },
      state: { user },
    } = ctx;
    const { id: userId } = user;

    if (!macromoId) {
      return respondWithError({ ctx, data: INSIGHTS_MACROMO_ID_NOT_DEFINED });
    }

    try {
      const kitsState = await strapi
        .query("kit")
        .model.query((q) => {
          q.where("userId", userId);
        })
        .fetchAll(strapi.services["insights-schema"].kits);
      const kits = kitsState.toJSON();

      const kitId = kits[0]?.id;

      const medicalResultsState = kitId
        ? await strapi
            .query("medical_result")
            .model.query((q) => {
              q.where("kit", kitId).andWhere("completed", true);
            })
            .fetch(strapi.services["insights-schema"].medicalResults)
        : undefined;

      if (!medicalResultsState) {
        return respond({ ctx });
      }

      const medicalResults = medicalResultsState.toJSON();

      const traitState = await strapi
        .query("trait")
        .model.query((q) => {
          q.where("macromoId", macromoId);
        })
        .fetch(strapi.services["insights-schema"].traitDetails);

      if (!traitState) {
        return respondWithError({ ctx, data: INSIGHTS_TRAIT_NOT_FOUND });
      }

      const trait = traitState.toJSON();

      const level = medicalResults?.results?.insights?.find(
        (insight) => insight.macromoId === macromoId
      )?.riskScore;

      const payload = sanitizeEntity(
        {
          ...trait,
          level,
        },
        { model: strapi.models.trait }
      );

      respond({ ctx, data: { payload } });
    } catch (error) {
      respondWithError({ ctx, data: INTERNAL_SERVER_ERROR, error });
    }
  },

  // TODO - check, update errors
  // CAUTION - doesn't work now!!!
  async isUserInsightReady(ctx) {
    const userId = ctx.state.user.id;

    const user = await strapi
      .query("user", "users-permissions")
      .findOne({ id: userId });
    if (!user) {
      return ctx.badRequest("User not found");
    }

    try {
      const insight = await strapi
        .query("medical_result")
        .findOne({ userId, completed: true });

      if (!insight) {
        return (ctx.body = {
          statusCode: 200,
          message: "Insights are not ready.",
        });
      } else {
        // TODO: lang is missing, AWS is calling this route, wrong email template.
        if (user.email) {
          await strapi.services.user.sendInsightReadyEmail(user);
        } else {
          await strapi.services.sms.send(
            "Your insights are ready! Please open Macromo" +
              " application. https://www.macromo.org",
            user.phone
          );
        }

        ctx.body = {
          statusCode: 200,
          insightId: insight.id,
          isReady: insight.completed,
        };
      }
    } catch (e) {
      console.error(e);
      ctx.status = 500;
      ctx.body = {
        statusCode: 500,
        error: "Internal server error",
      };
    }
  },
};