diff --git a/.circleci/config.yml b/.circleci/config.yml index eb1461673..ac2cb2e75 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -118,6 +118,7 @@ commands: - restore_cache: keys: - ubuntu-package-cache-v1-{{ checksum "~/bichard7-next-core/.circleci/scripts/install-ms-edge-on-linux.sh" }} + - ubuntu-package-cache-v1- - run: name: Install MS Edge (dev) working_directory: ~/bichard7-next-core diff --git a/cypress/e2e/case-details/view-case-details/view-offence-matching-exceptions.cy.ts b/cypress/e2e/case-details/view-case-details/view-offence-matching-exceptions.cy.ts index 9c603d23c..b2e632cad 100644 --- a/cypress/e2e/case-details/view-case-details/view-offence-matching-exceptions.cy.ts +++ b/cypress/e2e/case-details/view-case-details/view-offence-matching-exceptions.cy.ts @@ -7,13 +7,13 @@ describe("View offence matching exceptions", () => { { asn: ExceptionCode.HO100304, firstOffenceBadge: "Unmatched" }, { asn: ExceptionCode.HO100328, firstOffenceBadge: "Unmatched" }, { asn: ExceptionCode.HO100507, firstOffenceBadge: "Added by Court", secondOffenceBadge: "Added by Court" }, - { offenceReasonSequence: ExceptionCode.HO100203 }, - { offenceReasonSequence: ExceptionCode.HO100228 }, - { offenceReasonSequence: ExceptionCode.HO100311 }, - { offenceReasonSequence: ExceptionCode.HO100312 }, - { offenceReasonSequence: ExceptionCode.HO100320 }, - { offenceReasonSequence: ExceptionCode.HO100329 }, - { offenceReasonSequence: ExceptionCode.HO100333 } + { offenceReasonSequence: ExceptionCode.HO100203, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100228, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100311, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100312, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100320, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100329, firstOffenceBadge: "Unmatched" }, + { offenceReasonSequence: ExceptionCode.HO100333, firstOffenceBadge: "Unmatched" } ].forEach(({ asn, offenceReasonSequence, firstOffenceBadge = "Matched", secondOffenceBadge = "Unmatched" }) => { it(`Should display the correct error for ${asn ?? offenceReasonSequence}`, () => { cy.task("clearCourtCases") diff --git a/src/features/CourtCaseDetails/Tabs/Panels/Offences/Offence/OffenceMatching.tsx b/src/features/CourtCaseDetails/Tabs/Panels/Offences/Offence/OffenceMatching.tsx index 120b79519..71cddd875 100644 --- a/src/features/CourtCaseDetails/Tabs/Panels/Offences/Offence/OffenceMatching.tsx +++ b/src/features/CourtCaseDetails/Tabs/Panels/Offences/Offence/OffenceMatching.tsx @@ -1,33 +1,20 @@ import { Offence } from "@moj-bichard7-developers/bichard7-next-core/core/types/AnnotatedHearingOutcome" -import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" import Badge, { BadgeColours } from "components/Badge" import ConditionalRender from "components/ConditionalRender" import ErrorPromptMessage from "components/ErrorPromptMessage" import ExceptionFieldTableRow from "components/ExceptionFieldTableRow" import { useCourtCase } from "context/CourtCaseContext" import { useCurrentUser } from "context/CurrentUserContext" -import { findExceptions } from "types/ErrorMessages" -import { DisplayFullUser } from "types/display/Users" import { Exception } from "types/exceptions" -import getExceptionDefinition from "utils/getExceptionDefinition" +import getExceptionMessage from "utils/offenceMatcher/getExceptionMessage" +import getOffenceMatchingException from "utils/offenceMatcher/getOffenceMatchingException" +import isEnabled from "utils/offenceMatcher/isEnabled" +import offenceMatchingExceptions from "utils/offenceMatcher/offenceMatchingExceptions" import findCandidates from "../../../../../../utils/offenceMatcher/findCandidates" import { TableRow } from "../../TableRow" -import { getOffenceMatchingException } from "utils/offenceMatcher/getOffenceMatchingException" import OffenceMatcher from "./OffenceMatcher" -const enabled = (user: DisplayFullUser) => { - const enabledInProduction = true // change this if we need to disable in production for everyone - const { exceptionsEnabled, offenceMatchingEnabled } = user.featureFlags - const featureFlagsEnabled = exceptionsEnabled && offenceMatchingEnabled - - const isProduction = process.env.WORKSPACE === "production" - if (!isProduction) { - return featureFlagsEnabled - } - return enabledInProduction && featureFlagsEnabled -} - -type Props = { +type OffenceMatchingProps = { offenceIndex: number offence: Offence isCaseUnresolved: boolean @@ -41,37 +28,15 @@ export const OffenceMatching = ({ isCaseUnresolved, exceptions, isCaseLockedToCurrentUser -}: Props) => { +}: OffenceMatchingProps) => { const { courtCase, savedAmendments } = useCourtCase() const currentUser = useCurrentUser() - const offenceMatchingExceptions = [ExceptionCode.HO100310, ExceptionCode.HO100332] - const noneOffenceMatchingExceptions = [ - ExceptionCode.HO100203, - ExceptionCode.HO100228, - ExceptionCode.HO100304, - ExceptionCode.HO100311, - ExceptionCode.HO100312, - ExceptionCode.HO100320, - ExceptionCode.HO100328, - ExceptionCode.HO100333, - ExceptionCode.HO100507 - ] - const offenceMatchingException = isCaseUnresolved && getOffenceMatchingException(exceptions, offenceIndex) - - const findExceptionByOffenceNumber = courtCase.aho.Exceptions.filter((exception) => - exception.path.includes(offenceIndex) - ) - const offenceMatchingExceptionMessage = - findExceptions( - courtCase, - findExceptionByOffenceNumber.length > 0 ? findExceptionByOffenceNumber : courtCase.aho.Exceptions, - ...noneOffenceMatchingExceptions - ) || getExceptionDefinition(findExceptionByOffenceNumber[0]?.code)?.shortDescription + const offenceMatchingExceptionMessage = getExceptionMessage(courtCase, offenceIndex) const displayOffenceMatcher = - enabled(currentUser) && exceptions.some((e) => offenceMatchingExceptions.includes(e.code)) + isEnabled(currentUser) && exceptions.some((e) => offenceMatchingExceptions.offenceNotMatched.includes(e.code)) const userCanMatchOffence = courtCase.errorLockedByUsername === currentUser?.username && courtCase.errorStatus === "Unresolved" diff --git a/src/utils/getTabDetails.ts b/src/utils/getTabDetails.ts index d571f66c7..7e1fa0102 100644 --- a/src/utils/getTabDetails.ts +++ b/src/utils/getTabDetails.ts @@ -2,12 +2,12 @@ import { Amendments } from "types/Amendments" import { Exception } from "types/exceptions" import getNextHearingDateExceptions from "./exceptions/getNextHearingDateExceptions" import getNextHearingLocationExceptions from "./exceptions/getNextHearingLocationExceptions" -import { getOffenceMatchingExceptions } from "./offenceMatcher/getOffenceMatchingException" import hasNextHearingDateExceptions from "./exceptions/hasNextHearingDateExceptions" import hasNextHearingLocationException from "./exceptions/hasNextHearingLocationException" -import hasOffenceMatchingExceptions from "./offenceMatcher/hasOffenceMatchingExceptions" import isAsnFormatValid from "./exceptions/isAsnFormatValid" import isAsnException from "./exceptions/isException/isAsnException" +import getOffenceMatchingExceptions from "./offenceMatcher/getOffenceMatchingExceptions" +import hasOffenceMatchingExceptions from "./offenceMatcher/hasOffenceMatchingExceptions" export type TabDetails = { name: "Defendant" | "Hearing" | "Case" | "Offences" | "Notes" diff --git a/src/utils/offenceMatcher/findCandidates.ts b/src/utils/offenceMatcher/findCandidates.ts index 64da9e9e9..8e14812db 100644 --- a/src/utils/offenceMatcher/findCandidates.ts +++ b/src/utils/offenceMatcher/findCandidates.ts @@ -1,7 +1,7 @@ +import { CaseType } from "@moj-bichard7-developers/bichard7-next-core/core/phase1/enrichAho/enrichFunctions/matchOffencesToPnc/annotatePncMatch" +import generateCandidate from "@moj-bichard7-developers/bichard7-next-core/core/phase1/enrichAho/enrichFunctions/matchOffencesToPnc/generateCandidate" import { DisplayFullCourtCase } from "../../types/display/CourtCases" import { Candidates } from "../../types/OffenceMatching" -import generateCandidate from "@moj-bichard7-developers/bichard7-next-core/core/phase1/enrichAho/enrichFunctions/matchOffencesToPnc/generateCandidate" -import { CaseType } from "@moj-bichard7-developers/bichard7-next-core/core/phase1/enrichAho/enrichFunctions/matchOffencesToPnc/annotatePncMatch" const findCandidates = (courtCase: DisplayFullCourtCase, offenceIndex: number): Candidates[] => { if (!courtCase.aho.PncQuery || !courtCase.aho.PncQuery.courtCases) { @@ -9,7 +9,7 @@ const findCandidates = (courtCase: DisplayFullCourtCase, offenceIndex: number): } const offence = courtCase.aho.AnnotatedHearingOutcome.HearingOutcome.Case.HearingDefendant.Offence[offenceIndex] - const candiates = courtCase.aho.PncQuery.courtCases + const candidates = courtCase.aho.PncQuery.courtCases .map((c) => { const matchForThisCase = c.offences.filter( (pncOffence) => @@ -28,7 +28,7 @@ const findCandidates = (courtCase: DisplayFullCourtCase, offenceIndex: number): }) .filter((e) => !!e) - return candiates as Candidates[] + return candidates as Candidates[] } export default findCandidates diff --git a/src/utils/offenceMatcher/getExceptionMessage.test.ts b/src/utils/offenceMatcher/getExceptionMessage.test.ts new file mode 100644 index 000000000..f831af9a5 --- /dev/null +++ b/src/utils/offenceMatcher/getExceptionMessage.test.ts @@ -0,0 +1,83 @@ +import type { AnnotatedHearingOutcome } from "@moj-bichard7-developers/bichard7-next-core/core/types/AnnotatedHearingOutcome" +import type { DisplayFullCourtCase } from "types/display/CourtCases" +import getExceptionMessage from "./getExceptionMessage" + +describe("getExceptionMessage", () => { + let courtCase: DisplayFullCourtCase + + beforeEach(() => { + courtCase = { + asn: "", + courtName: "", + errorId: 0, + errorStatus: "Unresolved", + errorReport: "", + isUrgent: false, + ptiurn: "", + triggerCount: 0, + defendantName: "", + orgForPoliceFilter: null, + courtCode: null, + courtReference: "", + notes: [], + canUserEditExceptions: false, + triggers: [], + resolutionTimestamp: null, + aho: {} as AnnotatedHearingOutcome, + updatedHearingOutcome: {} as AnnotatedHearingOutcome + } + }) + + it("returns undefined if there's no exceptions in the aho", () => { + const result = getExceptionMessage(courtCase, 0) + expect(result).toBeUndefined() + }) + + it("returns the exception message if there is exceptions in the aho and it's not present ErrorMessages file", () => { + courtCase.aho = { + Exceptions: [{ code: "HO100310", path: ["path", "to", 0, "offence"] }] + } as AnnotatedHearingOutcome + + const result = getExceptionMessage(courtCase, 0) + expect(result).toBe("Multiple court Offences with different Results match a PNC offence") + }) + + it("returns the exception message if there is exceptions in the aho and it's present ErrorMessages file", () => { + courtCase.aho = { + Exceptions: [{ code: "HO100507", path: ["path", "to", 0, "offence"] }] + } as AnnotatedHearingOutcome + + const result = getExceptionMessage(courtCase, 0) + expect(result).toBe( + "Offences have been added in court to a Penalty case. This needs to be manually resolved on the PNC to deal with error, and then manually resolved in Bichard." + ) + }) + + it("returns undefined if the exception is resolved", () => { + courtCase.errorStatus = "Resolved" + courtCase.aho = { + Exceptions: [{ code: "HO100310", path: ["path", "to", 0, "offence"] }] + } as AnnotatedHearingOutcome + + const result = getExceptionMessage(courtCase, 0) + expect(result).toBeUndefined() + }) + + it("returns undefined if the exception is not found", () => { + courtCase.aho = { + Exceptions: [{ code: "HO100110", path: ["path", "to", 0, "offence"] }] + } as AnnotatedHearingOutcome + + const result = getExceptionMessage(courtCase, 0) + expect(result).toBeUndefined() + }) + + it("returns undefined if the exception is not found with the offenceIndex begin changed", () => { + courtCase.aho = { + Exceptions: [{ code: "HO100110", path: ["path", "to", 0, "offence"] }] + } as AnnotatedHearingOutcome + + const result = getExceptionMessage(courtCase, 1) + expect(result).toBeUndefined() + }) +}) diff --git a/src/utils/offenceMatcher/getExceptionMessage.ts b/src/utils/offenceMatcher/getExceptionMessage.ts new file mode 100644 index 000000000..dcb51284d --- /dev/null +++ b/src/utils/offenceMatcher/getExceptionMessage.ts @@ -0,0 +1,35 @@ +import type ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" +import type { DisplayFullCourtCase } from "types/display/CourtCases" +import { findExceptions } from "types/ErrorMessages" +import getExceptionDefinition from "utils/getExceptionDefinition" +import offenceMatchingExceptions from "./offenceMatchingExceptions" + +type ExceptionCodeAndPath = { + code: ExceptionCode + path: (string | number)[] +} + +const findExceptionByOffenceNumber = (courtCase: DisplayFullCourtCase, offenceIndex: number): ExceptionCodeAndPath[] => + courtCase.aho.Exceptions?.filter((exception) => exception.path.includes(offenceIndex)) + +const getExceptionMessage = (courtCase: DisplayFullCourtCase, offenceIndex: number): string | undefined => { + const exceptionByOffenceNumber: ExceptionCodeAndPath[] = findExceptionByOffenceNumber(courtCase, offenceIndex) + + if (exceptionByOffenceNumber === undefined) { + return undefined + } + + if (courtCase.errorStatus === "Resolved") { + return undefined + } + + return ( + findExceptions( + courtCase, + exceptionByOffenceNumber.length > 0 ? exceptionByOffenceNumber : courtCase.aho.Exceptions, + ...offenceMatchingExceptions.noOffencesMatched + ) || getExceptionDefinition(exceptionByOffenceNumber[0]?.code)?.shortDescription + ) +} + +export default getExceptionMessage diff --git a/src/utils/offenceMatcher/getOffenceMatchingException.test.ts b/src/utils/offenceMatcher/getOffenceMatchingException.test.ts index 1dbb1b42a..e733a950d 100644 --- a/src/utils/offenceMatcher/getOffenceMatchingException.test.ts +++ b/src/utils/offenceMatcher/getOffenceMatchingException.test.ts @@ -1,39 +1,8 @@ -import { Exception } from "types/exceptions" -import { - getOffenceMatchingException, - GetOffenceMatchingExceptionResult, - getOffenceMatchingExceptions -} from "./getOffenceMatchingException" import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" +import type { Exception } from "types/exceptions" import { ExceptionBadgeType } from "utils/exceptions/exceptionBadgeType" - -describe("getOffenceMatchingExceptions", () => { - it("returns an empty array when given no exceptions", () => { - const result = getOffenceMatchingExceptions([]) - expect(result).toEqual([]) - }) - - it("returns an empty array when given exception that is not in array of valid values", () => { - const exception: Exception = { code: ExceptionCode.HO100304, path: ["test"] } - const result = getOffenceMatchingExceptions([exception]) - expect(result).toEqual([]) - }) - - it("returns exception when given exception that is in array of valid values", () => { - const exception: Exception = { code: ExceptionCode.HO100310, path: ["test"] } - const result = getOffenceMatchingExceptions([exception]) - expect(result).toEqual([exception]) - }) - - it("returns exception when given multiple exceptions and exception is in array of valid values", () => { - const exceptions: Exception[] = [ - { code: ExceptionCode.HO100304, path: ["test"] }, - { code: ExceptionCode.HO100310, path: ["test"] } - ] - const result = getOffenceMatchingExceptions(exceptions) - expect(result).toEqual([exceptions[1]]) - }) -}) +import type { GetOffenceMatchingExceptionResult } from "./getOffenceMatchingException" +import getOffenceMatchingException from "./getOffenceMatchingException" describe("getOffenceMatchingException", () => { it("returns undefined when given an empty array", () => { diff --git a/src/utils/offenceMatcher/getOffenceMatchingException.ts b/src/utils/offenceMatcher/getOffenceMatchingException.ts index 7b635b071..2ad920310 100644 --- a/src/utils/offenceMatcher/getOffenceMatchingException.ts +++ b/src/utils/offenceMatcher/getOffenceMatchingException.ts @@ -3,22 +3,9 @@ import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/type import { isEqual } from "lodash" import { Exception } from "types/exceptions" import { ExceptionBadgeType } from "../exceptions/exceptionBadgeType" +import offenceMatchingExceptions from "./offenceMatchingExceptions" const getOffenceReasonSequencePath = (offenceIndex: number) => errorPaths.offence(offenceIndex).reasonSequence -const offenceMatchingExceptions = { - noOffencesMatched: [ExceptionCode.HO100304, ExceptionCode.HO100328, ExceptionCode.HO100507], - offenceNotMatched: [ - ExceptionCode.HO100203, - ExceptionCode.HO100228, - ExceptionCode.HO100310, - ExceptionCode.HO100311, - ExceptionCode.HO100312, - ExceptionCode.HO100320, - ExceptionCode.HO100329, - ExceptionCode.HO100332, - ExceptionCode.HO100333 - ] -} type GetOffenceMatchingExceptionResult = | { @@ -27,10 +14,6 @@ type GetOffenceMatchingExceptionResult = } | undefined -const getOffenceMatchingExceptions = (exceptions: Exception[]): Exception[] => { - return exceptions.filter((exception) => offenceMatchingExceptions.offenceNotMatched.includes(exception.code)) -} - const getOffenceMatchingException = ( exceptions: Exception[], offenceIndex: number @@ -61,5 +44,5 @@ const getOffenceMatchingException = ( } } -export { getOffenceMatchingException, getOffenceMatchingExceptions } +export default getOffenceMatchingException export type { GetOffenceMatchingExceptionResult } diff --git a/src/utils/offenceMatcher/getOffenceMatchingExceptions.test.ts b/src/utils/offenceMatcher/getOffenceMatchingExceptions.test.ts new file mode 100644 index 000000000..ab3a83793 --- /dev/null +++ b/src/utils/offenceMatcher/getOffenceMatchingExceptions.test.ts @@ -0,0 +1,31 @@ +import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" +import type { Exception } from "types/exceptions" +import getOffenceMatchingExceptions from "./getOffenceMatchingExceptions" + +describe("getOffenceMatchingExceptions", () => { + it("returns an empty array when given no exceptions", () => { + const result = getOffenceMatchingExceptions([]) + expect(result).toEqual([]) + }) + + it("returns an empty array when given exception that is not in array of valid values", () => { + const exception: Exception = { code: ExceptionCode.HO100312, path: ["test"] } + const result = getOffenceMatchingExceptions([exception]) + expect(result).toEqual([]) + }) + + it("returns exception when given exception that is in array of valid values", () => { + const exception: Exception = { code: ExceptionCode.HO100310, path: ["test"] } + const result = getOffenceMatchingExceptions([exception]) + expect(result).toEqual([exception]) + }) + + it("returns exception when given multiple exceptions and exception is in array of valid values", () => { + const exceptions: Exception[] = [ + { code: ExceptionCode.HO100310, path: ["test"] }, + { code: ExceptionCode.HO100312, path: ["test"] } + ] + const result = getOffenceMatchingExceptions(exceptions) + expect(result).toEqual([exceptions[0]]) + }) +}) diff --git a/src/utils/offenceMatcher/getOffenceMatchingExceptions.ts b/src/utils/offenceMatcher/getOffenceMatchingExceptions.ts new file mode 100644 index 000000000..ff2aadf39 --- /dev/null +++ b/src/utils/offenceMatcher/getOffenceMatchingExceptions.ts @@ -0,0 +1,7 @@ +import type { Exception } from "types/exceptions" +import offenceMatchingExceptions from "./offenceMatchingExceptions" + +const getOffenceMatchingExceptions = (exceptions: Exception[]): Exception[] => + exceptions.filter((exception) => offenceMatchingExceptions.offenceNotMatched.includes(exception.code)) + +export default getOffenceMatchingExceptions diff --git a/src/utils/offenceMatcher/hasOffenceMatchingExceptions.test.ts b/src/utils/offenceMatcher/hasOffenceMatchingExceptions.test.ts index 6046f83f4..967c6c399 100644 --- a/src/utils/offenceMatcher/hasOffenceMatchingExceptions.test.ts +++ b/src/utils/offenceMatcher/hasOffenceMatchingExceptions.test.ts @@ -1,6 +1,6 @@ import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" -import hasOffenceMatchingExceptions, { filterOffenceMatchingException } from "./hasOffenceMatchingExceptions" import { Exception } from "types/exceptions" +import hasOffenceMatchingExceptions from "./hasOffenceMatchingExceptions" describe("hasOffenceMatchingExceptions", () => { it("returns false when given empty array", () => { @@ -29,31 +29,3 @@ describe("hasOffenceMatchingExceptions", () => { expect(result).toBe(true) }) }) - -describe("filterOffenceMatchingException", () => { - it("returns an empty array when given no exceptions", () => { - const result = filterOffenceMatchingException([]) - expect(result).toEqual([]) - }) - - it("returns an empty array when given exception that is not in array of valid values", () => { - const exception: Exception = { code: ExceptionCode.HO100312, path: ["test"] } - const result = filterOffenceMatchingException([exception]) - expect(result).toEqual([]) - }) - - it("returns exception when given exception that is in array of valid values", () => { - const exception: Exception = { code: ExceptionCode.HO100310, path: ["test"] } - const result = filterOffenceMatchingException([exception]) - expect(result).toEqual([exception]) - }) - - it("returns exception when given multiple exceptions and exception is in array of valid values", () => { - const exceptions: Exception[] = [ - { code: ExceptionCode.HO100310, path: ["test"] }, - { code: ExceptionCode.HO100312, path: ["test"] } - ] - const result = filterOffenceMatchingException(exceptions) - expect(result).toEqual([exceptions[0]]) - }) -}) diff --git a/src/utils/offenceMatcher/hasOffenceMatchingExceptions.ts b/src/utils/offenceMatcher/hasOffenceMatchingExceptions.ts index cff823a34..ea928a9fe 100644 --- a/src/utils/offenceMatcher/hasOffenceMatchingExceptions.ts +++ b/src/utils/offenceMatcher/hasOffenceMatchingExceptions.ts @@ -1,12 +1,6 @@ -import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" import { Exception } from "types/exceptions" +import getOffenceMatchingExceptions from "./getOffenceMatchingExceptions" -const offenceMatchingExceptions = [ExceptionCode.HO100310] +const hasOffenceMatchingExceptions = (exceptions: Exception[]) => getOffenceMatchingExceptions(exceptions).length > 0 -const filterOffenceMatchingException = (exceptions: Exception[]): Exception[] => - exceptions.filter((exception) => offenceMatchingExceptions.includes(exception.code)) - -const hasOffenceMatchingExceptions = (exceptions: Exception[]) => filterOffenceMatchingException(exceptions).length > 0 - -export { filterOffenceMatchingException } export default hasOffenceMatchingExceptions diff --git a/src/utils/offenceMatcher/isEnabled.test.ts b/src/utils/offenceMatcher/isEnabled.test.ts new file mode 100644 index 000000000..1144b15b0 --- /dev/null +++ b/src/utils/offenceMatcher/isEnabled.test.ts @@ -0,0 +1,59 @@ +import type { DisplayFullUser } from "types/display/Users" +import isEnabled from "./isEnabled" + +describe("isEnabled", () => { + let user: DisplayFullUser + + beforeEach(() => { + user = { + username: "GeneralHandler", + visibleForces: [], + email: "generalhandler@example.com", + visibleCourts: [], + excludedTriggers: [], + groups: [], + hasAccessTo: { 0: false, 1: false, 2: false, 3: false, 4: false, 5: false, 6: false }, + featureFlags: {} + } + }) + + it("returns false with no feature flags", () => { + const result = isEnabled(user) + expect(result).toBe(false) + }) + + it("returns false with only exceptionsEnabled feature flag enabled", () => { + user.featureFlags = { exceptionsEnabled: true } + + const result = isEnabled(user) + expect(result).toBe(false) + }) + + it("returns false with only offenceMatchingEnabled feature flag enabled", () => { + user.featureFlags = { offenceMatchingEnabled: true } + + const result = isEnabled(user) + expect(result).toBe(false) + }) + + it("returns true with exceptionsEnabled and offenceMatchingEnabled feature flag enabled", () => { + user.featureFlags = { exceptionsEnabled: true, offenceMatchingEnabled: true } + + const result = isEnabled(user) + expect(result).toBe(true) + }) + + it("returns false with exceptionsEnabled disabled and offenceMatchingEnabled enabled", () => { + user.featureFlags = { exceptionsEnabled: false, offenceMatchingEnabled: true } + + const result = isEnabled(user) + expect(result).toBe(false) + }) + + it("returns false with exceptionsEnabled enabled and offenceMatchingEnabled disabled", () => { + user.featureFlags = { exceptionsEnabled: true, offenceMatchingEnabled: false } + + const result = isEnabled(user) + expect(result).toBe(false) + }) +}) diff --git a/src/utils/offenceMatcher/isEnabled.ts b/src/utils/offenceMatcher/isEnabled.ts new file mode 100644 index 000000000..b76b1766b --- /dev/null +++ b/src/utils/offenceMatcher/isEnabled.ts @@ -0,0 +1,15 @@ +import type { DisplayFullUser } from "types/display/Users" + +const isEnabled = (user: DisplayFullUser): boolean => { + const enabledInProduction = true // change this if we need to disable in production for everyone + const { exceptionsEnabled, offenceMatchingEnabled } = user.featureFlags + const featureFlagsEnabled: boolean = (exceptionsEnabled ?? false) && (offenceMatchingEnabled ?? false) + + const isProduction = process.env.WORKSPACE === "production" + if (!isProduction) { + return featureFlagsEnabled + } + return enabledInProduction && featureFlagsEnabled +} + +export default isEnabled diff --git a/src/utils/offenceMatcher/offenceMatchingExceptions.ts b/src/utils/offenceMatcher/offenceMatchingExceptions.ts new file mode 100644 index 000000000..d53f2e1e8 --- /dev/null +++ b/src/utils/offenceMatcher/offenceMatchingExceptions.ts @@ -0,0 +1,19 @@ +import ExceptionCode from "@moj-bichard7-developers/bichard7-next-data/dist/types/ExceptionCode" + +const offenceMatchingExceptions = { + noOffencesMatched: [ + ExceptionCode.HO100203, + ExceptionCode.HO100228, + ExceptionCode.HO100304, + ExceptionCode.HO100311, + ExceptionCode.HO100312, + ExceptionCode.HO100320, + ExceptionCode.HO100329, + ExceptionCode.HO100328, + ExceptionCode.HO100333, + ExceptionCode.HO100507 + ], + offenceNotMatched: [ExceptionCode.HO100310, ExceptionCode.HO100332] +} + +export default offenceMatchingExceptions