package repository import ( "electricity_bill_calc/cache" "electricity_bill_calc/global" "electricity_bill_calc/logger" "electricity_bill_calc/model" "github.com/doug-martin/goqu/v9" _ "github.com/doug-martin/goqu/v9/dialect/postgres" "github.com/georgysavva/scany/v2/pgxscan" "go.uber.org/zap" ) type _RegionRepository struct { log *zap.Logger ds goqu.DialectWrapper } var RegionRepository = _RegionRepository{ log: logger.Named("Repository", "Region"), ds: goqu.Dialect("postgres"), } // 获取指定行政区划下所有直接子级行政区划 func (r *_RegionRepository) FindSubRegions(parent string) ([]model.Region, error) { r.log.Info("获取指定行政区划下所有直接子级行政区划", zap.String("parent", parent)) cacheConditions := []string{ "parent", parent, } if regions, err := cache.RetrieveSearch[[]model.Region]("region", cacheConditions...); err == nil && regions != nil { r.log.Info("已经从缓存获取到了指定的子级行政区划。") return *regions, nil } ctx, cancel := global.TimeoutContext() defer cancel() var regions []model.Region regionQuerySql, regionParams, _ := r.ds. From("region"). Where(goqu.Ex{"parent": parent}). Prepared(true).ToSQL() if err := pgxscan.Select(ctx, global.DB, ®ions, regionQuerySql, regionParams...); err != nil { r.log.Error("获取指定行政区划下所有直接子级行政区划失败!", zap.Error(err)) return nil, err } if len(regions) > 0 { cache.CacheSearch(regions, []string{"region"}, "region", cacheConditions...) } return regions, nil } // 获取一个指定编号的行政区划详细信息 func (r *_RegionRepository) FindRegion(code string) (*model.Region, error) { r.log.Info("获取指定行政区划信息", zap.String("code", code)) if region, err := cache.RetrieveEntity[model.Region]("region", code); err == nil && region != nil { r.log.Info("已经从缓存获取到了指定的行政区划详细信息。") return region, nil } ctx, cancel := global.TimeoutContext() defer cancel() var region model.Region regionQuerySql, regionParams, _ := r.ds. From("region"). Where(goqu.Ex{"code": code}). Prepared(true).ToSQL() if err := pgxscan.Get(ctx, global.DB, ®ion, regionQuerySql, regionParams...); err != nil { r.log.Error("获取指定行政区划信息失败!", zap.Error(err)) return nil, err } cache.CacheEntity(region, []string{"region"}, "region", code) return ®ion, nil } // 获取指定行政区划的所有直接和非直接父级 func (r *_RegionRepository) FindParentRegions(code string) ([]*model.Region, error) { r.log.Info("获取指定行政区划的所有直接和非直接父级", zap.String("code", code)) cacheConditions := []string{ "parent", code, } if regions, err := cache.RetrieveSearch[[]*model.Region]("region", cacheConditions...); err == nil && regions != nil { r.log.Info("已经从缓存获取到了指定的父级行政区划。") return *regions, nil } var ( regionsScanTask = []string{code} regions = make([]*model.Region, 0) ) for len(regionsScanTask) > 0 { region, err := r.FindRegion(regionsScanTask[0]) regionsScanTask = append([]string{}, regionsScanTask[1:]...) if err == nil && region != nil { regions = append(regions, region) if region.Parent != "0" { regionsScanTask = append(regionsScanTask, region.Parent) } } } if len(regions) > 0 { cache.CacheSearch(regions, []string{"region"}, "region", cacheConditions...) } return regions, nil }