diff --git a/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.createInstitution.e2e-spec.ts b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.createInstitution.e2e-spec.ts index d08a00a131..7de9b8aee1 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.createInstitution.e2e-spec.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.createInstitution.e2e-spec.ts @@ -7,7 +7,16 @@ import { getAESTToken, } from "../../../../testHelpers"; import { E2EDataSources, createE2EDataSources } from "@sims/test-utils"; -import { InstitutionType } from "@sims/sims-db"; +import { + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionOrganizationStatus, +} from "@sims/sims-db"; +import { + CANADA_COUNTRY_CODE, + BC_PROVINCE_CODE, + INSTITUTION_TYPE_BC_PUBLIC, +} from "@sims/sims-db/constant"; describe("InstitutionAESTController(e2e)-createInstitution", () => { let app: INestApplication; @@ -24,12 +33,16 @@ describe("InstitutionAESTController(e2e)-createInstitution", () => { const payload = { legalOperatingName: "Create Institution legal operating name", operatingName: "Create Institution operating name", - institutionType: 1, regulatingBody: "icbc", establishedDate: "2023-06-01", primaryEmail: "test@test.ca", primaryPhone: "7785367878", website: "https://www.test.ca", + country: CANADA_COUNTRY_CODE, + province: BC_PROVINCE_CODE, + classification: InstitutionClassification.Public, + organizationStatus: InstitutionOrganizationStatus.Profit, + medicalSchoolStatus: InstitutionMedicalSchoolStatus.No, primaryContactFirstName: "Primary", primaryContactLastName: "Contact", primaryContactEmail: "test@test.ca", @@ -91,43 +104,52 @@ describe("InstitutionAESTController(e2e)-createInstitution", () => { primaryPhone: true, regulatingBody: true, website: true, + country: true, + province: true, + classification: true, + organizationStatus: true, + medicalSchoolStatus: true, }, where: { id: institutionId }, relations: { institutionType: true }, }); - expect(savedInstitution).toEqual( - expect.objectContaining({ - businessGuid: null, - establishedDate: payload.establishedDate, - institutionAddress: { - mailingAddress: { - addressLine1: payload.mailingAddress.addressLine1, - addressLine2: payload.mailingAddress.addressLine2, - city: payload.mailingAddress.city, - country: payload.mailingAddress.country, - postalCode: payload.mailingAddress.postalCode, - provinceState: payload.mailingAddress.provinceState, - selectedCountry: payload.mailingAddress.selectedCountry, - }, + expect(savedInstitution).toEqual({ + id: institutionId, + businessGuid: null, + establishedDate: payload.establishedDate, + institutionAddress: { + mailingAddress: { + addressLine1: payload.mailingAddress.addressLine1, + addressLine2: payload.mailingAddress.addressLine2, + city: payload.mailingAddress.city, + country: payload.mailingAddress.country, + postalCode: payload.mailingAddress.postalCode, + provinceState: payload.mailingAddress.provinceState, + selectedCountry: payload.mailingAddress.selectedCountry, }, - institutionPrimaryContact: { - email: payload.primaryContactEmail, - firstName: payload.primaryContactFirstName, - lastName: payload.primaryContactLastName, - phone: payload.primaryContactPhone, - }, - institutionType: expect.objectContaining({ - id: payload.institutionType, - } as InstitutionType), - legalOperatingName: payload.legalOperatingName, - operatingName: payload.operatingName, - otherRegulatingBody: null, - primaryEmail: payload.primaryEmail, - primaryPhone: payload.primaryPhone, - regulatingBody: payload.regulatingBody, - website: payload.website, - }), - ); + }, + institutionPrimaryContact: { + email: payload.primaryContactEmail, + firstName: payload.primaryContactFirstName, + lastName: payload.primaryContactLastName, + phone: payload.primaryContactPhone, + }, + institutionType: { + id: INSTITUTION_TYPE_BC_PUBLIC, + }, + legalOperatingName: payload.legalOperatingName, + operatingName: payload.operatingName, + otherRegulatingBody: null, + primaryEmail: payload.primaryEmail, + primaryPhone: payload.primaryPhone, + regulatingBody: payload.regulatingBody, + website: payload.website, + country: payload.country, + province: payload.province, + classification: payload.classification, + organizationStatus: payload.organizationStatus, + medicalSchoolStatus: payload.medicalSchoolStatus, + }); }); afterAll(async () => { diff --git a/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.getInstitutionDetailById.e2e-spec.ts b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.getInstitutionDetailById.e2e-spec.ts index c5f6daec2a..857bb0229e 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.getInstitutionDetailById.e2e-spec.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.aest.controller.getInstitutionDetailById.e2e-spec.ts @@ -13,6 +13,16 @@ import { } from "@sims/test-utils"; import { InstitutionDetailAPIOutDTO } from "../../models/institution.dto"; import { getISODateOnlyString } from "@sims/utilities"; +import { + BC_PROVINCE_CODE, + CANADA_COUNTRY_CODE, + INSTITUTION_TYPE_BC_PRIVATE, +} from "@sims/sims-db/constant"; +import { + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionOrganizationStatus, +} from "@sims/sims-db"; describe("InstitutionAESTController(e2e)-getInstitutionDetailById", () => { let app: INestApplication; @@ -26,12 +36,25 @@ describe("InstitutionAESTController(e2e)-getInstitutionDetailById", () => { it("Should return institution details when an institution with given institution id exist.", async () => { // Arrange - const institution = await db.institution.save(createFakeInstitution()); - const mailingAddress = institution.institutionAddress.mailingAddress; const institutionType = await db.institutionType.findOne({ select: { id: true, name: true }, - where: { id: institution.institutionType.id }, + where: { id: INSTITUTION_TYPE_BC_PRIVATE }, }); + const institution = await db.institution.save( + createFakeInstitution( + { institutionType }, + { + initialValues: { + country: CANADA_COUNTRY_CODE, + province: BC_PROVINCE_CODE, + classification: InstitutionClassification.Private, + organizationStatus: InstitutionOrganizationStatus.Profit, + medicalSchoolStatus: InstitutionMedicalSchoolStatus.No, + }, + }, + ), + ); + const mailingAddress = institution.institutionAddress.mailingAddress; const expectedInstitutionDetails: InstitutionDetailAPIOutDTO = { legalOperatingName: institution.legalOperatingName, operatingName: institution.operatingName, @@ -41,7 +64,6 @@ describe("InstitutionAESTController(e2e)-getInstitutionDetailById", () => { regulatingBody: institution.regulatingBody, otherRegulatingBody: institution.otherRegulatingBody ?? null, institutionType: institutionType.id, - institutionTypeName: institutionType.name, establishedDate: getISODateOnlyString(institution.establishedDate), primaryContactEmail: institution.institutionPrimaryContact.email, primaryContactFirstName: institution.institutionPrimaryContact.firstName, @@ -60,6 +82,11 @@ describe("InstitutionAESTController(e2e)-getInstitutionDetailById", () => { isBCPrivate: true, isBCPublic: false, hasBusinessGuid: true, + country: CANADA_COUNTRY_CODE, + province: BC_PROVINCE_CODE, + classification: InstitutionClassification.Private, + organizationStatus: InstitutionOrganizationStatus.Profit, + medicalSchoolStatus: InstitutionMedicalSchoolStatus.No, }; const endpoint = `/aest/institution/${institution.id}`; const token = await getAESTToken(AESTGroups.Operations); diff --git a/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.institutions.controller.getInstitutionDetail.e2e-spec.ts b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.institutions.controller.getInstitutionDetail.e2e-spec.ts new file mode 100644 index 0000000000..9e9aeec312 --- /dev/null +++ b/sources/packages/backend/apps/api/src/route-controllers/institution/_tests_/e2e/institution.institutions.controller.getInstitutionDetail.e2e-spec.ts @@ -0,0 +1,124 @@ +import { HttpStatus, INestApplication } from "@nestjs/common"; +import * as request from "supertest"; +import { + BEARER_AUTH_TYPE, + createTestingAppModule, + getInstitutionToken, + InstitutionTokenTypes, + mockInstitutionUserAuthorization, +} from "../../../../testHelpers"; +import { + E2EDataSources, + createE2EDataSources, + createFakeInstitution, +} from "@sims/test-utils"; +import { + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionOrganizationStatus, + InstitutionUserTypes, +} from "@sims/sims-db"; +import { + CANADA_COUNTRY_CODE, + BC_PROVINCE_CODE, + INSTITUTION_TYPE_BC_PUBLIC, +} from "@sims/sims-db/constant"; +import { getISODateOnlyString } from "@sims/utilities"; +import { InstitutionUserAuthorizations } from "../../../../services"; +import { TestingModule } from "@nestjs/testing"; + +describe("InstitutionInstitutionsController(e2e)-getInstitutionDetail", () => { + let app: INestApplication; + let db: E2EDataSources; + let appModule: TestingModule; + const endpoint = "/institutions/institution"; + + beforeAll(async () => { + const { nestApplication, module, dataSource } = + await createTestingAppModule(); + app = nestApplication; + appModule = module; + db = createE2EDataSources(dataSource); + }); + + it("Should return details of the institution associated to the institution user from the user token when the institution is already set up.", async () => { + // Arrange + const institutionType = await db.institutionType.findOne({ + select: { id: true, name: true }, + where: { id: INSTITUTION_TYPE_BC_PUBLIC }, + }); + const institution = await db.institution.save( + createFakeInstitution( + { institutionType }, + { + initialValues: { + country: CANADA_COUNTRY_CODE, + province: BC_PROVINCE_CODE, + classification: InstitutionClassification.Public, + organizationStatus: InstitutionOrganizationStatus.NotForProfit, + medicalSchoolStatus: InstitutionMedicalSchoolStatus.No, + }, + }, + ), + ); + const mailingAddress = institution.institutionAddress.mailingAddress; + const expectedInstitutionDetails = { + legalOperatingName: institution.legalOperatingName, + operatingName: institution.operatingName, + primaryPhone: institution.primaryPhone, + primaryEmail: institution.primaryEmail, + website: institution.website, + regulatingBody: institution.regulatingBody, + otherRegulatingBody: institution.otherRegulatingBody ?? null, + institutionType: institutionType.id, + establishedDate: getISODateOnlyString(institution.establishedDate), + primaryContactEmail: institution.institutionPrimaryContact.email, + primaryContactFirstName: institution.institutionPrimaryContact.firstName, + primaryContactLastName: institution.institutionPrimaryContact.lastName, + primaryContactPhone: institution.institutionPrimaryContact.phone, + mailingAddress: { + addressLine1: mailingAddress.addressLine1, + addressLine2: mailingAddress.addressLine2, + provinceState: mailingAddress.provinceState, + country: mailingAddress.country, + city: mailingAddress.city, + postalCode: mailingAddress.postalCode, + canadaPostalCode: mailingAddress.postalCode, + selectedCountry: mailingAddress.selectedCountry, + }, + isBCPrivate: false, + isBCPublic: true, + hasBusinessGuid: true, + country: CANADA_COUNTRY_CODE, + province: BC_PROVINCE_CODE, + classification: InstitutionClassification.Public, + organizationStatus: InstitutionOrganizationStatus.NotForProfit, + medicalSchoolStatus: InstitutionMedicalSchoolStatus.No, + }; + // Mock institution user authorization so that the user token will return the fake institution id and mocked roles. + await mockInstitutionUserAuthorization( + appModule, + new InstitutionUserAuthorizations(institution.id, [ + { + locationId: null, + userRole: null, + userType: InstitutionUserTypes.admin, + }, + ]), + ); + const institutionUserToken = await getInstitutionToken( + InstitutionTokenTypes.CollegeFUser, + ); + + // Act/Assert + await request(app.getHttpServer()) + .get(endpoint) + .auth(institutionUserToken, BEARER_AUTH_TYPE) + .expect(HttpStatus.OK) + .expect(expectedInstitutionDetails); + }); + + afterAll(async () => { + await app?.close(); + }); +}); diff --git a/sources/packages/backend/apps/api/src/route-controllers/institution/institution.controller.service.ts b/sources/packages/backend/apps/api/src/route-controllers/institution/institution.controller.service.ts index 448b7b747a..dd82f429b3 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/institution/institution.controller.service.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/institution/institution.controller.service.ts @@ -50,7 +50,6 @@ export class InstitutionControllerService { regulatingBody: institutionDetail.regulatingBody, otherRegulatingBody: institutionDetail.otherRegulatingBody, institutionType: institutionDetail.institutionType.id, - institutionTypeName: institutionDetail.institutionType.name, establishedDate: institutionDetail.establishedDate, primaryContactEmail: institutionDetail.institutionPrimaryContact.email, primaryContactFirstName: @@ -70,6 +69,13 @@ export class InstitutionControllerService { isBCPrivate, isBCPublic, hasBusinessGuid: !!institutionDetail.businessGuid, + // Fallback to undefined is to avoid returning null which is causing issues at the consumer side + // and eventually all these fields should become mandatory. + country: institutionDetail.country ?? undefined, + province: institutionDetail.province ?? undefined, + classification: institutionDetail.classification ?? undefined, + organizationStatus: institutionDetail.organizationStatus ?? undefined, + medicalSchoolStatus: institutionDetail.medicalSchoolStatus ?? undefined, }; } diff --git a/sources/packages/backend/apps/api/src/route-controllers/institution/models/institution.dto.ts b/sources/packages/backend/apps/api/src/route-controllers/institution/models/institution.dto.ts index 6c0b691dd7..f9392efbce 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/institution/models/institution.dto.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/institution/models/institution.dto.ts @@ -1,8 +1,9 @@ import { IsDateString, + IsEnum, IsNotEmpty, IsOptional, - IsPositive, + Length, MaxLength, ValidateIf, ValidateNested, @@ -18,8 +19,13 @@ import { import { OPERATING_NAME_MAX_LENGTH, LEGAL_OPERATING_NAME_MAX_LENGTH, + InstitutionClassification, + InstitutionOrganizationStatus, + InstitutionMedicalSchoolStatus, } from "@sims/sims-db"; import { OTHER_REGULATING_BODY_MAX_LENGTH } from "../../../constants"; +import { CANADA_COUNTRY_CODE } from "@sims/sims-db/constant"; +import { AllowIf } from "../../../utilities/class-validation"; /** * DTO for institution creation by the institution user during the on board process @@ -44,8 +50,26 @@ export class CreateInstitutionAPIInDTO { otherRegulatingBody: string; @IsDateString() establishedDate: string; - @IsPositive() - institutionType: number; + @IsNotEmpty() + @Length(2, 2) + country: string; + @ValidateIf( + (input: InstitutionProfileAPIInDTO) => + input.country === CANADA_COUNTRY_CODE || !!input.province, + ) + @AllowIf( + (input: InstitutionProfileAPIInDTO) => + input.country === CANADA_COUNTRY_CODE, + ) + @IsNotEmpty() + @Length(2, 2) + province?: string; + @IsEnum(InstitutionClassification) + classification: InstitutionClassification; + @IsEnum(InstitutionOrganizationStatus) + organizationStatus: InstitutionOrganizationStatus; + @IsEnum(InstitutionMedicalSchoolStatus) + medicalSchoolStatus: InstitutionMedicalSchoolStatus; //Institutions Primary Contact Information @IsNotEmpty() primaryContactFirstName: string; @@ -107,17 +131,42 @@ export class InstitutionProfileAPIInDTO extends InstitutionContactAPIInDTO { website: string; @IsNotEmpty() regulatingBody: string; - @ValidateIf((e) => e.regulatingBody === "other") + @ValidateIf( + (input: InstitutionProfileAPIInDTO) => input.regulatingBody === "other", + ) @IsNotEmpty() @MaxLength(OTHER_REGULATING_BODY_MAX_LENGTH) otherRegulatingBody: string; @IsDateString() establishedDate: string; - @IsPositive() - institutionType: number; + @IsNotEmpty() + @Length(2, 2) + country: string; + @ValidateIf( + (input: InstitutionProfileAPIInDTO) => + input.country === CANADA_COUNTRY_CODE || !!input.province, + ) + @AllowIf( + (input: InstitutionProfileAPIInDTO) => + input.country === CANADA_COUNTRY_CODE, + ) + @IsNotEmpty() + @Length(2, 2) + province?: string; + @IsEnum(InstitutionClassification) + classification: InstitutionClassification; + @IsEnum(InstitutionOrganizationStatus) + organizationStatus: InstitutionOrganizationStatus; + @IsEnum(InstitutionMedicalSchoolStatus) + medicalSchoolStatus: InstitutionMedicalSchoolStatus; } -export class InstitutionProfileAPIOutDTO extends InstitutionContactAPIOutDTO { +export class InstitutionDetailAPIOutDTO { + primaryContactEmail: string; + primaryContactFirstName: string; + primaryContactLastName: string; + primaryContactPhone: string; + mailingAddress: AddressDetailsAPIOutDTO; operatingName: string; primaryPhone: string; primaryEmail: string; @@ -126,11 +175,7 @@ export class InstitutionProfileAPIOutDTO extends InstitutionContactAPIOutDTO { otherRegulatingBody?: string; establishedDate: string; institutionType: number; -} - -export class InstitutionDetailAPIOutDTO extends InstitutionProfileAPIOutDTO { legalOperatingName: string; - institutionTypeName?: string; isBCPrivate: boolean; isBCPublic: boolean; /** @@ -138,6 +183,11 @@ export class InstitutionDetailAPIOutDTO extends InstitutionProfileAPIOutDTO { * associated with, if not it is a basic BCeID institution. */ hasBusinessGuid: boolean; + country?: string; + province?: string; + classification?: InstitutionClassification; + organizationStatus?: InstitutionOrganizationStatus; + medicalSchoolStatus?: InstitutionMedicalSchoolStatus; } export class InstitutionBasicAPIOutDTO { diff --git a/sources/packages/backend/apps/api/src/route-controllers/system-lookup-configuration/system-lookup-configuration.controller.ts b/sources/packages/backend/apps/api/src/route-controllers/system-lookup-configuration/system-lookup-configuration.controller.ts index 9bda6ca1fc..43fc164102 100644 --- a/sources/packages/backend/apps/api/src/route-controllers/system-lookup-configuration/system-lookup-configuration.controller.ts +++ b/sources/packages/backend/apps/api/src/route-controllers/system-lookup-configuration/system-lookup-configuration.controller.ts @@ -1,6 +1,9 @@ import { Controller, Get, Param, ParseEnumPipe } from "@nestjs/common"; import BaseController from "../BaseController"; -import { AllowAuthorizedParty } from "../../auth/decorators/authorized-party.decorator"; +import { + AllowAuthorizedParty, + RequiresUserAccount, +} from "../../auth/decorators"; import { AuthorizedParties } from "../../auth/authorized-parties.enum"; import { ApiTags } from "@nestjs/swagger"; import { SystemLookupCategory } from "@sims/sims-db"; @@ -16,6 +19,7 @@ import { SystemLookupEntriesAPIOutDTO } from ".."; AuthorizedParties.supportingUsers, AuthorizedParties.aest, ) +@RequiresUserAccount(false) @Controller("system-lookup-configuration") @ApiTags("system-lookup-configuration") export class SystemLookupConfigurationController extends BaseController { diff --git a/sources/packages/backend/apps/api/src/services/institution/institution.service.model.ts b/sources/packages/backend/apps/api/src/services/institution/institution.service.model.ts index 8f878120c6..4ef0df137b 100644 --- a/sources/packages/backend/apps/api/src/services/institution/institution.service.model.ts +++ b/sources/packages/backend/apps/api/src/services/institution/institution.service.model.ts @@ -1,4 +1,9 @@ -import { AddressInfo } from "@sims/sims-db"; +import { + AddressInfo, + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionOrganizationStatus, +} from "@sims/sims-db"; export interface UpdateInstitution { operatingName?: string; @@ -8,12 +13,16 @@ export interface UpdateInstitution { regulatingBody?: string; otherRegulatingBody?: string; establishedDate?: string; - institutionType?: number; primaryContactEmail: string; primaryContactFirstName: string; primaryContactLastName: string; primaryContactPhone: string; mailingAddress: AddressInfo; + country?: string; + province?: string; + classification?: InstitutionClassification; + organizationStatus?: InstitutionOrganizationStatus; + medicalSchoolStatus?: InstitutionMedicalSchoolStatus; } export interface InstitutionFormModel { @@ -37,11 +46,15 @@ export interface InstitutionFormModel { regulatingBody: string; otherRegulatingBody?: string; establishedDate: string; + country: string; + province?: string; + classification: InstitutionClassification; + organizationStatus: InstitutionOrganizationStatus; + medicalSchoolStatus: InstitutionMedicalSchoolStatus; primaryContactFirstName: string; primaryContactLastName: string; primaryContactEmail: string; primaryContactPhone: string; - institutionType: number; mailingAddress: AddressInfo; } diff --git a/sources/packages/backend/apps/api/src/services/institution/institution.service.ts b/sources/packages/backend/apps/api/src/services/institution/institution.service.ts index 3cb4ebed32..240e9f7c57 100644 --- a/sources/packages/backend/apps/api/src/services/institution/institution.service.ts +++ b/sources/packages/backend/apps/api/src/services/institution/institution.service.ts @@ -7,13 +7,15 @@ import { InstitutionUserTypeAndRole, User, InstitutionLocation, - InstitutionType, Note, NoteType, IdentityProviders, getUserFullNameLikeSearch, Application, ApplicationStatus, + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionType, } from "@sims/sims-db"; import { DataSource, EntityManager, IsNull, Not, Repository } from "typeorm"; import { InstitutionUserType, UserInfo } from "../../types"; @@ -43,7 +45,21 @@ import { import { InstitutionUserAuthService } from "../institution-user-auth/institution-user-auth.service"; import { UserService } from "../user/user.service"; import { NoteSharedService } from "@sims/services"; +import { + BC_PROVINCE_CODE, + CANADA_COUNTRY_CODE, + UNITED_STATES_COUNTRY_CODE, +} from "@sims/sims-db/constant"; +enum InstitutionTypes { + BCPublic = 1, + BCPrivate = 2, + OutOfProvincePublic = 3, + UnitedStates = 4, + International = 5, + InternationalMedical = 6, + OutOfProvincePrivate = 7, +} @Injectable() export class InstitutionService extends RecordDataModelService { institutionUserRepo: Repository; @@ -266,9 +282,13 @@ export class InstitutionService extends RecordDataModelService { institution.otherRegulatingBody = institutionModel.otherRegulatingBody; institution.establishedDate = institutionModel.establishedDate; institution.institutionType = { - id: institutionModel.institutionType, + id: this.getInstitutionTypeId(institutionModel), } as InstitutionType; - + institution.country = institutionModel.country; + institution.province = institutionModel.province ?? null; + institution.classification = institutionModel.classification; + institution.organizationStatus = institutionModel.organizationStatus; + institution.medicalSchoolStatus = institutionModel.medicalSchoolStatus; // Institution Primary Contact Information. institution.institutionPrimaryContact = { firstName: institutionModel.primaryContactFirstName, @@ -851,8 +871,13 @@ export class InstitutionService extends RecordDataModelService { institution.otherRegulatingBody = updateInstitution.otherRegulatingBody; institution.establishedDate = updateInstitution.establishedDate; institution.institutionType = { - id: updateInstitution.institutionType, + id: this.getInstitutionTypeId(updateInstitution), } as InstitutionType; + institution.country = updateInstitution.country; + institution.province = updateInstitution.province ?? null; + institution.classification = updateInstitution.classification; + institution.organizationStatus = updateInstitution.organizationStatus; + institution.medicalSchoolStatus = updateInstitution.medicalSchoolStatus; } institution.institutionPrimaryContact = { firstName: updateInstitution.primaryContactFirstName, @@ -986,4 +1011,43 @@ export class InstitutionService extends RecordDataModelService { where: { locations: { id: locationId }, programs: { id: programId } }, }); } + + /** + * Get institution type id based on institution details. + * @returns institution type. + */ + private getInstitutionTypeId( + institution: Pick< + Institution, + | "country" + | "province" + | "classification" + | "organizationStatus" + | "medicalSchoolStatus" + >, + ): number { + // When country is Canada. + if (institution.country === CANADA_COUNTRY_CODE) { + const isPublic = + institution.classification === InstitutionClassification.Public; + const canadaMap = { + [BC_PROVINCE_CODE]: isPublic + ? InstitutionTypes.BCPublic + : InstitutionTypes.BCPrivate, + default: isPublic + ? InstitutionTypes.OutOfProvincePublic + : InstitutionTypes.OutOfProvincePrivate, + }; + return canadaMap[institution.province] || canadaMap.default; + } + // When country is United States. + if (institution.country === UNITED_STATES_COUNTRY_CODE) { + return InstitutionTypes.UnitedStates; + } + // Other international institutions. + return institution.medicalSchoolStatus === + InstitutionMedicalSchoolStatus.Yes + ? InstitutionTypes.InternationalMedical + : InstitutionTypes.International; + } } diff --git a/sources/packages/backend/apps/api/src/testHelpers/auth/institution-user-helpers.ts b/sources/packages/backend/apps/api/src/testHelpers/auth/institution-user-helpers.ts index 609414246b..6f3294a8a8 100644 --- a/sources/packages/backend/apps/api/src/testHelpers/auth/institution-user-helpers.ts +++ b/sources/packages/backend/apps/api/src/testHelpers/auth/institution-user-helpers.ts @@ -22,7 +22,7 @@ export async function mockInstitutionUserAuthorization( ); jest .spyOn(institutionUserAuthService, "getAuthorizationsByUserName") - .mockImplementation(() => { + .mockImplementationOnce(() => { return Promise.resolve(institutionUserAuthorizations); }); } diff --git a/sources/packages/backend/apps/db-migrations/src/sql/Institution/Add-additional-information-cols.sql b/sources/packages/backend/apps/db-migrations/src/sql/Institution/Add-additional-information-cols.sql index dcd17b7431..19b2e1be3b 100644 --- a/sources/packages/backend/apps/db-migrations/src/sql/Institution/Add-additional-information-cols.sql +++ b/sources/packages/backend/apps/db-migrations/src/sql/Institution/Add-additional-information-cols.sql @@ -66,17 +66,17 @@ SET ELSE NULL END, classification = CASE - -- Update for Canadian public institution types(BC Public, Out of Province Public) to Public. - -- Update for Canadian private institution types(BC Private, Out of Province Private) to Private. - WHEN institution_type_id IN (1, 3) THEN 'Public' - WHEN institution_type_id IN (2, 7) THEN 'Private' + -- Update for Canadian public institution types(BC Public, Out of Province Public) to public. + -- Update for Canadian private institution types(BC Private, Out of Province Private) to private. + WHEN institution_type_id IN (1, 3) THEN 'public' + WHEN institution_type_id IN (2, 7) THEN 'private' ELSE NULL END, medical_school_status = CASE - -- Update for International Medical institution type to Yes. - -- Update for International institution type to No. - WHEN institution_type_id = 6 THEN 'Yes' - WHEN institution_type_id = 5 THEN 'No' + -- Update for International Medical institution type to yes. + -- Update for International institution type to no. + WHEN institution_type_id = 6 THEN 'yes' + WHEN institution_type_id = 5 THEN 'no' ELSE NULL END, updated_at = NOW(), diff --git a/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Create-system-lookup-configurations-table.sql b/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Create-system-lookup-configurations-table.sql index 6e7a087e16..77a8d18517 100644 --- a/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Create-system-lookup-configurations-table.sql +++ b/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Create-system-lookup-configurations-table.sql @@ -3,6 +3,7 @@ CREATE TABLE sims.system_lookup_configurations( lookup_category VARCHAR(100) NOT NULL, lookup_key VARCHAR(100) NOT NULL, lookup_value VARCHAR(500) NOT NULL, + lookup_priority SMALLINT NOT NULL, -- Audit columns. created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), @@ -22,6 +23,8 @@ COMMENT ON COLUMN sims.system_lookup_configurations.lookup_key IS 'Lookup key of COMMENT ON COLUMN sims.system_lookup_configurations.lookup_value IS 'Lookup value of a lookup data.'; +COMMENT ON COLUMN sims.system_lookup_configurations.lookup_priority IS 'Lookup priority to order the lookup data.'; + COMMENT ON COLUMN sims.system_lookup_configurations.created_at IS 'Record creation timestamp.'; COMMENT ON COLUMN sims.system_lookup_configurations.updated_at IS 'Record update timestamp.'; diff --git a/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Insert-country-and-province-system-lookup.sql b/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Insert-country-and-province-system-lookup.sql index e0c42b7655..e32ac6e490 100644 --- a/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Insert-country-and-province-system-lookup.sql +++ b/sources/packages/backend/apps/db-migrations/src/sql/SystemLookupConfigurations/Insert-country-and-province-system-lookup.sql @@ -13,12 +13,14 @@ INSERT INTO lookup_category, lookup_value, lookup_key, + lookup_priority, creator ) SELECT lookup_data.lookup_category, lookup_data.lookup_value, lookup_data.lookup_key, + lookup_data.lookup_priority, su.id FROM ( @@ -26,1322 +28,1591 @@ FROM ( 'Country', 'Afghanistan', - 'AF' + 'AF', + 2 ), ( 'Country', 'Albania', - 'AL' + 'AL', + 2 ), ( 'Country', 'Antarctica', - 'AQ' + 'AQ', + 2 ), ( 'Country', 'Algeria', - 'DZ' + 'DZ', + 2 ), ( 'Country', 'American Samoa', - 'AS' + 'AS', + 2 ), ( 'Country', 'Andorra', - 'AD' + 'AD', + 2 ), ( 'Country', 'Angola', - 'AO' + 'AO', + 2 ), ( 'Country', 'Antigua and Barbuda', - 'AG' + 'AG', + 2 ), ( 'Country', 'Azerbaijan', - 'AZ' + 'AZ', + 2 ), ( 'Country', 'Argentina', - 'AR' + 'AR', + 2 ), ( 'Country', 'Australia', - 'AU' + 'AU', + 2 ), ( 'Country', 'Austria', - 'AT' + 'AT', + 2 ), ( 'Country', 'Bahamas', - 'BS' + 'BS', + 2 ), ( 'Country', 'Bahrain', - 'BH' + 'BH', + 2 ), ( 'Country', 'Bangladesh', - 'BD' + 'BD', + 2 ), ( 'Country', 'Armenia', - 'AM' + 'AM', + 2 ), ( 'Country', 'Barbados', - 'BB' + 'BB', + 2 ), ( 'Country', 'Belgium', - 'BE' + 'BE', + 2 ), ( 'Country', 'Bermuda', - 'BM' + 'BM', + 2 ), ( 'Country', 'Bhutan', - 'BT' + 'BT', + 2 ), ( 'Country', 'Bolivia', - 'BO' + 'BO', + 2 ), ( 'Country', 'Bosnia and Herzegovina', - 'BA' + 'BA', + 2 ), ( 'Country', 'Botswana', - 'BW' + 'BW', + 2 ), ( 'Country', 'Bouvet Island', - 'BV' + 'BV', + 2 ), ( 'Country', 'Brazil', - 'BR' + 'BR', + 2 ), ( 'Country', 'Belize', - 'BZ' + 'BZ', + 2 ), ( 'Country', 'British Indian Ocean Territory', - 'IO' + 'IO', + 2 ), ( 'Country', 'Solomon Islands', - 'SB' + 'SB', + 2 ), ( 'Country', 'Virgin Islands, British', - 'VG' + 'VG', + 2 ), ( 'Country', 'Brunei Darussalam', - 'BN' + 'BN', + 2 ), ( 'Country', 'Bulgaria', - 'BG' + 'BG', + 2 ), ( 'Country', 'Myanmar', - 'MM' + 'MM', + 2 ), ( 'Country', 'Burundi', - 'BI' + 'BI', + 2 ), ( 'Country', 'Belarus', - 'BY' + 'BY', + 2 ), ( 'Country', 'Cambodia', - 'KH' + 'KH', + 2 ), ( 'Country', 'Cameroon', - 'CM' + 'CM', + 2 ), ( 'Country', 'Canada', - 'CA' + 'CA', + 1 ), ( 'Country', 'Cabo Verde', - 'CV' + 'CV', + 2 ), ( 'Country', 'Cayman Islands', - 'KY' + 'KY', + 2 ), ( 'Country', 'Central African Republic', - 'CF' + 'CF', + 2 ), ( 'Country', 'Sri Lanka', - 'LK' + 'LK', + 2 ), ( 'Country', 'Chad', - 'TD' + 'TD', + 2 ), ( 'Country', 'Chile', - 'CL' + 'CL', + 2 ), ( 'Country', 'China', - 'CN' + 'CN', + 2 ), ( 'Country', 'Taiwan', - 'TW' + 'TW', + 2 ), ( 'Country', 'Christmas Island', - 'CX' + 'CX', + 2 ), ( 'Country', 'Cocos (Keeling) Islands', - 'CC' + 'CC', + 2 ), ( 'Country', 'Colombia', - 'CO' + 'CO', + 2 ), ( 'Country', 'Comoros', - 'KM' + 'KM', + 2 ), ( 'Country', 'Mayotte', - 'YT' + 'YT', + 2 ), ( 'Country', 'Congo, Republic of the', - 'CG' + 'CG', + 2 ), ( 'Country', 'Congo, Democratic Republic of the', - 'CD' + 'CD', + 2 ), ( 'Country', 'Cook Islands', - 'CK' + 'CK', + 2 ), ( 'Country', 'Costa Rica', - 'CR' + 'CR', + 2 ), ( 'Country', 'Croatia', - 'HR' + 'HR', + 2 ), ( 'Country', 'Cuba', - 'CU' + 'CU', + 2 ), ( 'Country', 'Cyprus', - 'CY' + 'CY', + 2 ), ( 'Country', 'Czechia', - 'CZ' + 'CZ', + 2 ), ( 'Country', 'Benin', - 'BJ' + 'BJ', + 2 ), ( 'Country', 'Denmark', - 'DK' + 'DK', + 2 ), ( 'Country', 'Dominica', - 'DM' + 'DM', + 2 ), ( 'Country', 'Dominican Republic', - 'DO' + 'DO', + 2 ), ( 'Country', 'Ecuador', - 'EC' + 'EC', + 2 ), ( 'Country', 'El Salvador', - 'SV' + 'SV', + 2 ), ( 'Country', 'Equatorial Guinea', - 'GQ' + 'GQ', + 2 ), ( 'Country', 'Ethiopia', - 'ET' + 'ET', + 2 ), ( 'Country', 'Eritrea', - 'ER' + 'ER', + 2 ), ( 'Country', 'Estonia', - 'EE' + 'EE', + 2 ), ( 'Country', 'Faroe Islands', - 'FO' + 'FO', + 2 ), ( 'Country', 'Falkland Islands (Malvinas)', - 'FK' + 'FK', + 2 ), ( 'Country', 'South Georgia and the South Sandwich Islands', - 'GS' + 'GS', + 2 ), ( 'Country', 'Fiji', - 'FJ' + 'FJ', + 2 ), ( 'Country', 'Finland', - 'FI' + 'FI', + 2 ), ( 'Country', 'Åland Islands', - 'AX' + 'AX', + 2 ), ( 'Country', 'France', - 'FR' + 'FR', + 2 ), ( 'Country', 'French Guiana', - 'GF' + 'GF', + 2 ), ( 'Country', 'French Polynesia', - 'PF' + 'PF', + 2 ), ( 'Country', 'French Southern Territories', - 'TF' + 'TF', + 2 ), ( 'Country', 'Djibouti', - 'DJ' + 'DJ', + 2 ), ( 'Country', 'Gabon', - 'GA' + 'GA', + 2 ), ( 'Country', 'Georgia', - 'GE' + 'GE', + 2 ), ( 'Country', 'Gambia', - 'GM' + 'GM', + 2 ), ( 'Country', 'West Bank and Gaza', - 'PS' + 'PS', + 2 ), ( 'Country', 'Germany', - 'DE' + 'DE', + 2 ), ( 'Country', 'Ghana', - 'GH' + 'GH', + 2 ), ( 'Country', 'Gibraltar', - 'GI' + 'GI', + 2 ), ( 'Country', 'Kiribati', - 'KI' + 'KI', + 2 ), ( 'Country', 'Greece', - 'GR' + 'GR', + 2 ), ( 'Country', 'Greenland', - 'GL' + 'GL', + 2 ), ( 'Country', 'Grenada', - 'GD' + 'GD', + 2 ), ( 'Country', 'Guadeloupe', - 'GP' + 'GP', + 2 ), ( 'Country', 'Guam', - 'GU' + 'GU', + 2 ), ( 'Country', 'Guatemala', - 'GT' + 'GT', + 2 ), ( 'Country', 'Guinea', - 'GN' + 'GN', + 2 ), ( 'Country', 'Guyana', - 'GY' + 'GY', + 2 ), ( 'Country', 'Haiti', - 'HT' + 'HT', + 2 ), ( 'Country', 'Heard Island and McDonald Islands', - 'HM' + 'HM', + 2 ), ( 'Country', 'Holy See (Vatican City State)', - 'VA' + 'VA', + 2 ), ( 'Country', 'Honduras', - 'HN' + 'HN', + 2 ), ( 'Country', 'Hong Kong', - 'HK' + 'HK', + 2 ), ( 'Country', 'Hungary', - 'HU' + 'HU', + 2 ), ( 'Country', 'Iceland', - 'IS' + 'IS', + 2 ), ( 'Country', 'India', - 'IN' + 'IN', + 2 ), ( 'Country', 'Indonesia', - 'ID' + 'ID', + 2 ), ( 'Country', 'Iran', - 'IR' + 'IR', + 2 ), ( 'Country', 'Iraq', - 'IQ' + 'IQ', + 2 ), ( 'Country', 'Ireland', - 'IE' + 'IE', + 2 ), ( 'Country', 'Israel', - 'IL' + 'IL', + 2 ), ( 'Country', 'Italy', - 'IT' + 'IT', + 2 ), ( 'Country', 'Côte d’Ivoire', - 'CI' + 'CI', + 2 ), ( 'Country', 'Jamaica', - 'JM' + 'JM', + 2 ), ( 'Country', 'Japan', - 'JP' + 'JP', + 2 ), ( 'Country', 'Kazakhstan', - 'KZ' + 'KZ', + 2 ), ( 'Country', 'Jordan', - 'JO' + 'JO', + 2 ), ( 'Country', 'Kenya', - 'KE' + 'KE', + 2 ), ( 'Country', 'Korea, North', - 'KP' + 'KP', + 2 ), ( 'Country', 'Korea, South', - 'KR' + 'KR', + 2 ), ( 'Country', 'Kuwait', - 'KW' + 'KW', + 2 ), ( 'Country', 'Kyrgyzstan', - 'KG' + 'KG', + 2 ), ( 'Country', 'Laos', - 'LA' + 'LA', + 2 ), ( 'Country', 'Lebanon', - 'LB' + 'LB', + 2 ), ( 'Country', 'Lesotho', - 'LS' + 'LS', + 2 ), ( 'Country', 'Latvia', - 'LV' + 'LV', + 2 ), ( 'Country', 'Liberia', - 'LR' + 'LR', + 2 ), ( 'Country', 'Libya', - 'LY' + 'LY', + 2 ), ( 'Country', 'Liechtenstein', - 'LI' + 'LI', + 2 ), ( 'Country', 'Lithuania', - 'LT' + 'LT', + 2 ), ( 'Country', 'Luxembourg', - 'LU' + 'LU', + 2 ), ( 'Country', 'Macao', - 'MO' + 'MO', + 2 ), ( 'Country', 'Madagascar', - 'MG' + 'MG', + 2 ), ( 'Country', 'Malawi', - 'MW' + 'MW', + 2 ), ( 'Country', 'Malaysia', - 'MY' + 'MY', + 2 ), ( 'Country', 'Maldives', - 'MV' + 'MV', + 2 ), ( 'Country', 'Mali', - 'ML' + 'ML', + 2 ), ( 'Country', 'Malta', - 'MT' + 'MT', + 2 ), ( 'Country', 'Martinique', - 'MQ' + 'MQ', + 2 ), ( 'Country', 'Mauritania', - 'MR' + 'MR', + 2 ), ( 'Country', 'Mauritius', - 'MU' + 'MU', + 2 ), ( 'Country', 'Mexico', - 'MX' + 'MX', + 2 ), ( 'Country', 'Monaco', - 'MC' + 'MC', + 2 ), ( 'Country', 'Mongolia', - 'MN' + 'MN', + 2 ), ( 'Country', 'Moldova', - 'MD' + 'MD', + 2 ), ( 'Country', 'Montenegro', - 'ME' + 'ME', + 2 ), ( 'Country', 'Montserrat', - 'MS' + 'MS', + 2 ), ( 'Country', 'Morocco', - 'MA' + 'MA', + 2 ), ( 'Country', 'Mozambique', - 'MZ' + 'MZ', + 2 ), ( 'Country', 'Oman', - 'OM' + 'OM', + 2 ), ( 'Country', 'Namibia', - 'NA' + 'NA', + 2 ), ( 'Country', 'Nauru', - 'NR' + 'NR', + 2 ), ( 'Country', 'Nepal', - 'NP' + 'NP', + 2 ), ( 'Country', 'Netherlands', - 'NL' + 'NL', + 2 ), ( 'Country', 'Curaçao', - 'CW' + 'CW', + 2 ), ( 'Country', 'Aruba', - 'AW' + 'AW', + 2 ), ( 'Country', 'Sint Maarten (Dutch part)', - 'SX' + 'SX', + 2 ), ( 'Country', 'Bonaire, Sint Eustatius and Saba', - 'BQ' + 'BQ', + 2 ), ( 'Country', 'New Caledonia', - 'NC' + 'NC', + 2 ), ( 'Country', 'Vanuatu', - 'VU' + 'VU', + 2 ), ( 'Country', 'New Zealand', - 'NZ' + 'NZ', + 2 ), ( 'Country', 'Nicaragua', - 'NI' + 'NI', + 2 ), ( 'Country', 'Niger', - 'NE' + 'NE', + 2 ), ( 'Country', 'Nigeria', - 'NG' + 'NG', + 2 ), ( 'Country', 'Niue', - 'NU' + 'NU', + 2 ), ( 'Country', 'Norfolk Island', - 'NF' + 'NF', + 2 ), ( 'Country', 'Norway', - 'NO' + 'NO', + 2 ), ( 'Country', 'Northern Mariana Islands', - 'MP' + 'MP', + 2 ), ( 'Country', 'United States Minor Outlying Islands', - 'UM' + 'UM', + 2 ), ( 'Country', 'Micronesia, Federated States of', - 'FM' + 'FM', + 2 ), ( 'Country', 'Marshall Islands', - 'MH' + 'MH', + 2 ), ( 'Country', 'Palau', - 'PW' + 'PW', + 2 ), ( 'Country', 'Pakistan', - 'PK' + 'PK', + 2 ), ( 'Country', 'Panama', - 'PA' + 'PA', + 2 ), ( 'Country', 'Papua New Guinea', - 'PG' + 'PG', + 2 ), ( 'Country', 'Paraguay', - 'PY' + 'PY', + 2 ), ( 'Country', 'Peru', - 'PE' + 'PE', + 2 ), ( 'Country', 'Philippines', - 'PH' + 'PH', + 2 ), ( 'Country', 'Pitcairn', - 'PN' + 'PN', + 2 ), ( 'Country', 'Poland', - 'PL' + 'PL', + 2 ), ( 'Country', 'Portugal', - 'PT' + 'PT', + 2 ), ( 'Country', 'Guinea-Bissau', - 'GW' + 'GW', + 2 ), ( 'Country', 'Timor-Leste', - 'TL' + 'TL', + 2 ), ( 'Country', 'Puerto Rico', - 'PR' + 'PR', + 2 ), ( 'Country', 'Qatar', - 'QA' + 'QA', + 2 ), ( 'Country', 'Réunion', - 'RE' + 'RE', + 2 ), ( 'Country', 'Romania', - 'RO' + 'RO', + 2 ), ( 'Country', 'Russian Federation', - 'RU' + 'RU', + 2 ), ( 'Country', 'Rwanda', - 'RW' + 'RW', + 2 ), ( 'Country', 'Saint Barthélemy', - 'BL' + 'BL', + 2 ), ( 'Country', 'Saint Helena, Ascension and Tristan da Cunha', - 'SH' + 'SH', + 2 ), ( 'Country', 'Saint Kitts and Nevis', - 'KN' + 'KN', + 2 ), ( 'Country', 'Anguilla', - 'AI' + 'AI', + 2 ), ( 'Country', 'Saint Lucia', - 'LC' + 'LC', + 2 ), ( 'Country', 'Saint Martin (French part)', - 'MF' + 'MF', + 2 ), ( 'Country', 'Saint Pierre and Miquelon', - 'PM' + 'PM', + 2 ), ( 'Country', 'Saint Vincent and the Grenadines', - 'VC' + 'VC', + 2 ), ( 'Country', 'San Marino', - 'SM' + 'SM', + 2 ), ( 'Country', 'Sao Tome and Principe', - 'ST' + 'ST', + 2 ), ( 'Country', 'Sark', - 'XQ' + 'XQ', + 2 ), ( 'Country', 'Saudi Arabia', - 'SA' + 'SA', + 2 ), ( 'Country', 'Senegal', - 'SN' + 'SN', + 2 ), ( 'Country', 'Serbia', - 'RS' + 'RS', + 2 ), ( 'Country', 'Seychelles', - 'SC' + 'SC', + 2 ), ( 'Country', 'Sierra Leone', - 'SL' + 'SL', + 2 ), ( 'Country', 'Singapore', - 'SG' + 'SG', + 2 ), ( 'Country', 'Slovakia', - 'SK' + 'SK', + 2 ), ( 'Country', 'Viet Nam', - 'VN' + 'VN', + 2 ), ( 'Country', 'Slovenia', - 'SI' + 'SI', + 2 ), ( 'Country', 'Somalia', - 'SO' + 'SO', + 2 ), ( 'Country', 'South Africa, Republic of', - 'ZA' + 'ZA', + 2 ), ( 'Country', 'Zimbabwe', - 'ZW' + 'ZW', + 2 ), ( 'Country', 'Spain', - 'ES' + 'ES', + 2 ), ( 'Country', 'South Sudan', - 'SS' + 'SS', + 2 ), ( 'Country', 'Sudan', - 'SD' + 'SD', + 2 ), ( 'Country', 'Western Sahara', - 'EH' + 'EH', + 2 ), ( 'Country', 'Suriname', - 'SR' + 'SR', + 2 ), ( 'Country', 'Svalbard and Jan Mayen', - 'SJ' + 'SJ', + 2 ), ( 'Country', 'Eswatini', - 'SZ' + 'SZ', + 2 ), ( 'Country', 'Sweden', - 'SE' + 'SE', + 2 ), ( 'Country', 'Switzerland', - 'CH' + 'CH', + 2 ), ( 'Country', 'Syria', - 'SY' + 'SY', + 2 ), ( 'Country', 'Tajikistan', - 'TJ' + 'TJ', + 2 ), ( 'Country', 'Thailand', - 'TH' + 'TH', + 2 ), ( 'Country', 'Togo', - 'TG' + 'TG', + 2 ), ( 'Country', 'Tokelau', - 'TK' + 'TK', + 2 ), ( 'Country', 'Tonga', - 'TO' + 'TO', + 2 ), ( 'Country', 'Trinidad and Tobago', - 'TT' + 'TT', + 2 ), ( 'Country', 'United Arab Emirates', - 'AE' + 'AE', + 2 ), ( 'Country', 'Tunisia', - 'TN' + 'TN', + 2 ), ( 'Country', 'Türkiye', - 'TR' + 'TR', + 2 ), ( 'Country', 'Turkmenistan', - 'TM' + 'TM', + 2 ), ( 'Country', 'Turks and Caicos Islands', - 'TC' + 'TC', + 2 ), ( 'Country', 'Tuvalu', - 'TV' + 'TV', + 2 ), ( 'Country', 'Uganda', - 'UG' + 'UG', + 2 ), ( 'Country', 'Ukraine', - 'UA' + 'UA', + 2 ), ( 'Country', 'North Macedonia', - 'MK' + 'MK', + 2 ), ( 'Country', 'Egypt', - 'EG' + 'EG', + 2 ), ( 'Country', 'United Kingdom', - 'GB' + 'GB', + 2 ), ( 'Country', 'Guernsey', - 'GG' + 'GG', + 2 ), ( 'Country', 'Jersey', - 'JE' + 'JE', + 2 ), ( 'Country', 'Isle of Man', - 'IM' + 'IM', + 2 ), ( 'Country', 'Tanzania', - 'TZ' + 'TZ', + 2 ), ( 'Country', 'United States of America', - 'US' + 'US', + 2 ), ( 'Country', 'Virgin Islands, United States', - 'VI' + 'VI', + 2 ), ( 'Country', 'Burkina Faso', - 'BF' + 'BF', + 2 ), ( 'Country', 'Uruguay', - 'UY' + 'UY', + 2 ), ( 'Country', 'Uzbekistan', - 'UZ' + 'UZ', + 2 ), ( 'Country', 'Venezuela', - 'VE' + 'VE', + 2 ), ( 'Country', 'Wallis and Futuna', - 'WF' + 'WF', + 2 ), ( 'Country', 'Samoa', - 'WS' + 'WS', + 2 ), ( 'Country', 'Yemen', - 'YE' + 'YE', + 2 ), ( 'Country', 'Zambia', - 'ZM' + 'ZM', + 2 ), ( 'Country', 'Kosovo', - 'XK' + 'XK', + 2 ), ( 'Province', 'Alberta', - 'AB' + 'AB', + 2 ), ( 'Province', 'British Columbia', - 'BC' + 'BC', + 1 ), ( 'Province', 'Manitoba', - 'MB' + 'MB', + 2 ), ( 'Province', 'New Brunswick', - 'NB' + 'NB', + 2 ), ( 'Province', 'Newfoundland and Labrador', - 'NL' + 'NL', + 2 ), ( 'Province', 'Nova Scotia', - 'NS' + 'NS', + 2 ), ( 'Province', 'Ontario', - 'ON' + 'ON', + 2 ), ( 'Province', 'Prince Edward Island', - 'PE' + 'PE', + 2 ), ( 'Province', 'Quebec', - 'QC' + 'QC', + 2 ), ( 'Province', 'Saskatchewan', - 'SK' + 'SK', + 2 ), ( 'Province', 'Yukon', - 'YT' + 'YT', + 2 ), ( 'Province', 'Nunavut', - 'NU' + 'NU', + 2 ), ( 'Province', 'Northwest Territories', - 'NT' + 'NT', + 2 ) - ) AS lookup_data(lookup_category, lookup_value, lookup_key) + ) AS lookup_data( + lookup_category, + lookup_value, + lookup_key, + lookup_priority + ) CROSS JOIN system_user_data su; \ No newline at end of file diff --git a/sources/packages/backend/libs/services/src/system-lookup-configuration/system-lookup-configuration.service.ts b/sources/packages/backend/libs/services/src/system-lookup-configuration/system-lookup-configuration.service.ts index 5ae0061bff..794cee2778 100644 --- a/sources/packages/backend/libs/services/src/system-lookup-configuration/system-lookup-configuration.service.ts +++ b/sources/packages/backend/libs/services/src/system-lookup-configuration/system-lookup-configuration.service.ts @@ -33,7 +33,8 @@ export class SystemLookupConfigurationService { }, order: { lookupCategory: "ASC", - lookupKey: "ASC", + lookupPriority: "ASC", + lookupValue: "ASC", }, }); this.systemLookupConfigurationsMap = lookupItems.reduce( diff --git a/sources/packages/backend/libs/sims-db/src/constant.ts b/sources/packages/backend/libs/sims-db/src/constant.ts index 7cd324f67b..277ecc7b6a 100644 --- a/sources/packages/backend/libs/sims-db/src/constant.ts +++ b/sources/packages/backend/libs/sims-db/src/constant.ts @@ -87,3 +87,8 @@ export const CANADA_COUNTRY_CODE = "CA"; * BC province code. */ export const BC_PROVINCE_CODE = "BC"; + +/** + * United States country code. + */ +export const UNITED_STATES_COUNTRY_CODE = "US"; diff --git a/sources/packages/backend/libs/sims-db/src/entities/institution-classification.type.ts b/sources/packages/backend/libs/sims-db/src/entities/institution-classification.type.ts index dac475e53b..302ca00450 100644 --- a/sources/packages/backend/libs/sims-db/src/entities/institution-classification.type.ts +++ b/sources/packages/backend/libs/sims-db/src/entities/institution-classification.type.ts @@ -2,6 +2,6 @@ * Institution classification types. */ export enum InstitutionClassification { - Public = "Public", - Private = "Private", + Public = "public", + Private = "private", } diff --git a/sources/packages/backend/libs/sims-db/src/entities/institution-medical-school-status.type.ts b/sources/packages/backend/libs/sims-db/src/entities/institution-medical-school-status.type.ts index 60c295d488..eb8ce369bd 100644 --- a/sources/packages/backend/libs/sims-db/src/entities/institution-medical-school-status.type.ts +++ b/sources/packages/backend/libs/sims-db/src/entities/institution-medical-school-status.type.ts @@ -2,6 +2,6 @@ * Institution medical school status types. */ export enum InstitutionMedicalSchoolStatus { - Yes = "Yes", - No = "No", + Yes = "yes", + No = "no", } diff --git a/sources/packages/backend/libs/sims-db/src/entities/institution-organization-status.type.ts b/sources/packages/backend/libs/sims-db/src/entities/institution-organization-status.type.ts index 4fdf51f4d5..55dd619e32 100644 --- a/sources/packages/backend/libs/sims-db/src/entities/institution-organization-status.type.ts +++ b/sources/packages/backend/libs/sims-db/src/entities/institution-organization-status.type.ts @@ -2,6 +2,6 @@ * Institution organization status types. */ export enum InstitutionOrganizationStatus { - Profit = "Profit", - NotForProfit = "Not for profit", + Profit = "profit", + NotForProfit = "notForProfit", } diff --git a/sources/packages/backend/libs/sims-db/src/entities/system-lookup-configuration.model.ts b/sources/packages/backend/libs/sims-db/src/entities/system-lookup-configuration.model.ts index 8ca10181e7..0a47c7fff3 100644 --- a/sources/packages/backend/libs/sims-db/src/entities/system-lookup-configuration.model.ts +++ b/sources/packages/backend/libs/sims-db/src/entities/system-lookup-configuration.model.ts @@ -36,4 +36,13 @@ export class SystemLookupConfiguration extends RecordDataModel { name: "lookup_value", }) lookupValue: string; + + /** + * Lookup priority to order the lookup data. + */ + @Column({ + name: "lookup_priority", + type: "smallint", + }) + lookupPriority: number; } diff --git a/sources/packages/backend/libs/test-utils/src/factories/institution.ts b/sources/packages/backend/libs/test-utils/src/factories/institution.ts index a43cc21f27..656ec3ac25 100644 --- a/sources/packages/backend/libs/test-utils/src/factories/institution.ts +++ b/sources/packages/backend/libs/test-utils/src/factories/institution.ts @@ -1,16 +1,31 @@ import { faker } from "@faker-js/faker"; -import { Institution, InstitutionType } from "@sims/sims-db"; -import { INSTITUTION_TYPE_BC_PRIVATE } from "@sims/sims-db/constant"; +import { + Institution, + InstitutionClassification, + InstitutionMedicalSchoolStatus, + InstitutionOrganizationStatus, + InstitutionType, +} from "@sims/sims-db"; +import { + BC_PROVINCE_CODE, + CANADA_COUNTRY_CODE, + INSTITUTION_TYPE_BC_PRIVATE, +} from "@sims/sims-db/constant"; /** * Create fake institution. * @param relations institution relations. * - `institutionType` institution type. + * @param options institution options. + * - `initialValues` initial values for the institution creation. * @returns institution. */ -export function createFakeInstitution(relations?: { - institutionType?: InstitutionType; -}): Institution { +export function createFakeInstitution( + relations?: { + institutionType?: InstitutionType; + }, + options?: { initialValues?: Partial }, +): Institution { const institution = new Institution(); institution.businessGuid = faker.string.uuid(); institution.legalOperatingName = faker.company.name(); @@ -42,5 +57,15 @@ export function createFakeInstitution(relations?: { postalCode: faker.location.zipCode("A9A9A9"), }, }; + institution.country = options?.initialValues?.country ?? CANADA_COUNTRY_CODE; + institution.province = options?.initialValues?.province ?? BC_PROVINCE_CODE; + institution.classification = + options?.initialValues?.classification ?? InstitutionClassification.Private; + institution.organizationStatus = + options?.initialValues?.organizationStatus ?? + InstitutionOrganizationStatus.Profit; + institution.medicalSchoolStatus = + options?.initialValues?.medicalSchoolStatus ?? + InstitutionMedicalSchoolStatus.No; return institution; } diff --git a/sources/packages/backend/libs/test-utils/src/factories/system-lookup-configuration.ts b/sources/packages/backend/libs/test-utils/src/factories/system-lookup-configuration.ts index efbedc2317..71740c0a5f 100644 --- a/sources/packages/backend/libs/test-utils/src/factories/system-lookup-configuration.ts +++ b/sources/packages/backend/libs/test-utils/src/factories/system-lookup-configuration.ts @@ -28,6 +28,8 @@ export function createFakeSystemLookupConfiguration( systemLookupConfiguration.lookupValue = options?.initialValues?.lookupValue ?? faker.string.alphanumeric({ length: 100 }); + systemLookupConfiguration.lookupPriority = + options?.initialValues?.lookupPriority ?? 2; systemLookupConfiguration.creator = relations.auditUser; return systemLookupConfiguration; } diff --git a/sources/packages/forms/src/form-definitions/institutionprofile.json b/sources/packages/forms/src/form-definitions/institutionprofile.json index cd4e96f09a..af6c909b64 100644 --- a/sources/packages/forms/src/form-definitions/institutionprofile.json +++ b/sources/packages/forms/src/form-definitions/institutionprofile.json @@ -41,6 +41,15 @@ "input": false, "tableView": false }, + { + "label": "Is full institution profile update allowed", + "persistent": "client-only", + "calculateValue": "value = data.clientType === 'aest';", + "key": "isFullUpdateAllowed", + "type": "hidden", + "input": true, + "tableView": false + }, { "title": "Institution details panel", "collapsible": false, @@ -48,10 +57,14 @@ "key": "institutionDetailsPanel", "logic": [ { - "name": "Client type not AEST", + "name": "Disable panel when full update is not allowed", "trigger": { - "type": "javascript", - "javascript": "result = (data.clientType !== 'aest')" + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } }, "actions": [ { @@ -130,22 +143,6 @@ "type": "textfield", "input": true }, - { - "label": "Institution type", - "widget": "html5", - "tableView": true, - "clearOnHide": false, - "validate": { - "required": true - }, - "key": "institutionType", - "attributes": { - "data-cy": "institutionType" - }, - "type": "select", - "input": true, - "searchThreshold": 0.3 - }, { "label": "Institution regulatory body", "widget": "choicesjs", @@ -246,6 +243,268 @@ "type": "textfield", "input": true }, + { + "label": "What country is your institution located in?", + "widget": "choicesjs", + "placeholder": "Select country", + "tableView": true, + "validate": { + "required": true + }, + "validateWhenHidden": false, + "key": "country", + "logic": [ + { + "name": "Populate component data values from option values", + "trigger": { + "type": "javascript", + "javascript": "result = !!data.countryOptionValues && !!data.countryOptionValues.length;" + }, + "actions": [ + { + "name": "Set component data values", + "type": "customAction", + "customAction": "component.data.values = data.countryOptionValues.map((optionValue) => ({\r\n value: optionValue.lookupKey,\r\n label: optionValue.lookupValue,\r\n}));" + } + ] + }, + { + "name": "Set component to not required when full update is not allowed", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } + }, + "actions": [ + { + "name": "Set required as false", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "select", + "input": true + }, + { + "label": "In which Canadian province is the organization located?", + "widget": "choicesjs", + "placeholder": "Select province", + "tableView": true, + "validate": { + "required": true + }, + "validateWhenHidden": false, + "key": "province", + "conditional": { + "show": true, + "when": "country", + "eq": "CA" + }, + "logic": [ + { + "name": "Populate component data values from option values", + "trigger": { + "type": "javascript", + "javascript": "result = !!data.provinceOptionValues && !!data.provinceOptionValues.length;" + }, + "actions": [ + { + "name": "Set component data values", + "type": "customAction", + "customAction": "component.data.values = data.provinceOptionValues.map((optionValue) => ({\r\n value: optionValue.lookupKey,\r\n label: optionValue.lookupValue,\r\n}));" + } + ] + }, + { + "name": "Set component to not required when full update is not allowed", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } + }, + "actions": [ + { + "name": "Set required as false", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "select", + "input": true + }, + { + "label": "Is the institution public or private?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "Public", + "value": "public", + "shortcut": "" + }, + { + "label": "Private", + "value": "private", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "classification", + "logic": [ + { + "name": "Set component to not required when full update is not allowed", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } + }, + "actions": [ + { + "name": "Set required as false", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "radio", + "input": true + }, + { + "label": "Is the institution for profit or not for profit?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "For profit", + "value": "profit", + "shortcut": "" + }, + { + "label": "Not for profit", + "value": "notForProfit", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "organizationStatus", + "logic": [ + { + "name": "Set component to not required when full update is not allowed", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } + }, + "actions": [ + { + "name": "Set required as false", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "radio", + "input": true + }, + { + "label": "Is the institution medical in nature?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "Yes", + "value": "yes", + "shortcut": "" + }, + { + "label": "No", + "value": "no", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "medicalSchoolStatus", + "logic": [ + { + "name": "Set component to not required when full update is not allowed", + "trigger": { + "type": "simple", + "simple": { + "show": true, + "when": "isFullUpdateAllowed", + "eq": "false" + } + }, + "actions": [ + { + "name": "Set required as false", + "type": "property", + "property": { + "label": "Required", + "value": "validate.required", + "type": "boolean" + }, + "state": false + } + ] + } + ], + "type": "radio", + "input": true + }, { "label": "Columns", "columns": [ @@ -847,24 +1106,32 @@ "tableView": false }, { - "label": "mode (create/edit)", - "key": "mode", + "label": "Country option values", + "persistent": "client-only", + "key": "countryOptionValues", "type": "hidden", "input": true, "tableView": false }, { - "label": "applicationId", + "label": "Province option values", "persistent": "client-only", - "key": "applicationId", + "key": "provinceOptionValues", "type": "hidden", "input": true, "tableView": false }, { - "label": "applicationStatus", + "label": "Client type (aest|undefined)", "persistent": "client-only", - "key": "applicationStatus", + "key": "clientType", + "type": "hidden", + "input": true, + "tableView": false + }, + { + "label": "mode (create|edit)", + "key": "mode", "type": "hidden", "input": true, "tableView": false diff --git a/sources/packages/forms/src/form-definitions/institutionprofilecreation.json b/sources/packages/forms/src/form-definitions/institutionprofilecreation.json index b1e2a20906..8da670cd5f 100644 --- a/sources/packages/forms/src/form-definitions/institutionprofilecreation.json +++ b/sources/packages/forms/src/form-definitions/institutionprofilecreation.json @@ -178,22 +178,6 @@ "type": "textfield", "input": true }, - { - "label": "Institution type", - "widget": "html5", - "placeholder": "Select", - "tableView": true, - "validate": { - "required": true - }, - "key": "institutionType", - "attributes": { - "data-cy": "institutionType" - }, - "type": "select", - "input": true, - "searchThreshold": 0.3 - }, { "label": "Institution regulatory body", "widget": "choicesjs", @@ -293,6 +277,147 @@ "type": "textfield", "input": true }, + { + "label": "What country is your institution located in?", + "widget": "choicesjs", + "placeholder": "Select country", + "tableView": true, + "validate": { + "required": true + }, + "validateWhenHidden": false, + "key": "country", + "logic": [ + { + "name": "Populate component data values from option values", + "trigger": { + "type": "javascript", + "javascript": "result = !!data.countryOptionValues && !!data.countryOptionValues.length;" + }, + "actions": [ + { + "name": "Set component data values", + "type": "customAction", + "customAction": "component.data.values = data.countryOptionValues.map((optionValue) => ({\r\n value: optionValue.lookupKey,\r\n label: optionValue.lookupValue,\r\n}));" + } + ] + } + ], + "type": "select", + "input": true + }, + { + "label": "In which Canadian province is the organization located?", + "widget": "choicesjs", + "placeholder": "Select province", + "tableView": true, + "validate": { + "required": true + }, + "validateWhenHidden": false, + "key": "province", + "conditional": { + "show": true, + "when": "country", + "eq": "CA" + }, + "logic": [ + { + "name": "Populate component data values from option values", + "trigger": { + "type": "javascript", + "javascript": "result = !!data.provinceOptionValues && !!data.provinceOptionValues.length;" + }, + "actions": [ + { + "name": "Set component data values", + "type": "customAction", + "customAction": "component.data.values = data.provinceOptionValues.map((optionValue) => ({\r\n value: optionValue.lookupKey,\r\n label: optionValue.lookupValue,\r\n}));" + } + ] + } + ], + "type": "select", + "input": true + }, + { + "label": "Is the institution public or private?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "Public", + "value": "public", + "shortcut": "" + }, + { + "label": "Private", + "value": "private", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "classification", + "type": "radio", + "input": true + }, + { + "label": "Is the institution for profit or not for profit?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "For profit", + "value": "profit", + "shortcut": "" + }, + { + "label": "Not for profit", + "value": "notForProfit", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "organizationStatus", + "type": "radio", + "input": true + }, + { + "label": "Is the institution medical in nature?", + "optionsLabelPosition": "right", + "inline": false, + "tableView": false, + "values": [ + { + "label": "Yes", + "value": "yes", + "shortcut": "" + }, + { + "label": "No", + "value": "no", + "shortcut": "" + } + ], + "validate": { + "required": true, + "onlyAvailableItems": true + }, + "validateWhenHidden": false, + "key": "medicalSchoolStatus", + "type": "radio", + "input": true + }, { "label": "Columns", "columns": [ @@ -869,17 +994,17 @@ "tableView": false }, { - "label": "applicationId", + "label": "Country option values", "persistent": "client-only", - "key": "applicationId", + "key": "countryOptionValues", "type": "hidden", "input": true, "tableView": false }, { - "label": "applicationStatus", + "label": "Province option values", "persistent": "client-only", - "key": "applicationStatus", + "key": "provinceOptionValues", "type": "hidden", "input": true, "tableView": false diff --git a/sources/packages/web/src/components/institutions/profile/InstitutionProfileForm.vue b/sources/packages/web/src/components/institutions/profile/InstitutionProfileForm.vue index aeeba69ad8..051a3727d3 100644 --- a/sources/packages/web/src/components/institutions/profile/InstitutionProfileForm.vue +++ b/sources/packages/web/src/components/institutions/profile/InstitutionProfileForm.vue @@ -1,8 +1,8 @@