diff --git a/src/app/http/referrals/referrals.repository.ts b/src/app/http/referrals/referrals.repository.ts index 420b1f0..61ee69d 100644 --- a/src/app/http/referrals/referrals.repository.ts +++ b/src/app/http/referrals/referrals.repository.ts @@ -6,10 +6,12 @@ import { LessThanOrEqual, MoreThanOrEqual, Repository, + type SelectQueryBuilder, } from 'typeorm'; import { Referral } from '@/domain/entities/referral'; import { ReferralStatus } from '@/domain/schemas/referral'; +import type { CategoryTotalReferrals } from '@/domain/schemas/statistics'; import { CreateReferralDto } from './referrals.dtos'; @@ -67,4 +69,50 @@ export class ReferralsRepository { return await this.referralsRepository.count({ where }); } + + public async getTotalReferralsByCategory( + input: { startDate?: Date; endDate?: Date; limit?: number } = {}, + ): Promise<{ categories: CategoryTotalReferrals[]; total: number }> { + const { startDate, endDate, limit = 10 } = input; + + function getQueryBuilderWithFilters( + queryBuilder: SelectQueryBuilder, + ) { + if (startDate && endDate) { + queryBuilder.andWhere('referral.date BETWEEN :start AND :end', { + start: startDate, + end: endDate, + }); + } + + return queryBuilder; + } + + const createQueryBuilder = (): SelectQueryBuilder => { + return this.referralsRepository.createQueryBuilder('referral'); + }; + + const categoryListQuery = getQueryBuilderWithFilters( + createQueryBuilder() + .select('referral.category', 'category') + .addSelect('COUNT(referral.id)', 'total') + .groupBy('referral.category') + .orderBy('COUNT(referral.id)', 'DESC') + .limit(limit), + ); + + const totalCategoriesQuery = getQueryBuilderWithFilters( + createQueryBuilder().select('COUNT(DISTINCT referral.category)', 'total'), + ); + + const [categories, totalResult] = await Promise.all([ + categoryListQuery.getRawMany(), + totalCategoriesQuery.getRawOne<{ total: string }>(), + ]); + + return { + categories, + total: Number(totalResult?.total || 0), + }; + } } diff --git a/src/app/http/statistics/statistics.controller.ts b/src/app/http/statistics/statistics.controller.ts index b0aae11..271f910 100644 --- a/src/app/http/statistics/statistics.controller.ts +++ b/src/app/http/statistics/statistics.controller.ts @@ -7,6 +7,7 @@ import type { GetPatientsByGenderResponse, GetReferredPatientsByStateResponse, GetTotalReferralsAndReferredPatientsPercentageResponse, + GetTotalReferralsByCategoryResponse, PatientsByCity, PatientsByGender, } from '@/domain/schemas/statistics'; @@ -15,6 +16,7 @@ import { GetPatientsByPeriodQuery, GetReferredPatientsByStateQuery, GetTotalReferralsAndReferredPatientsPercentageQuery, + GetTotalReferralsByCategoryQuery, } from './statistics.dtos'; import { StatisticsService } from './statistics.service'; @@ -93,6 +95,25 @@ export class StatisticsController { }; } + @Get('referrals-by-category') + @Roles(['manager', 'nurse']) + @ApiOperation({ + summary: 'Lista com o total de encaminhamentos por categoria', + }) + async getTotalReferralsByCategory( + @Query() query: GetTotalReferralsByCategoryQuery, + ): Promise { + const { categories, total } = + await this.statisticsService.getTotalReferralsByCategory(query); + + return { + success: true, + message: + 'Lista com o total de encaminhamentos por categoria retornada com sucesso.', + data: { categories, total }, + }; + } + @Get('referrals-by-state') @Roles(['manager', 'nurse']) @ApiOperation({ diff --git a/src/app/http/statistics/statistics.dtos.ts b/src/app/http/statistics/statistics.dtos.ts index bd9861e..9004d2d 100644 --- a/src/app/http/statistics/statistics.dtos.ts +++ b/src/app/http/statistics/statistics.dtos.ts @@ -4,6 +4,7 @@ import { getPatientsByPeriodQuerySchema, getReferredPatientsByStateQuerySchema, getTotalReferralsAndReferredPatientsPercentageQuerySchema, + getTotalReferralsByCategoryQuerySchema, } from '@/domain/schemas/statistics'; export class GetPatientsByPeriodQuery extends createZodDto( @@ -14,6 +15,10 @@ export class GetTotalReferralsAndReferredPatientsPercentageQuery extends createZ getTotalReferralsAndReferredPatientsPercentageQuerySchema, ) {} +export class GetTotalReferralsByCategoryQuery extends createZodDto( + getTotalReferralsByCategoryQuerySchema, +) {} + export class GetReferredPatientsByStateQuery extends createZodDto( getReferredPatientsByStateQuerySchema, ) {} diff --git a/src/app/http/statistics/statistics.service.ts b/src/app/http/statistics/statistics.service.ts index bf63d73..7fa5ffd 100644 --- a/src/app/http/statistics/statistics.service.ts +++ b/src/app/http/statistics/statistics.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import type { + CategoryTotalReferrals, GetTotalPatientsByStatusResponse, PatientsStatisticField, StateReferredPatients, @@ -13,6 +14,7 @@ import type { GetPatientsByPeriodQuery, GetReferredPatientsByStateQuery, GetTotalReferralsAndReferredPatientsPercentageQuery, + GetTotalReferralsByCategoryQuery, } from './statistics.dtos'; @Injectable() @@ -69,6 +71,19 @@ export class StatisticsService { }; } + async getTotalReferralsByCategory( + query: GetTotalReferralsByCategoryQuery, + ): Promise<{ categories: CategoryTotalReferrals[]; total: number }> { + const { startDate, endDate } = this.utilsService.getDateRangeForPeriod( + query.period, + ); + + return await this.referralsRepository.getTotalReferralsByCategory({ + startDate, + endDate, + }); + } + async getReferredPatientsByState( query: GetReferredPatientsByStateQuery, ): Promise<{ states: StateReferredPatients[]; total: number }> { diff --git a/src/domain/schemas/statistics.ts b/src/domain/schemas/statistics.ts index f8e4348..1a35938 100644 --- a/src/domain/schemas/statistics.ts +++ b/src/domain/schemas/statistics.ts @@ -5,6 +5,7 @@ import { BRAZILIAN_STATES } from '@/constants/brazilian-states'; import { baseResponseSchema } from './base'; import { GENDERS } from './patient'; import { baseQuerySchema } from './query'; +import { REFERRAL_CATEGORIES } from './referral'; // Patients @@ -104,3 +105,26 @@ export const getReferredPatientsByStateResponseSchema = export type GetReferredPatientsByStateResponse = z.infer< typeof getReferredPatientsByStateResponseSchema >; + +export const getTotalReferralsByCategoryQuerySchema = baseQuerySchema.pick({ + period: true, +}); + +export const categoryTotalReferralsSchema = z.object({ + category: z.enum(REFERRAL_CATEGORIES), + total: z.number(), +}); +export type CategoryTotalReferrals = z.infer< + typeof categoryTotalReferralsSchema +>; + +export const getTotalReferralsByCategoryResponseSchema = + baseResponseSchema.extend({ + data: z.object({ + categories: z.array(categoryTotalReferralsSchema), + total: z.number(), + }), + }); +export type GetTotalReferralsByCategoryResponse = z.infer< + typeof getTotalReferralsByCategoryResponseSchema +>;