Skip to content
48 changes: 48 additions & 0 deletions src/app/http/referrals/referrals.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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<Referral>,
) {
if (startDate && endDate) {
queryBuilder.andWhere('referral.date BETWEEN :start AND :end', {
start: startDate,
end: endDate,
});
}

return queryBuilder;
}

const createQueryBuilder = (): SelectQueryBuilder<Referral> => {
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<CategoryTotalReferrals>(),
totalCategoriesQuery.getRawOne<{ total: string }>(),
]);

return {
categories,
total: Number(totalResult?.total || 0),
};
}
}
21 changes: 21 additions & 0 deletions src/app/http/statistics/statistics.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
GetPatientsByGenderResponse,
GetReferredPatientsByStateResponse,
GetTotalReferralsAndReferredPatientsPercentageResponse,
GetTotalReferralsByCategoryResponse,
PatientsByCity,
PatientsByGender,
} from '@/domain/schemas/statistics';
Expand All @@ -15,6 +16,7 @@ import {
GetPatientsByPeriodQuery,
GetReferredPatientsByStateQuery,
GetTotalReferralsAndReferredPatientsPercentageQuery,
GetTotalReferralsByCategoryQuery,
} from './statistics.dtos';
import { StatisticsService } from './statistics.service';

Expand Down Expand Up @@ -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<GetTotalReferralsByCategoryResponse> {
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({
Expand Down
5 changes: 5 additions & 0 deletions src/app/http/statistics/statistics.dtos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getPatientsByPeriodQuerySchema,
getReferredPatientsByStateQuerySchema,
getTotalReferralsAndReferredPatientsPercentageQuerySchema,
getTotalReferralsByCategoryQuerySchema,
} from '@/domain/schemas/statistics';

export class GetPatientsByPeriodQuery extends createZodDto(
Expand All @@ -14,6 +15,10 @@ export class GetTotalReferralsAndReferredPatientsPercentageQuery extends createZ
getTotalReferralsAndReferredPatientsPercentageQuerySchema,
) {}

export class GetTotalReferralsByCategoryQuery extends createZodDto(
getTotalReferralsByCategoryQuerySchema,
) {}

export class GetReferredPatientsByStateQuery extends createZodDto(
getReferredPatientsByStateQuerySchema,
) {}
15 changes: 15 additions & 0 deletions src/app/http/statistics/statistics.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Injectable } from '@nestjs/common';

import type {
CategoryTotalReferrals,
GetTotalPatientsByStatusResponse,
PatientsStatisticField,
StateReferredPatients,
Expand All @@ -13,6 +14,7 @@ import type {
GetPatientsByPeriodQuery,
GetReferredPatientsByStateQuery,
GetTotalReferralsAndReferredPatientsPercentageQuery,
GetTotalReferralsByCategoryQuery,
} from './statistics.dtos';

@Injectable()
Expand Down Expand Up @@ -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 }> {
Expand Down
24 changes: 24 additions & 0 deletions src/domain/schemas/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
>;