niki/patientapp/service/analytic/service.go

129 lines
3.7 KiB
Go

package analytic
import (
"context"
"errors"
"fmt"
"time"
analytic2 "git.gocasts.ir/ebhomengo/niki/patientapp/delivery/http/analytic/dto"
"git.gocasts.ir/ebhomengo/niki/patientapp/service/entity"
)
var (
ErrInvalidProvinceID = errors.New("invalid province id")
ErrInvalidCountryID = errors.New("invalid country id")
ErrInvalidMapLevel = errors.New("invalid map level")
)
type Repository interface {
GetPatients(ctx context.Context, f PatientFilter) ([]entity.Patient, error)
CountPatients(ctx context.Context, f PatientFilter) (int, error)
SummaryByCity(ctx context.Context, provinceID int, f PatientMapFilter) ([]entity.MapSummaryItem, error)
SummaryByProvince(ctx context.Context, countryID int, f PatientMapFilter) ([]entity.MapSummaryItem, error)
SummaryByCountry(ctx context.Context, f PatientMapFilter) ([]entity.MapSummaryItem, error)
}
type Service struct {
repository Repository
validator Validator
}
func NewPatientAnalyticService(repo Repository, validator Validator) Service {
return Service{
repository: repo,
validator: validator,
}
}
func (s Service) List(ctx context.Context, req analytic2.ListPatientAnalyticRequest) (analytic2.PatientAnalyticResponse, error) {
limit, offset := normalizeLimitOffset(req.Limit, req.Offset)
// convert age range
dobFrom, dobTo := ageRangeToDOB(req.MinAge, req.MaxAge, time.Now())
filter := PatientFilter{
DOBFrom: dobFrom,
DOBTo: dobTo,
Sex: req.Sex,
City: req.City,
Province: req.Province,
Search: req.Search,
Limit: limit,
Offset: offset,
}
items, err := s.repository.GetPatients(ctx, filter)
if err != nil {
return analytic2.PatientAnalyticResponse{}, fmt.Errorf("GetPatients: %w", err)
}
total, err := s.repository.CountPatients(ctx, filter)
if err != nil {
return analytic2.PatientAnalyticResponse{}, fmt.Errorf("CountPatients: %w", err)
}
// mapping response
out := make([]analytic2.PatientAnalyticItem, 0, len(items))
for _, value := range items {
out = append(out, analytic2.ToPatientResponse(value))
}
return analytic2.PatientAnalyticResponse{
Items: out,
Limit: limit,
Offset: offset,
Total: total,
}, nil
}
func (s Service) GetMapSummary(ctx context.Context, req analytic2.GetPatientMapSummaryRequest) (analytic2.GetPatientMapSummaryResponse, error) {
dobFrom, dobTo := ageRangeToDOB(req.MinAge, req.MaxAge, time.Now())
filter := PatientMapFilter{
MinDOB: dobFrom,
MaxDOB: dobTo,
Sex: req.Sex,
Search: req.Search,
}
switch req.Level {
case entity.MapLevelCity:
if req.ParentID == nil || *req.ParentID <= 0 {
return analytic2.GetPatientMapSummaryResponse{}, ErrInvalidProvinceID
}
items, err := s.repository.SummaryByCity(ctx, *req.ParentID, filter)
if err != nil {
return analytic2.GetPatientMapSummaryResponse{}, fmt.Errorf("SummaryByCity: %w", err)
}
return analytic2.GetPatientMapSummaryResponse{Level: req.Level, Items: items}, nil
case entity.MapLevelProvince:
if req.ParentID == nil || *req.ParentID <= 0 {
return analytic2.GetPatientMapSummaryResponse{}, ErrInvalidCountryID
}
items, err := s.repository.SummaryByProvince(ctx, *req.ParentID, filter)
if err != nil {
return analytic2.GetPatientMapSummaryResponse{}, fmt.Errorf("SummaryByProvince: %w", err)
}
return analytic2.GetPatientMapSummaryResponse{Level: req.Level, Items: items}, nil
case entity.MapLevelCountry:
items, err := s.repository.SummaryByCountry(ctx, filter)
if err != nil {
return analytic2.GetPatientMapSummaryResponse{}, fmt.Errorf("SummaryByCountry: %w", err)
}
return analytic2.GetPatientMapSummaryResponse{Level: req.Level, Items: items}, nil
default:
return analytic2.GetPatientMapSummaryResponse{}, ErrInvalidMapLevel
}
}