diff --git a/app/src/controllers/permit.ts b/app/src/controllers/permit.ts index 3d9dba91..e050beb5 100644 --- a/app/src/controllers/permit.ts +++ b/app/src/controllers/permit.ts @@ -36,9 +36,9 @@ const controller = { } }, - async listPermits(req: Request<{ activityId: string }>, res: Response, next: NextFunction) { + async listPermits(req: Request, res: Response, next: NextFunction) { try { - const response = await permitService.listPermits(req.params.activityId); + const response = await permitService.listPermits(req.query?.activityId); res.status(200).json(response); } catch (e: unknown) { next(e); diff --git a/app/src/db/migrations/20240718000000_007-rbac.ts b/app/src/db/migrations/20240718000000_007-rbac.ts index 25f0f03b..f4a8128d 100644 --- a/app/src/db/migrations/20240718000000_007-rbac.ts +++ b/app/src/db/migrations/20240718000000_007-rbac.ts @@ -710,12 +710,264 @@ export async function up(knex: Knex): Promise { inner join yars.resource on resource.resource_id = yars.policy.resource_id inner join yars.action on yars.action.action_id = yars.policy.action_id;`); }) + + // Drop public schema functions + .then(() => + knex.schema.raw(`drop function public.get_activity_statistics( + date_from text, + date_to text, + month_year text, + user_id uuid + )`) + ) + + // Create public schema functions + .then(() => + knex.schema.raw(`create or replace function public.get_activity_statistics( + date_from text, + date_to text, + month_year text, + user_id uuid + ) + returns table ( + total_submissions bigint, + total_submissions_between bigint, + total_submissions_monthyear bigint, + total_submissions_assignedto bigint, + intake_submitted bigint, + intake_assigned bigint, + intake_completed bigint, + state_new bigint, + state_inprogress bigint, + state_delayed bigint, + state_completed bigint, + supported_bc bigint, + supported_indigenous bigint, + supported_non_profit bigint, + supported_housing_coop bigint, + waiting_on bigint, + queue_1 bigint, + queue_2 bigint, + queue_3 bigint, + escalation bigint, + general_enquiry bigint, + guidance bigint, + inapplicable bigint, + status_request bigint, + multi_permits_needed bigint + ) + language plpgsql + as $$ + begin + return query + with submission_counts as ( + select + count(*) as submission_count, + (select count(*) from public.submission where "submitted_at" between cast(date_from as timestamp) and cast(date_to as timestamp)) as submission_count_between, + (select count(*) from public.submission where extract(month from cast(month_year as timestamp)) = extract(month from "submitted_at") and extract(year from cast(month_year as timestamp)) = extract(year from "submitted_at")) as submission_count_monthyear, + (select count(*) from public.submission where "assigned_user_id" = user_id) as submission_count_assignedto, + count(*) filter (where s."intake_status" = 'Submitted') as intake_submitted_submission_count, + count(*) filter (where s."intake_status" = 'Assigned') as intake_assigned_submission_count, + count(*) filter (where s."intake_status" = 'Completed') as intake_completed_submission_count, + count(*) filter (where s."application_status" = 'New') as state_new_submission_count, + count(*) filter (where s."application_status" = 'In Progress') as state_inprogress_submission_count, + count(*) filter (where s."application_status" = 'Delayed') as state_delayed_submission_count, + count(*) filter (where s."application_status" = 'Completed') as state_completed_submission_count, + count(*) filter (where s."financially_supported_bc" = 'Yes') as supported_bc_submission_count, + count(*) filter (where s."financially_supported_indigenous" = 'Yes') as supported_indigenous_submission_count, + count(*) filter (where s."financially_supported_non_profit" = 'Yes') as supported_non_profit_submission_count, + count(*) filter (where s."financially_supported_housing_coop" = 'Yes') as supported_housing_coop_submission_count, + count(*) filter (where s."waiting_on" is not null) as waiting_on_submission_count, + count(*) filter (where s."queue_priority" = 1) as queue_1_submission_count, + count(*) filter (where s."queue_priority" = 2) as queue_2_submission_count, + count(*) filter (where s."queue_priority" = 3) as queue_3_submission_count, + count(*) filter (where s."submission_type" = 'Guidance') as guidance_submission_count, + count(*) filter (where s."submission_type" = 'Inapplicable') as inapplicable_submission_count, + count(distinct s.activity_id) filter (where permit_counts.permit_count > 1) as multi_permits_needed + from public.submission s + join public.activity a on s.activity_id = a.activity_id + left join ( + select p.activity_id, count(*) as permit_count + from public.permit p + where p.needed = 'Yes' + group by p.activity_id + ) permit_counts on permit_counts.activity_id = s.activity_id + where a.is_deleted = false + ), + enquiry_counts as ( + select + count(*) as enquiry_count, + (select count(*) from public.enquiry where "submitted_at" between cast(date_from as timestamp) and cast(date_to as timestamp)) as enquiry_count_between, + (select count(*) from public.enquiry where extract(month from cast(month_year as timestamp)) = extract(month from "submitted_at") and extract(year from cast(month_year as timestamp)) = extract(year from "submitted_at")) as enquiry_count_monthyear, + (select count(*) from public.enquiry where "assigned_user_id" = user_id) as enquiry_count_assignedto, + count(*) filter (where e."intake_status" = 'Submitted') as intake_submitted_enquiry_count, + count(*) filter (where e."intake_status" = 'Assigned') as intake_assigned_enquiry_count, + count(*) filter (where e."intake_status" = 'Completed') as intake_completed_enquiry_count, + count(*) filter (where e."waiting_on" is not null) waiting_on_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Escalation') escalation_enquiry_count, + count(*) filter (where e."enquiry_type" = 'General enquiry') general_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Inapplicable') as inapplicable_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Status request') as status_request_enquiry_count + from public.enquiry e + join public.activity a on e.activity_id = a.activity_id + where a.is_deleted = false) + select + (submission_counts.submission_count + enquiry_counts.enquiry_count) AS total_submissions, + (submission_counts.submission_count_between + enquiry_counts.enquiry_count_between) AS total_submissions_between, + (submission_counts.submission_count_monthyear + enquiry_counts.enquiry_count_monthyear) AS total_submissions_monthyear, + (submission_counts.submission_count_assignedto + enquiry_counts.enquiry_count_assignedto) AS total_submissions_assignedto, + (submission_counts.intake_submitted_submission_count + enquiry_counts.intake_submitted_enquiry_count) AS intake_submitted, + (submission_counts.intake_assigned_submission_count + enquiry_counts.intake_assigned_enquiry_count) AS intake_assigned, + (submission_counts.intake_completed_submission_count + enquiry_counts.intake_completed_enquiry_count) AS intake_completed, + (submission_counts.state_new_submission_count) AS state_new, + (submission_counts.state_inprogress_submission_count) AS state_inprogress, + (submission_counts.state_delayed_submission_count) AS state_delayed, + (submission_counts.state_completed_submission_count) AS state_completed, + (submission_counts.supported_bc_submission_count) AS supported_bc, + (submission_counts.supported_indigenous_submission_count) AS supported_indigenous, + (submission_counts.supported_non_profit_submission_count) AS supported_non_profit, + (submission_counts.supported_housing_coop_submission_count) AS supported_housing_coop, + (submission_counts.waiting_on_submission_count + enquiry_counts.waiting_on_enquiry_count) AS waiting_on, + (submission_counts.queue_1_submission_count) AS queue_1, + (submission_counts.queue_2_submission_count) AS queue_2, + (submission_counts.queue_3_submission_count) AS queue_3, + (enquiry_counts.escalation_enquiry_count) AS escalation, + (enquiry_counts.general_enquiry_count) AS general_enquiry, + (submission_counts.guidance_submission_count) AS guidance, + (submission_counts.inapplicable_submission_count + enquiry_counts.inapplicable_enquiry_count) AS inapplicable, + (enquiry_counts.status_request_enquiry_count) AS status_request, + (submission_counts.multi_permits_needed) AS multi_permits_needed + from submission_counts, enquiry_counts; + end; $$`) + ) ); } export async function down(knex: Knex): Promise { return ( Promise.resolve() + + // Drop public schema functions + .then(() => + knex.schema.raw(`drop function public.get_activity_statistics( + date_from text, + date_to text, + month_year text, + user_id uuid + )`) + ) + + // Create public schema functions + .then(() => + knex.schema.raw(`create or replace function public.get_activity_statistics( + date_from text, + date_to text, + month_year text, + user_id uuid + ) + returns table ( + total_submissions bigint, + total_submissions_between bigint, + total_submissions_monthyear bigint, + total_submissions_assignedto bigint, + intake_submitted bigint, + intake_assigned bigint, + intake_completed bigint, + state_new bigint, + state_inprogress bigint, + state_delayed bigint, + state_completed bigint, + supported_bc bigint, + supported_indigenous bigint, + supported_non_profit bigint, + supported_housing_coop bigint, + waiting_on bigint, + queue_1 bigint, + queue_2 bigint, + queue_3 bigint, + escalation bigint, + general_enquiry bigint, + guidance bigint, + inapplicable bigint, + status_request bigint + ) + language plpgsql + as $$ + begin + return query + with submission_counts as ( + select + count(*) as submission_count, + (select count(*) from public.submission where "submitted_at" between cast(date_from as timestamp) and cast(date_to as timestamp)) as submission_count_between, + (select count(*) from public.submission where extract(month from cast(month_year as timestamp)) = extract(month from "submitted_at") and extract(year from cast(month_year as timestamp)) = extract(year from "submitted_at")) as submission_count_monthyear, + (select count(*) from public.submission where "assigned_user_id" = user_id) as submission_count_assignedto, + count(*) filter (where s."intake_status" = 'Submitted') as intake_submitted_submission_count, + count(*) filter (where s."intake_status" = 'Assigned') as intake_assigned_submission_count, + count(*) filter (where s."intake_status" = 'Completed') as intake_completed_submission_count, + count(*) filter (where s."application_status" = 'New') as state_new_submission_count, + count(*) filter (where s."application_status" = 'In Progress') as state_inprogress_submission_count, + count(*) filter (where s."application_status" = 'Delayed') as state_delayed_submission_count, + count(*) filter (where s."application_status" = 'Completed') as state_completed_submission_count, + count(*) filter (where s."financially_supported_bc" = 'Yes') as supported_bc_submission_count, + count(*) filter (where s."financially_supported_indigenous" = 'Yes') as supported_indigenous_submission_count, + count(*) filter (where s."financially_supported_non_profit" = 'Yes') as supported_non_profit_submission_count, + count(*) filter (where s."financially_supported_housing_coop" = 'Yes') as supported_housing_coop_submission_count, + count(*) filter (where s."waiting_on" is not null) as waiting_on_submission_count, + count(*) filter (where s."queue_priority" = 1) as queue_1_submission_count, + count(*) filter (where s."queue_priority" = 2) as queue_2_submission_count, + count(*) filter (where s."queue_priority" = 3) as queue_3_submission_count, + count(*) filter (where s."submission_type" = 'Guidance') as guidance_submission_count, + count(*) filter (where s."submission_type" = 'Inapplicable') as inapplicable_submission_count + from public.submission s + join public.activity a on s.activity_id = a.activity_id + where a.is_deleted = false + ), + enquiry_counts as ( + select + count(*) as enquiry_count, + (select count(*) from public.enquiry where "submitted_at" between cast(date_from as timestamp) and cast(date_to as timestamp)) as enquiry_count_between, + (select count(*) from public.enquiry where extract(month from cast(month_year as timestamp)) = extract(month from "submitted_at") and extract(year from cast(month_year as timestamp)) = extract(year from "submitted_at")) as enquiry_count_monthyear, + (select count(*) from public.enquiry where "assigned_user_id" = user_id) as enquiry_count_assignedto, + count(*) filter (where e."intake_status" = 'Submitted') as intake_submitted_enquiry_count, + count(*) filter (where e."intake_status" = 'Assigned') as intake_assigned_enquiry_count, + count(*) filter (where e."intake_status" = 'Completed') as intake_completed_enquiry_count, + count(*) filter (where e."waiting_on" is not null) waiting_on_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Escalation') escalation_enquiry_count, + count(*) filter (where e."enquiry_type" = 'General enquiry') general_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Inapplicable') as inapplicable_enquiry_count, + count(*) filter (where e."enquiry_type" = 'Status request') as status_request_enquiry_count + from public.enquiry e + join public.activity a on e.activity_id = a.activity_id + where a.is_deleted = false) + select + (submission_counts.submission_count + enquiry_counts.enquiry_count) AS total_submissions, + (submission_counts.submission_count_between + enquiry_counts.enquiry_count_between) AS total_submissions_between, + (submission_counts.submission_count_monthyear + enquiry_counts.enquiry_count_monthyear) AS total_submissions_monthyear, + (submission_counts.submission_count_assignedto + enquiry_counts.enquiry_count_assignedto) AS total_submissions_assignedto, + (submission_counts.intake_submitted_submission_count + enquiry_counts.intake_submitted_enquiry_count) AS intake_submitted, + (submission_counts.intake_assigned_submission_count + enquiry_counts.intake_assigned_enquiry_count) AS intake_assigned, + (submission_counts.intake_completed_submission_count + enquiry_counts.intake_completed_enquiry_count) AS intake_completed, + (submission_counts.state_new_submission_count) AS state_new, + (submission_counts.state_inprogress_submission_count) AS state_inprogress, + (submission_counts.state_delayed_submission_count) AS state_delayed, + (submission_counts.state_completed_submission_count) AS state_completed, + (submission_counts.supported_bc_submission_count) AS supported_bc, + (submission_counts.supported_indigenous_submission_count) AS supported_indigenous, + (submission_counts.supported_non_profit_submission_count) AS supported_non_profit, + (submission_counts.supported_housing_coop_submission_count) AS supported_housing_coop, + (submission_counts.waiting_on_submission_count + enquiry_counts.waiting_on_enquiry_count) AS waiting_on, + (submission_counts.queue_1_submission_count) AS queue_1, + (submission_counts.queue_2_submission_count) AS queue_2, + (submission_counts.queue_3_submission_count) AS queue_3, + (enquiry_counts.escalation_enquiry_count) AS escalation, + (enquiry_counts.general_enquiry_count) AS general_enquiry, + (submission_counts.guidance_submission_count) AS guidance, + (submission_counts.inapplicable_submission_count + enquiry_counts.inapplicable_enquiry_count) AS inapplicable, + (enquiry_counts.status_request_enquiry_count) AS status_request + from submission_counts, enquiry_counts; + end; $$`) + ) + // Drop yars views .then(() => knex.schema.withSchema('yars').dropViewIfExists('group_role_policy_vw')) diff --git a/app/src/routes/v1/permit.ts b/app/src/routes/v1/permit.ts index 16866fbb..049a0d18 100644 --- a/app/src/routes/v1/permit.ts +++ b/app/src/routes/v1/permit.ts @@ -14,6 +14,16 @@ const router = express.Router(); router.use(requireSomeAuth); router.use(requireSomeGroup); +// Permit list endpoint +router.get( + '/', + hasAuthorization(Resource.PERMIT, Action.READ), + permitValidator.listPermits, + (req: Request, res: Response, next: NextFunction): void => { + permitController.listPermits(req, res, next); + } +); + // Permit create endpoint router.put( '/', @@ -46,16 +56,6 @@ router.delete( } ); -// Permit list by activity endpoint -router.get( - '/list/:activityId', - hasAuthorization(Resource.PERMIT, Action.READ), - permitValidator.listPermits, - (req: Request, res: Response, next: NextFunction): void => { - permitController.listPermits(req, res, next); - } -); - // Permit types endpoint router.get( '/types', diff --git a/app/src/services/permit.ts b/app/src/services/permit.ts index 2a7063c8..802dce18 100644 --- a/app/src/services/permit.ts +++ b/app/src/services/permit.ts @@ -99,17 +99,17 @@ const service = { /** * @function listPermits - * Retrieve a list of permits associated with a given activity + * Retrieve all permits if no activityId is provided, otherwise retrieve permits for a specific activity * @param {string} activityId PCNS Activity ID * @returns {Promise} The result of running the findMany operation */ - listPermits: async (activityId: string) => { + listPermits: async (activityId?: string) => { const response = await prisma.permit.findMany({ include: { permit_type: true }, where: { - activity_id: activityId + activity_id: activityId ? activityId : undefined }, orderBy: { permit_type: { diff --git a/app/src/validators/permit.ts b/app/src/validators/permit.ts index f86a9987..cf1f8341 100644 --- a/app/src/validators/permit.ts +++ b/app/src/validators/permit.ts @@ -28,8 +28,8 @@ const schema = { }) }, listPermits: { - params: Joi.object({ - activityId: activityId + query: Joi.object({ + activityId: Joi.string().min(8).max(8).allow(null) }) }, updatePermit: { diff --git a/app/tests/unit/controllers/permit.spec.ts b/app/tests/unit/controllers/permit.spec.ts index 8eacd446..7e8ae857 100644 --- a/app/tests/unit/controllers/permit.spec.ts +++ b/app/tests/unit/controllers/permit.spec.ts @@ -249,7 +249,7 @@ describe('listPermits', () => { it('should return 200 if all good', async () => { const now = new Date(); const req = { - params: { activityId: 'ACT_ID' }, + query: { activityId: 'ACT_ID' }, currentContext: CURRENT_CONTEXT }; @@ -275,14 +275,14 @@ describe('listPermits', () => { await permitController.listPermits(req as any, res as any, next); expect(listSpy).toHaveBeenCalledTimes(1); - expect(listSpy).toHaveBeenCalledWith(req.params.activityId); + expect(listSpy).toHaveBeenCalledWith(req.query.activityId); expect(res.status).toHaveBeenCalledWith(200); expect(res.json).toHaveBeenCalledWith(permitList); }); it('calls next if the permit service fails to list permits', async () => { const req = { - params: { activityId: 'ACT_ID' }, + query: { activityId: 'ACT_ID' }, currentContext: CURRENT_CONTEXT }; @@ -294,7 +294,7 @@ describe('listPermits', () => { await permitController.listPermits(req as any, res as any, next); expect(listSpy).toHaveBeenCalledTimes(1); - expect(listSpy).toHaveBeenCalledWith(req.params.activityId); + expect(listSpy).toHaveBeenCalledWith(req.query.activityId); expect(res.status).toHaveBeenCalledTimes(0); expect(next).toHaveBeenCalledTimes(1); }); diff --git a/frontend/src/components/housing/submission/SubmissionListNavigator.vue b/frontend/src/components/housing/submission/SubmissionListNavigator.vue index 72480950..801afe49 100644 --- a/frontend/src/components/housing/submission/SubmissionListNavigator.vue +++ b/frontend/src/components/housing/submission/SubmissionListNavigator.vue @@ -239,7 +239,13 @@ function isFinanciallySupported(data: Submission) { style="min-width: 125px" /> + {{ statistics.total_submissions }} {{ getPercentage(statistics.total_submissions) }}% + + Multi-authorization projects + {{ statistics.multi_permits_needed }} + {{ getPercentage(statistics.multi_permits_needed) }}% + Submissions by range diff --git a/frontend/src/components/housing/submission/SubmissionsNavigator.vue b/frontend/src/components/housing/submission/SubmissionsNavigator.vue index 89145084..ba3da863 100644 --- a/frontend/src/components/housing/submission/SubmissionsNavigator.vue +++ b/frontend/src/components/housing/submission/SubmissionsNavigator.vue @@ -9,15 +9,15 @@ import SubmissionBringForwardCalendar from '@/components/housing/submission/Subm import SubmissionListNavigator from '@/components/housing/submission/SubmissionListNavigator.vue'; import SubmissionStatistics from '@/components/housing/submission/SubmissionStatistics.vue'; import { Accordion, AccordionTab, TabPanel, TabView, useToast } from '@/lib/primevue'; -import { enquiryService, noteService, submissionService } from '@/services'; +import { enquiryService, noteService, permitService, submissionService } from '@/services'; import { useAuthNStore, useAuthZStore } from '@/store'; -import { Action, Initiative, Resource, RouteName, StorageKey } from '@/utils/enums/application'; +import { Action, BasicResponse, Initiative, Resource, RouteName, StorageKey } from '@/utils/enums/application'; import { SubmissionType } from '@/utils/enums/housing'; import { BringForwardType, IntakeStatus } from '@/utils/enums/housing'; import { formatDate } from '@/utils/formatters'; import type { Ref } from 'vue'; -import type { BringForward, Enquiry, Statistics, Submission } from '@/types'; +import type { BringForward, Enquiry, Permit, Statistics, Submission } from '@/types'; // Constants const NOTES_TAB_INDEX = { @@ -37,6 +37,7 @@ const bringForward: Ref> = ref([]); const enquiries: Ref> = ref([]); const myBringForward: Ref> = ref([]); const myAssignedTo: Ref> = ref(new Set()); +const permits: Ref> = ref([]); const loading: Ref = ref(true); const submissions: Ref> = ref([]); const statistics: Ref = ref(undefined); @@ -95,9 +96,10 @@ onMounted(async () => { // To pull data from CHEFS await submissionService.getSubmissions(); - [enquiries.value, submissions.value, statistics.value, bringForward.value] = ( + [enquiries.value, permits.value, submissions.value, statistics.value, bringForward.value] = ( await Promise.all([ enquiryService.getEnquiries(), + permitService.listPermits(), submissionService.searchSubmissions({ includeUser: true, intakeStatus: [IntakeStatus.ASSIGNED, IntakeStatus.COMPLETED, IntakeStatus.SUBMITTED] @@ -108,6 +110,7 @@ onMounted(async () => { ).map((r) => r.data); assignEnquiriesAndFullName(); + assignMultiPermitsNeeded(); const profile = getProfile.value; @@ -170,6 +173,19 @@ function assignEnquiriesAndFullName() { }); } +// Set multiPermitsNeeded property of each submission to Yes/No (count) +// if the submission have more than one permit with needed Yes +function assignMultiPermitsNeeded() { + submissions.value.forEach((sub) => { + const multiPermitsNeededCount = permits.value.filter( + (x) => x.activityId === sub.activityId && x.needed?.toUpperCase() === BasicResponse.YES.toUpperCase() + ).length; + + if (multiPermitsNeededCount > 1) sub.multiPermitsNeeded = `${BasicResponse.YES} (${multiPermitsNeededCount})`; + else sub.multiPermitsNeeded = BasicResponse.NO; + }); +} + watch(accordionIndex, () => { if (accordionIndex.value !== null) { window.sessionStorage.setItem(StorageKey.BF_ACCORDION_IDX, accordionIndex.value.toString()); diff --git a/frontend/src/services/permitService.ts b/frontend/src/services/permitService.ts index 4029efd7..c2c00a13 100644 --- a/frontend/src/services/permitService.ts +++ b/frontend/src/services/permitService.ts @@ -31,8 +31,8 @@ export default { * @function listPermits * @returns {Promise} An axios response */ - async listPermits(activityId: string) { - return appAxios().get(`permit/list/${activityId}`); + async listPermits(activityId?: string) { + return appAxios().get('permit', { params: { activityId } }); }, /** diff --git a/frontend/src/types/Statistics.ts b/frontend/src/types/Statistics.ts index 24ee9fce..6cd1551c 100644 --- a/frontend/src/types/Statistics.ts +++ b/frontend/src/types/Statistics.ts @@ -6,6 +6,7 @@ export type Statistics = { intake_submitted: number; intake_assigned: number; intake_completed: number; + multi_permits_needed: number; state_new: number; state_inprogress: number; state_delayed: number; diff --git a/frontend/src/types/Submission.ts b/frontend/src/types/Submission.ts index 7c752b5c..ef8e5dfc 100644 --- a/frontend/src/types/Submission.ts +++ b/frontend/src/types/Submission.ts @@ -23,6 +23,7 @@ export type Submission = { projectLocationDescription: string; singleFamilyUnits: string; multiFamilyUnits: string; + multiPermitsNeeded: string; otherUnitsDescription: string; otherUnits: string; hasRentalUnits: string; diff --git a/frontend/tests/unit/service/permitService.spec.ts b/frontend/tests/unit/service/permitService.spec.ts index bdf3bff4..b807b6fc 100644 --- a/frontend/tests/unit/service/permitService.spec.ts +++ b/frontend/tests/unit/service/permitService.spec.ts @@ -71,7 +71,7 @@ describe('permitService test', () => { it('calls get permit list', async () => { await permitService.listPermits(TEST_ID); expect(getSpy).toHaveBeenCalledTimes(1); - expect(getSpy).toHaveBeenCalledWith(`${PATH}/list/${TEST_ID}`); + expect(getSpy).toHaveBeenCalledWith(`${PATH}`, { params: { activityId: TEST_ID } }); }); it('calls get permit list with wrong ID', async () => {