forked from ebhomengo/niki
120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
package analytic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"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 uint, f PatientMapFilter) (map[uint][]entity.MapSummaryItem, error)
|
|
SummaryByProvince(ctx context.Context, f PatientMapFilter) (map[uint][]entity.MapSummaryItem, error)
|
|
}
|
|
|
|
type Service struct {
|
|
repository Repository
|
|
}
|
|
|
|
func NewPatientAnalyticService(repo Repository) Service {
|
|
return Service{
|
|
repository: repo,
|
|
}
|
|
}
|
|
|
|
func (s Service) List(ctx context.Context, req ListPatientAnalyticRequest) (PatientAnalyticResponse, error) {
|
|
|
|
limit, offset := normalizeLimitOffset(req.Pagination.Limit, req.Pagination.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 PatientAnalyticResponse{}, fmt.Errorf("GetPatients: %w", err)
|
|
}
|
|
|
|
total, err := s.repository.CountPatients(ctx, filter)
|
|
if err != nil {
|
|
return PatientAnalyticResponse{}, fmt.Errorf("CountPatients: %w", err)
|
|
}
|
|
|
|
// mapping response
|
|
out := make([]PatientAnalyticItem, 0, len(items))
|
|
for _, value := range items {
|
|
out = append(out, ToPatientResponse(value))
|
|
}
|
|
|
|
return PatientAnalyticResponse{
|
|
Items: out,
|
|
Pagination: &Pagination{
|
|
Limit: limit,
|
|
Offset: offset,
|
|
},
|
|
Total: total,
|
|
}, nil
|
|
|
|
}
|
|
|
|
func (s Service) GetMapSummary(ctx context.Context, req GetPatientMapSummaryRequest) (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 GetPatientMapSummaryResponse{}, ErrInvalidProvinceID
|
|
}
|
|
|
|
items, err := s.repository.SummaryByCity(ctx, uint(*req.ParentID), filter)
|
|
if err != nil {
|
|
return GetPatientMapSummaryResponse{}, fmt.Errorf("SummaryByCity: %w", err)
|
|
}
|
|
return GetPatientMapSummaryResponse{Level: req.Level, Items: items}, nil
|
|
|
|
case entity.MapLevelProvince:
|
|
if req.ParentID == nil || *req.ParentID <= 0 {
|
|
return GetPatientMapSummaryResponse{}, ErrInvalidCountryID
|
|
}
|
|
|
|
items, err := s.repository.SummaryByProvince(ctx, filter)
|
|
if err != nil {
|
|
return GetPatientMapSummaryResponse{}, fmt.Errorf("SummaryByProvince: %w", err)
|
|
}
|
|
return GetPatientMapSummaryResponse{Level: req.Level, Items: items}, nil
|
|
|
|
default:
|
|
return GetPatientMapSummaryResponse{}, ErrInvalidMapLevel
|
|
}
|
|
|
|
}
|