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 } }