express-api/src/controllers/lookup/lookupController.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { AppDataSource } from '@/appDataSource';
import { PropertyClassification } from '@/typeorm/Entities/PropertyClassification';
import { Request, Response } from 'express';
import {
  BuildingConstructionPublicResponseSchema,
  ClassificationPublicResponseSchema,
  PredominateUsePublicResponseSchema,
  RegionalDistrictPublicResponseSchema,
  TierLevelPublicResponseSchema,
  ProjectStatusPublicResponseSchema,
  ProjectMetadataTypeSchema,
  TaskPublicResponseSchema,
} from './lookupSchema';
import { BuildingPredominateUse } from '@/typeorm/Entities/BuildingPredominateUse';
import { BuildingConstructionType } from '@/typeorm/Entities/BuildingConstructionType';
import { RegionalDistrict } from '@/typeorm/Entities/RegionalDistrict';
import { TierLevel } from '@/typeorm/Entities/TierLevel';
import { ProjectStatus } from '@/typeorm/Entities/ProjectStatus';
import { Task } from '@/typeorm/Entities/Task';
import { PropertyType } from '@/typeorm/Entities/PropertyType';
import { NoteType } from '@/typeorm/Entities/NoteType';
import { MonetaryType } from '@/typeorm/Entities/MonetaryType';
import { TimestampType } from '@/typeorm/Entities/TimestampType';
import { ProjectRisk } from '@/typeorm/Entities/ProjectRisk';
import { Role } from '@/typeorm/Entities/Role';
import { Agency } from '@/typeorm/Entities/Agency';
import { AdministrativeArea } from '@/typeorm/Entities/AdministrativeArea';
import getConfig from '@/constants/config';

/**
 * @description Get all property classification entries.
 * @param {Request}     req Incoming request
 * @param {Response}    res Outgoing response
 * @returns {Response}      A 200 status and a list of property classifications.
 */
