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.UserMeta, 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, AddressCity: *req.City, AddressState: *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 } }