Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stale case data #768

Merged
merged 124 commits into from
Aug 3, 2023
Merged
Changes from 1 commit
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
f8654c3
chore: add eslint unused import plugin to projects seperately (#425)
AfaqShuaib09 May 29, 2023
40b9437
feat(generated assignee-asigned-guard): assign endpoint (#451)
Blokh Jun 6, 2023
e627d71
Blokh/feat/backoffice image (#505)
Blokh Jun 6, 2023
13a4924
added logo url
Blokh Jun 6, 2023
cecbc7f
fix image logo by updating name to VITE_IMAGE_LOGO_URL
Blokh Jun 6, 2023
fb72c45
refactor(db-schema): remove enduser unneccesary fields (#508)
alonp99 Jun 7, 2023
39b099b
fixed document props update
alonp99 Jun 7, 2023
969a655
backoffice: fixed addtional info on entity
alonp99 Jun 7, 2023
8d4ef04
add ajv keywords
alonp99 Jun 7, 2023
32194e2
update pnpm lock file
alonp99 Jun 7, 2023
c8762aa
Create SECURITY.md (#513)
alonp99 Jun 7, 2023
db18f37
fix pdf view in backoffice
alonp99 Jun 8, 2023
7ffca00
fix(backoffice-v2): fixed height for image viewer - addresses how pdf…
Omri-Levy Jun 8, 2023
2a651aa
Blokh/feat/default case filter assignee (#480)
Blokh Jun 8, 2023
527df40
update doc type (#515)
alonp99 Jun 8, 2023
98ce0a5
updated common reference
Blokh Jun 8, 2023
a8abf08
update common versions
alonp99 Jun 8, 2023
ca83511
fix: upgrade @astrojs/mdx from 0.18.4 to 0.19.2 (#518)
alonp99 Jun 10, 2023
24d5603
fix: upgrade @ballerine/common from 0.4.3 to 0.4.4 (#519)
alonp99 Jun 10, 2023
07d8021
update pnpm lock file
alonp99 Jun 10, 2023
09c9d42
backoffice signin logo regression fix
alonp99 Jun 10, 2023
2817ec7
added test env ci
alonp99 Jun 12, 2023
7894109
Cases pagination, sorting, filtering, and search (#516)
MatanYadaev Jun 13, 2023
78fa77a
feat: create workflows websocket service (#499)
TzlilSwimmer123 Jun 13, 2023
f366cf4
feat(vite.config.ts): added sourcemaps
Omri-Levy Jun 13, 2023
9ef1158
update common
alonp99 Jun 13, 2023
d2598bf
Blokh/fix/refactor update category (#517)
Blokh Jun 14, 2023
4b6b32a
Blokh/feat/test infra (#500)
Blokh Jun 14, 2023
06ae2d4
feat: added handling of prisma validation errors to workflow controll…
chesterkmr Jun 14, 2023
0dacb3a
add kyb w/ external request (#541)
alonp99 Jun 17, 2023
e41846c
fix(backoffice-v2): fixed document type resetting to "undefined"
Omri-Levy Jun 18, 2023
a02b886
fix(*): no longer using hardcoded propertiesSchema
Omri-Levy Jun 18, 2023
d1b9296
update common lib
alonp99 Jun 18, 2023
9810ab0
feat(workflow-def): enable mulitple active workflows
alonp99 Jun 18, 2023
8899fcd
update pnpm lock
alonp99 Jun 18, 2023
6b4dc4f
updated cookie secure to false for testing
Blokh Jun 18, 2023
52e220c
added secure proxy to cookie logic
Blokh Jun 18, 2023
b987c0d
added trust proxy key to app
Blokh Jun 18, 2023
d24467d
added trust proxy key to app
Blokh Jun 18, 2023
dd87e6e
added trust proxy key to app
Blokh Jun 18, 2023
5c3f637
reverted unnecessary changes
Blokh Jun 18, 2023
6a3f87b
reverted unnecessary changes
Blokh Jun 18, 2023
73fd998
added secureProxy
Blokh Jun 18, 2023
428aa5f
removed secured of cookie
Blokh Jun 18, 2023
af68fe9
updated removed http only
Blokh Jun 18, 2023
31bb1b9
added secured false
Blokh Jun 18, 2023
ce8648e
remove cookie domaun
alonp99 Jun 18, 2023
94b1f48
WIP - Headless example fix (#510)
Omri-Levy Jun 19, 2023
307a5aa
fix conflicts
alonp99 Jun 19, 2023
6c91250
fix(swagger): dont open swagger in dev/prod (#533)
alonp99 Jun 20, 2023
7cf1a60
add timestamps to workflow webhooks (#561)
alonp99 Jun 20, 2023
76ca3ec
fix(docs): update astro (#565)
alonp99 Jun 20, 2023
0eda114
refactor(*): GET /workflows per entity instead of query params (#558)
Omri-Levy Jun 20, 2023
90ace1c
fix(webhooks): fix resolved ata (#574)
alonp99 Jun 21, 2023
520a44d
refactor(backoffice-v2): merged re-submit and reject into a single di…
Omri-Levy Jun 21, 2023
b13e054
feat(backoffice-v2): added rotate button to selected image (#576)
Omri-Levy Jun 21, 2023
2e94009
feat(backoffice-v2): added a content block to display plugin output (…
Omri-Levy Jun 22, 2023
f6df3fd
Updated pluginOutput to pluginsOutput (#582)
Omri-Levy Jun 22, 2023
2f5be20
Backoffice - Zoom document images (#575)
Omri-Levy Jun 22, 2023
c8817d9
Backoffice - feedback updates (#583)
Omri-Levy Jun 22, 2023
6a82f2d
Backoffice - Entity address + map block (#584)
Omri-Levy Jun 22, 2023
cff7e52
Docs site sturcutre changes (#580)
alonp99 Jun 22, 2023
8343bde
Update simple-kyb-guide.mdx (#586)
nitzanballerine Jun 23, 2023
d6417e1
Tech/feat/dynamic workflows (#538)
Blokh Jun 23, 2023
06746a1
update docs
alonp99 Jun 23, 2023
cbb6b29
update docs
alonp99 Jun 23, 2023
2c8730f
adding helm, dev
alonp99 Jun 23, 2023
78d93b0
update docs
alonp99 Jun 23, 2023
27ea2a5
update docs
alonp99 Jun 23, 2023
a515cfc
workflows dashboard (#567)
alonp99 Jun 23, 2023
bb494ab
update docs
alonp99 Jun 23, 2023
f89a176
update workflows dashboard name
alonp99 Jun 23, 2023
fbf844d
fix: fixed websocket-service path in init script (#594)
chesterkmr Jun 24, 2023
0a114e1
Illia rudniev/feat/winston logger (#544)
chesterkmr Jun 26, 2023
d93e8bd
feat: updated jq with jmespath (#600)
Blokh Jun 27, 2023
d5e8458
Blokh/feat/plugins documentation (#611)
Blokh Jun 28, 2023
9b5c6c7
fix(docs): fixed docs (#612)
alonp99 Jun 28, 2023
a030e41
Illia rudniev/feat/overview page and charts (#596)
chesterkmr Jun 28, 2023
6ace54c
refactor: refactored way of aquiring entity type & removed entity fro…
chesterkmr Jun 28, 2023
4962d42
fix(docs): add plugins section (#613)
alonp99 Jun 28, 2023
08428bb
test(headless-example): added an e2e smoke test - catches instances o…
Omri-Levy Jun 28, 2023
206e604
Illia rudniev/feat/workflow dashboard auth (#602)
chesterkmr Jun 29, 2023
d20a979
blokh/feat/definition-validator (#608)
Blokh Jun 29, 2023
39cc043
feat: implemented user activity tracker middleware & tests, connected…
chesterkmr Jul 1, 2023
e95b9c5
Fix headless-exampe 401 unauthorized errors (#624)
Omri-Levy Jul 2, 2023
41f62ab
Disable ability to change assignment on a case with a decision (#622)
Omri-Levy Jul 2, 2023
cd53458
Alphanumeric doc number (#623)
Omri-Levy Jul 2, 2023
1100d59
feat(backoffice-v2): added a comment field for reject/revision reason…
Omri-Levy Jul 3, 2023
7e99d5f
fix: fixed workflow dashboard port in env.example (#634)
chesterkmr Jul 3, 2023
14ce181
Illia rudniev/feat/wf runtimes page metrics (#626)
chesterkmr Jul 4, 2023
a43667f
add staging image publish
alonp99 Jul 4, 2023
2cd89a2
exper
alonp99 Jul 4, 2023
6ab0329
fix: fixed imports & added preview port to vite config (#647)
chesterkmr Jul 6, 2023
fa979a7
fix(webhook-handler): null check on document changed (#648)
alonp99 Jul 6, 2023
b610b1f
add: github actions to build & push docker images (#664)
pratapalakshmi Jul 10, 2023
0494828
Revert "add: github actions to build & push docker images (#664)"
alonp99 Jul 10, 2023
7362047
feat(schema): schema changes for kyb (#630)
alonp99 Jul 10, 2023
9f4c4a1
refactor: metric moved to different module & renamed endpoints & fixe…
chesterkmr Jul 10, 2023
585b20a
feat(doc-schemas): add mtn statement (#672)
alonp99 Jul 11, 2023
19fc64d
keep the values up to date docker-compose.yml (#646)
pratapalakshmi Jul 12, 2023
1f0bd1c
fix: added biging serialization & updated models & FE types (#675)
chesterkmr Jul 12, 2023
aadd5fd
feat(docs): add docs schema type (#676)
alonp99 Jul 12, 2023
75b224d
fix: fixed wf processing stats queries, added missing key to user res…
chesterkmr Jul 12, 2023
0c5683c
update default context schema
alonp99 Jul 12, 2023
4023c92
fix: removed grouping from approval rate quer & review time query now…
chesterkmr Jul 13, 2023
d4e63a1
alonp/fix/default context to js (#682)
alonp99 Jul 13, 2023
1b824b7
Illia rudniev/feat/react UI lib (#666)
chesterkmr Jul 13, 2023
0cd2be2
Authentication layouts using react-router-dom (#617)
Omri-Levy Jul 16, 2023
f15a5d7
publish ui package (#692)
alonp99 Jul 17, 2023
2a3ce3f
fix(*): renamed lib to dist (#693)
Omri-Levy Jul 17, 2023
dc5d81b
publish ui package
alonp99 Jul 17, 2023
0c5693f
Illia rudniev/fix/active agents stats (#697)
chesterkmr Jul 17, 2023
d5c710a
fix(editabledetails): fixes status not updating from revision to appr…
Omri-Levy Jul 22, 2023
1fceb59
Revert "fix(editabledetails): fixes status not updating from revision…
alonp99 Jul 23, 2023
b1ccffe
lock ballerine node package
alonp99 Jul 23, 2023
2128b98
lock ballerine node package
alonp99 Jul 23, 2023
3f56d45
feat(db): add plv8 (#727)
alonp99 Jul 27, 2023
813c63d
fix(postgres): change volume to avoid conflicts with all setup
alonp99 Jul 27, 2023
839df7b
feat(documents-schema): added now doc schema (#754)
alonp99 Aug 2, 2023
34e6e38
change document type
alonp99 Aug 2, 2023
bcd20f4
fix: remove @ballerine/ui from build (#758)
tomer-shvadron Aug 2, 2023
babb1c9
fix(document schemas): fixed typo of regestration
Omri-Levy Aug 2, 2023
542c0d6
fix(gh.ts): renamed businessName to companyName, and removed alphaNum…
Omri-Levy Aug 3, 2023
a6b2d91
fix(backoffice-v2): no longer sharing data between cases (different w…
Omri-Levy Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: added biging serialization & updated models & FE types (#675)
* fix: added biging serialization & updated models & FE types

* feat: updated metrics agent cases & cases per status to all time stats & updated endpoints & sql
chesterkmr authored Jul 12, 2023
commit 1f0bd1c56b6bed21be92666fe2c3135a3046568c
Original file line number Diff line number Diff line change
@@ -3,15 +3,26 @@ import {
GetUserStatsDto,
IResolvedCasesDailyMetric,
IUserStats,
UserStats,
} from '@app/domains/user/api/user-stats/user-stats.types';
import { request } from '@app/lib/request';

export const fetchUserStats = async (query: GetUserStatsDto): Promise<IUserStats> => {
export const fetchUserStats = async (query: GetUserStatsDto): Promise<UserStats> => {
const result = await request.get<IUserStats>(`/metrics/users/workflow-processing-statistic`, {
params: query,
});

return result.data;
const { approvalRate, averageAssignmentTime, averageResolutionTime, averageReviewTime } =
result.data || ({} as IUserStats);

const userStats: UserStats = {
approvalRate: approvalRate,
averageAssignmentTime: Number(averageAssignmentTime),
averageResolutionTime: Number(averageResolutionTime),
averageReviewTime: Number(averageReviewTime),
};

return userStats;
};

export const fetchUserDailyCasesResolvedStats = async (
Original file line number Diff line number Diff line change
@@ -4,6 +4,13 @@ export interface IResolvedCasesDailyMetric {
}

export interface IUserStats {
approvalRate: number;
averageResolutionTime: string;
averageAssignmentTime: string;
averageReviewTime: string;
}

export interface UserStats {
approvalRate: number;
averageResolutionTime: number;
averageAssignmentTime: number;
Original file line number Diff line number Diff line change
@@ -11,5 +11,5 @@ export interface GetUsersCaseResolvingStats {
}

export interface GetUsersAssignedCasesStatsDto {
fromDate: number;
fromDate?: number;
}
Original file line number Diff line number Diff line change
@@ -17,5 +17,5 @@ export type ICasesPerStatusStats = Record<IWorkflowStatus, number>;

export interface GetCasesPerStatusDto {
// UNIX timestamp
fromDate: number;
fromDate?: number;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IUserStats } from '@app/domains/user/api/user-stats';
import { UserStats as IUserStats } from '@app/domains/user/api/user-stats';
import { DurationCard } from '@app/pages/Overview/components/molecules/UserStats/components/DurationCard';
import { PercentageCard } from '@app/pages/Overview/components/molecules/UserStats/components/PercentageCard';

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dayjs from 'dayjs';
import { IUserStats, userStatsQueryKeys } from '@app/domains/user/api/user-stats';
import { UserStats, userStatsQueryKeys } from '@app/domains/user/api/user-stats';
import { useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';

const defaultValues: IUserStats = {
const defaultValues: UserStats = {
approvalRate: 0,
averageResolutionTime: 0,
averageReviewTime: 0,
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@ export const AgentCasesChart = memo(({ isLoading, data }: Props) => {
return (
<MetricListChart
title="Assigned Cases per agent"
description="( last 1 hour )"
isLoading={isLoading}
items={chartItems}
emptyPlaceholder={<div className="text-sm font-medium">No active cases.</div>}
Original file line number Diff line number Diff line change
@@ -28,11 +28,6 @@ export const CasesPerStatusChart = ({ isLoading, data }: Props) => {
);

return (
<MetricListChart
title="Amount of cases per status"
description="( last 1 hour )"
isLoading={isLoading}
items={chartItems}
/>
<MetricListChart title="Amount of cases per status" isLoading={isLoading} items={chartItems} />
);
};
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ export const useUsersAssignedCasesStatsQuery = () => {
const { filters } = useWorkflowFilters();
const { data, isLoading } = useQuery({
...usersStatsQueryKeys.casesAssignedStats({
fromDate: filters.fromDate!,
// fromDate: filters.fromDate!,
}),
enabled: Boolean(filters.fromDate),
});
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { ICasesPerStatusStats } from '@app/domains/workflows/api/workflow-metrics';
import { workflowMetricsKeys } from '@app/domains/workflows/api/workflow-metrics/query-keys';
import { useWorkflowFilters } from '@app/pages/Workflows/components/providers/WorkflowsFiltersProvider/hooks/useWorkflowFilters';
import { useQuery } from '@tanstack/react-query';

export const useCasesPerStatusQuery = () => {
const { filters } = useWorkflowFilters();
const { data = { active: 0, completed: 0, failed: 0 } as ICasesPerStatusStats, isLoading } =
useQuery({
...workflowMetricsKeys.workflowCasesPerStatusStats({ fromDate: filters.fromDate! }),
enabled: Boolean(filters.fromDate),
...workflowMetricsKeys.workflowCasesPerStatusStats({}),
});

return {
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface BaseParams {
fromDate: Date;
fromDate?: Date;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { DateQueryParamsDto } from '@/metrics/common/dto/date-query-params.dto';
import { IsOptional } from 'class-validator';

export class GetUsersAssignedCasesStatisticDto extends DateQueryParamsDto {}
export class GetUsersAssignedCasesStatisticDto extends DateQueryParamsDto {
@IsOptional()
fromDate!: Date;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { DateQueryParamsDto } from '@/metrics/common/dto/date-query-params.dto';
import { IsOptional } from 'class-validator';

export class GetWorkflowRuntimesStatusCountDto extends DateQueryParamsDto {}
export class GetWorkflowRuntimesStatusCountDto extends DateQueryParamsDto {
@IsOptional()
fromDate!: Date;
}
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ import { IAggregateAverageResolutionTime } from '@/metrics/repository/types/aggr
import { GetUserAverageAssignmentTimeParams } from '@/metrics/repository/types/get-user-average-assignment-time.params';
import { IAggregateAverageAssignmentTime } from '@/metrics/repository/types/aggregate-average-assignment-time';
import { GetUserAverageReviewTimeParams } from '@/metrics/repository/types/get-user-average-review-time.params';
import { UserAverageReviewTimeModel } from '@/metrics/repository/models/user-average-review-time.model';
import { AverageReviewTimeModel } from '@/metrics/repository/models/average-review-time.model';
import { IAggregateAverageReviewTime } from '@/metrics/repository/types/aggregate-average-review-time';
import { ListUserCasesResolvedDailyParams } from '@/metrics/repository/types/list-user-cases-resolved-daily.params';
import { CasesResolvedInDay } from '@/metrics/repository/models/cases-resolved-daily.model';
@@ -139,14 +139,14 @@ export class MetricsRepository {

async getUserAverageReviewTime(
params: GetUserAverageReviewTimeParams,
): Promise<UserAverageReviewTimeModel | null> {
): Promise<AverageReviewTimeModel | null> {
const results = await this.prismaService.$queryRawUnsafe<IAggregateAverageReviewTime[]>(
aggregateAverageReviewTimeQuery,
params.fromDate,
params.userId,
);

return results.length ? plainToClass(UserAverageReviewTimeModel, results.at(-1)) : null;
return results.length ? plainToClass(AverageReviewTimeModel, results.at(-1)) : null;
}

async listCasesResolvedDaily(
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';

export class AverageAssignmentTimeModel {
@ApiProperty({ description: 'Average assignment time in milliseconds' })
time!: number;
@Transform(({ value }) => (!value ? 0 : value.split('.')[0]))
time!: string;
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,6 @@ import { Transform } from 'class-transformer';

export class AverageResolutionTimeModel {
@ApiProperty({ description: 'Average resolution time in milliseconds.' })
@Transform(({ value }) => (value === null ? 0 : value))
time!: number;
@Transform(({ value }) => (!value ? 0 : value.split('.')[0]))
time!: string;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';

export class UserAverageReviewTimeModel {
export class AverageReviewTimeModel {
@ApiProperty({ description: 'Average review time in milliseconds' })
@Transform(({ value }) => (value === null ? 0 : value))
time!: number;
@Transform(({ value }) => (!value ? 0 : value.split('.')[0]))
time!: string;
}
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@ select
when "createdAt" notnull and "assignedAt" notnull
then (extract(epoch from "assignedAt") - extract(epoch from "createdAt")) * 1000
else 0
end)::int as time
end)::bigint as time
from "WorkflowRuntimeData"
where "assigneeId" = "User".id
and "assignedAt" >= $1)
)::int as time
)::varchar as time
from
"User"
where
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@ select
when "createdAt" notnull and "resolvedAt" notnull
then (extract(epoch from "resolvedAt") - extract(epoch from "createdAt")) * 1000
else 0
end)::int as time
end)::bigint as time
from "WorkflowRuntimeData"
where "assigneeId" = "User".id
and "resolvedAt" >= $1)
)::int as time
)::varchar as time
from
"User"
where
Original file line number Diff line number Diff line change
@@ -5,11 +5,11 @@ select
when "resolvedAt" notnull and "assignedAt" notnull
then (extract(epoch from "resolvedAt") - extract(epoch from "assignedAt")) * 1000
else 0
end)::int as time
end)::bigint as time
from "WorkflowRuntimeData"
where "assigneeId" = "User".id
and "resolvedAt" >= $1)
)::int as time
)::varchar as time
from
"User"
where
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ inner join (
count(*) as "casesCount"
from
"WorkflowRuntimeData"
where "assignedAt" >= $1
where "assignedAt" >= coalesce($1, '1900-01-01'::timestamp)
group by "assigneeId"
) as agent_workflow_runtime on
agent_workflow_runtime."assigneeId" = "id"
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ from
count("status") as status_count
from
"WorkflowRuntimeData"
where "createdAt" >= $1
where "createdAt" >= coalesce($1, '1900-01-01'::timestamp)
group by
"status"
) as workflow_runtime_data`;
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface IAggregateAverageAssignmentTime {
time: number | null;
time: string | null;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface IAggregateAverageResolutionTime {
time: number | null;
time: string | null;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface IAggregateAverageReviewTime {
time: number | null;
time: string | null;
}
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@ export class MetricsService {
this.metricsRepository.getUserApprovalRate(commonParams),
this.metricsRepository.getUserAverageAssignmentTime(commonParams),
this.metricsRepository.getUserAverageResolutionTime(commonParams),

this.metricsRepository.getUserAverageReviewTime(commonParams),
]);

@@ -70,9 +71,9 @@ export class MetricsService {
}

statisticModel.approvalRate = approvalRateModel?.approvalRate || 0;
statisticModel.averageAssignmentTime = averageAssignmentTimeModel?.time || 0;
statisticModel.averageResolutionTime = averageResolutionTimeModel?.time || 0;
statisticModel.averageReviewTime = averageReviewTimeModel?.time || 0;
statisticModel.averageAssignmentTime = averageAssignmentTimeModel?.time || '0';
statisticModel.averageResolutionTime = averageResolutionTimeModel?.time || '0';
statisticModel.averageReviewTime = averageReviewTimeModel?.time || '0';

return statisticModel;
}
Original file line number Diff line number Diff line change
@@ -8,11 +8,11 @@ export class UserWorkflowProcessingStatisticModel {
approvalRate!: number;

@ApiProperty({ description: 'Average resolution time in milliseconds' })
averageResolutionTime!: number;
averageResolutionTime!: string;

@ApiProperty({ description: 'Average assignment time in milliseconds' })
averageAssignmentTime!: number;
averageAssignmentTime!: string;

@ApiProperty({ description: 'Average review time in milliseconds' })
averageReviewTime!: number;
averageReviewTime!: string;
}