export const lookupPropertyClassifications = async (req: Request, res: Response) => {
  const classifications = await AppDataSource.getRepository(PropertyClassification).find();
  const filtered = classifications.filter((c) => !c.IsDisabled);
  const parsed = ClassificationPublicResponseSchema.array().safeParse(filtered);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

export const lookupBuildingPredominateUse = async (req: Request, res: Response) => {
  const uses = await AppDataSource.getRepository(BuildingPredominateUse).find();
  const filtered = uses.filter((u) => !u.IsDisabled);
  const parsed = PredominateUsePublicResponseSchema.array().safeParse(filtered);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

export const lookupBuildingConstructionType = async (req: Request, res: Response) => {
  const uses = await AppDataSource.getRepository(BuildingConstructionType).find();
  const filtered = uses.filter((u) => !u.IsDisabled);
  const parsed = BuildingConstructionPublicResponseSchema.array().safeParse(filtered);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

export const lookupRegionalDistricts = async (req: Request, res: Response) => {
  // Uses sort instead of TypeORM order because some names start with lowercase letters
  const districts = (await AppDataSource.getRepository(RegionalDistrict).find()).sort((a, b) =>
    a.Name.toLowerCase().localeCompare(b.Name.toLowerCase()),
  );
  const parsed = RegionalDistrictPublicResponseSchema.array().safeParse(districts);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * @description Get all project tier level entries.
 * @param {Request}     req Incoming request
 * @param {Response}    res Outgoing response
 * @returns {Response}      A 200 status and a list of project tier levels.
 */
export const lookupProjectTierLevels = async (req: Request, res: Response) => {
  const tiers = (await AppDataSource.getRepository(TierLevel).find()).sort(
    (a, b) => a.SortOrder - b.SortOrder,
  );
  const filtered = tiers.filter((u) => !u.IsDisabled);
  const parsed = TierLevelPublicResponseSchema.array().safeParse(filtered);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * @description Get all project project status entries.
 * @param {Request}     req Incoming request
 * @param {Response}    res Outgoing response
 * @returns {Response}      A 200 status and a list of project statuses.
 */
export const lookupProjectStatuses = async (req: Request, res: Response) => {
  const status = (await AppDataSource.getRepository(ProjectStatus).find()).sort(
    (a, b) => a.SortOrder - b.SortOrder,
  );
  const filtered = status.filter((u) => !u.IsDisabled);
  const parsed = ProjectStatusPublicResponseSchema.array().safeParse(filtered);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * @description Get all possible tasks, optionally select by status id.
 * @param {Request}     req Incoming request
 * @param {Response}    res Outgoing response
 * @returns {Response}      A 200 status and a list of tasks.
 */
export const lookupTasks = async (req: Request, res: Response) => {
  const statusId = req.query.statusId ? parseInt(req.query.statusId.toString()) : undefined;
  const tasks = (
    await AppDataSource.getRepository(Task).find({ where: { StatusId: statusId } })
  ).sort((a, b) => a.SortOrder - b.SortOrder);
  const parsed = TaskPublicResponseSchema.array().safeParse(tasks);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * Retrieves all property types from the database and sends them as a response.
 *
 * @param req - The request object.
 * @param res - The response object.
 * @returns A response with all property types and status code 200.
 */
export const lookupPropertyTypes = async (req: Request, res: Response) => {
  const types = await AppDataSource.getRepository(PropertyType).find();
  return res.status(200).send(types);
};

/**
 * Retrieves all note types from the database. Optionally filter by status.
 * @param req - Request object.
 * @param res - Response object.
 * @returns A response with note types and status code 200.
 */
export const lookupNoteTypes = async (req: Request, res: Response) => {
  const statusId = req.query.statusId ? parseInt(req.query.statusId.toString()) : undefined;
  const types = (
    await AppDataSource.getRepository(NoteType).find({ where: { StatusId: statusId } })
  ).sort((a, b) => a.SortOrder - b.SortOrder);
  const parsed = ProjectMetadataTypeSchema.array().safeParse(types);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * Retrieves all monetary types from the database. Optionally filter by status.
 * @param req - Request object.
 * @param res - Response object.
 * @returns A response with monetary types and status code 200.
 */
export const lookupMonetaryTypes = async (req: Request, res: Response) => {
  const statusId = req.query.statusId ? parseInt(req.query.statusId.toString()) : undefined;
  const types = (
    await AppDataSource.getRepository(MonetaryType).find({ where: { StatusId: statusId } })
  ).sort((a, b) => a.SortOrder - b.SortOrder);
  const parsed = ProjectMetadataTypeSchema.array().safeParse(types);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * Retrieves all timestamp types from the database. Optionally filter by status.
 * @param req - Request object.
 * @param res - Response object.
 * @returns A response with timestamp types and status code 200.
 */
export const lookupTimestampTypes = async (req: Request, res: Response) => {
  const statusId = req.query.statusId ? parseInt(req.query.statusId.toString()) : undefined;
  const types = (
    await AppDataSource.getRepository(TimestampType).find({ where: { StatusId: statusId } })
  ).sort((a, b) => a.SortOrder - b.SortOrder);
  const parsed = ProjectMetadataTypeSchema.array().safeParse(types);
  if (parsed.success) {
    return res.status(200).send(parsed.data);
  } else {
    return res.status(400).send(parsed);
  }
};

/**
 * @description Get all entries for frontend lookup context.
 * @param {Request}     req Incoming request
 * @param {Response}    res Outgoing response
 * @returns {Response}      A 200 status and a list entries.
 */
export const lookupAll = async (req: Request, res: Response) => {
  const cfg = getConfig();
  const Risks = await AppDataSource.getRepository(ProjectRisk).find({
    select: {
      Id: true,
      Name: true,
      Code: true,
      Description: true,
    },
    order: {
      SortOrder: 'asc',
    },
    where: { IsDisabled: false },
  });
  const TimestampTypes = await AppDataSource.getRepository(TimestampType).find({
    select: {
      Id: true,
      Name: true,
      IsOptional: true,
      Description: true,
      StatusId: true,
    },
    order: {
      SortOrder: 'asc',
    },
    where: { IsDisabled: false },
  });
  const MonetaryTypes = await AppDataSource.getRepository(MonetaryType).find({
    select: {
      Id: true,
      Name: true,
      IsOptional: true,
      Description: true,
      StatusId: true,
    },
    order: {
      SortOrder: 'asc',
    },
    where: { IsDisabled: false },
  });
  const NoteTypes = await AppDataSource.getRepository(NoteType).find({
    select: {
      Id: true,
      Name: true,
      IsOptional: true,
      Description: true,
      StatusId: true,
    },
    order: {
      SortOrder: 'asc',
    },
    where: { IsDisabled: false },
  });
  const PropertyTypes = await AppDataSource.getRepository(PropertyType).find({
    select: {
      Id: true,
      Name: true,
    },
    where: {
      IsDisabled: false,
    },
  });
  const Tasks = await AppDataSource.getRepository(Task).find({
    select: {
      Id: true,
      Name: true,
      IsOptional: true,
      Description: true,
      StatusId: true,
    },
    order: {
      SortOrder: 'asc',
    },
    where: {
      IsDisabled: false,
    },
  });
  const ProjectStatuses = await AppDataSource.getRepository(ProjectStatus).find({
    select: { Name: true, Id: true, Description: true },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const ProjectTiers = await AppDataSource.getRepository(TierLevel).find({
    select: {
      Name: true,
      Id: true,
      Description: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const RegionalDistricts = await AppDataSource.getRepository(RegionalDistrict).find({
    select: {
      Id: true,
      Name: true,
    },
  });
  const ConstructionTypes = await AppDataSource.getRepository(BuildingConstructionType).find({
    select: {
      Name: true,
      Id: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const PredominateUses = await AppDataSource.getRepository(BuildingPredominateUse).find({
    select: {
      Id: true,
      Name: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const Classifications = await AppDataSource.getRepository(PropertyClassification).find({
    select: { Id: true, Name: true, IsVisible: true },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const Roles = await AppDataSource.getRepository(Role).find({
    select: {
      Id: true,
      Name: true,
      Description: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const Agencies = await AppDataSource.getRepository(Agency).find({
    select: {
      Id: true,
      Name: true,
      Code: true,
      ParentId: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });
  const AdministrativeAreas = await AppDataSource.getRepository(AdministrativeArea).find({
    select: {
      Id: true,
      Name: true,
      RegionalDistrictId: true,
    },
    order: { SortOrder: 'asc', Name: 'asc' },
    where: { IsDisabled: false },
  });

  const returnObj = {
    Risks,
    TimestampTypes,
    MonetaryTypes,
    NoteTypes,
    PropertyTypes,
    Tasks,
    ProjectStatuses,
    ProjectTiers,
    ConstructionTypes,
    PredominateUses,
    Classifications,
    Roles,
    Agencies: (await Agencies).sort((a, b) =>
      a.Name.toLowerCase().localeCompare(b.Name.toLowerCase(), undefined, { numeric: true }),
    ),
    AdministrativeAreas,
    RegionalDistricts: (await RegionalDistricts).sort((a, b) =>
      a.Name.toLowerCase().localeCompare(b.Name.toLowerCase()),
    ),
    Config: {
      contactEmail: cfg.contact.toEmail,
      bcscIdentifier: cfg.keycloak.client_id,
    },
  };
  return res.status(200).send(returnObj);
};