package repository import ( "context" "electricity_bill_calc/global" "electricity_bill_calc/logger" "electricity_bill_calc/model" "electricity_bill_calc/tools" "electricity_bill_calc/tools/serial" "electricity_bill_calc/types" "github.com/doug-martin/goqu/v9" _ "github.com/doug-martin/goqu/v9/dialect/postgres" "github.com/georgysavva/scany/v2/pgxscan" "github.com/jackc/pgx/v5" "go.uber.org/zap" ) type _ParkRepository struct { log *zap.Logger ds goqu.DialectWrapper } var ParkRepository = _ParkRepository{ log: logger.Named("Repository", "Park"), ds: goqu.Dialect("postgres"), } // 列出指定用户下的所有园区 func (pr _ParkRepository) ListAllParks(uid string) ([]*model.Park, error) { pr.log.Info("列出指定用户下的所有园区", zap.String("uid", uid)) ctx, cancel := global.TimeoutContext() defer cancel() var parks = make([]*model.Park, 0) parkQuerySql, parkParams, _ := pr.ds. From("park"). Select( "id", "user_id", "name", "area", "tenement_quantity", "capacity", "category", "meter_04kv_type", "region", "address", "contact", "phone", "enabled", "price_policy", "tax_rate", "basic_pooled", "adjust_pooled", "loss_pooled", "public_pooled", "created_at", "last_modified_at", "deleted_at", ). Where( goqu.I("user_id").Eq(uid), goqu.I("deleted_at").IsNull(), ). Order(goqu.I("created_at").Asc()). Prepared(true).ToSQL() if err := pgxscan.Select(ctx, global.DB, &parks, parkQuerySql, parkParams...); err != nil { pr.log.Error("列出指定用户下的所有园区失败!", zap.Error(err)) return make([]*model.Park, 0), err } return parks, nil } // 检查并确定指定园区的归属情况 func (pr _ParkRepository) IsParkBelongs(pid, uid string) (bool, error) { pr.log.Info("检查并确定指定园区的归属情况", zap.String("pid", pid), zap.String("uid", uid)) ctx, cancel := global.TimeoutContext() defer cancel() var count int64 parkQuerySql, parkParams, _ := pr.ds. From("park"). Select(goqu.COUNT("*")). Where( goqu.I("id").Eq(pid), goqu.I("user_id").Eq(uid), ). Prepared(true).ToSQL() if err := pgxscan.Get(ctx, global.DB, &count, parkQuerySql, parkParams...); err != nil { pr.log.Error("检查并确定指定园区的归属情况失败!", zap.Error(err)) return false, err } return count > 0, nil } // 创建一个属于指定用户的新园区。该创建功能不会对园区的名称进行检查。 func (pr _ParkRepository) CreatePark(ownerId string, park *model.Park) (bool, error) { pr.log.Info("创建一个属于指定用户的新园区", zap.String("ownerId", ownerId)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() serial.StringSerialRequestChan <- 1 code := serial.Prefix("P", <-serial.StringSerialResponseChan) createSql, createArgs, _ := pr.ds. Insert("park"). Cols( "id", "user_id", "name", "abbr", "area", "tenement_quantity", "capacity", "category", "meter_04kv_type", "region", "address", "contact", "phone", "enabled", "price_policy", "tax_rate", "basic_pooled", "adjust_pooled", "loss_pooled", "public_pooled", "created_at", "last_modified_at", ). Vals(goqu.Vals{ code, ownerId, park.Name, tools.PinyinAbbr(park.Name), park.Area, park.TenementQuantity, park.Capacity, park.Category, park.MeterType, park.Region, park.Address, park.Contact, park.Phone, park.Enabled, park.PricePolicy, park.TaxRate, park.BasicPooled, park.AdjustPooled, park.LossPooled, park.PublicPooled, timeNow, timeNow, }). Prepared(true).ToSQL() rs, err := global.DB.Exec(ctx, createSql, createArgs...) if err != nil { pr.log.Error("创建一个属于指定用户的新园区失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil } // 获取指定园区的详细信息 func (pr _ParkRepository) RetrieveParkDetail(pid string) (*model.Park, error) { pr.log.Info("获取指定园区的详细信息", zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() var park model.Park parkSql, parkArgs, _ := pr.ds. From("park"). Select( "id", "user_id", "name", "area", "tenement_quantity", "capacity", "category", "meter_04kv_type", "region", "address", "contact", "phone", "enabled", "price_policy", "tax_rate", "basic_pooled", "adjust_pooled", "loss_pooled", "public_pooled", "created_at", "last_modified_at", "deleted_at", ). Where(goqu.I("id").Eq(pid)). Prepared(true).ToSQL() if err := pgxscan.Get(ctx, global.DB, &park, parkSql, parkArgs...); err != nil { pr.log.Error("获取指定园区的详细信息失败!", zap.Error(err)) return nil, err } return &park, nil } // 获取园区对应的用户ID func (pr _ParkRepository) RetrieveParkBelongs(pid string) (string, error) { pr.log.Info("获取园区对应的用户ID", zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() var uid string parkSql, parkArgs, _ := pr.ds. From("park"). Select(goqu.I("user_id")). Where(goqu.I("id").Eq(pid)). Prepared(true).ToSQL() if err := pgxscan.Get(ctx, global.DB, &uid, parkSql, parkArgs...); err != nil { pr.log.Error("获取园区对应的用户ID失败!", zap.Error(err)) return "", err } return uid, nil } // 更新指定园区的信息 func (pr _ParkRepository) UpdatePark(pid string, park *model.Park) (bool, error) { pr.log.Info("更新指定园区的信息", zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park"). Set(goqu.Record{ "name": park.Name, "abbr": tools.PinyinAbbr(park.Name), "area": park.Area, "tenement_quantity": park.TenementQuantity, "capacity": park.Capacity, "category": park.Category, "meter_04kv_type": park.MeterType, "region": park.Region, "address": park.Address, "contact": park.Contact, "phone": park.Phone, "price_policy": park.PricePolicy, "tax_rate": park.TaxRate, "basic_pooled": park.BasicPooled, "adjust_pooled": park.AdjustPooled, "loss_pooled": park.LossPooled, "public_pooled": park.PublicPooled, "last_modified_at": timeNow, }). Where(goqu.I("id").Eq(pid)). Prepared(true).ToSQL() ok, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("更新指定园区的信息失败!", zap.Error(err)) return false, err } return ok.RowsAffected() > 0, nil } // 设定园区的可用状态 func (pr _ParkRepository) EnablingPark(pid string, enabled bool) (bool, error) { pr.log.Info("设定园区的可用状态", zap.String("pid", pid), zap.Bool("enabled", enabled)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park"). Set(goqu.Record{ "enabled": enabled, "last_modified_at": timeNow, }). Where(goqu.I("id").Eq(pid)). Prepared(true).ToSQL() ok, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("设定园区的可用状态失败!", zap.Error(err)) return false, err } return ok.RowsAffected() > 0, nil } // 删除指定园区(软删除) func (pr _ParkRepository) DeletePark(pid string) (bool, error) { pr.log.Info("删除指定园区(软删除)", zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park"). Set(goqu.Record{ "deleted_at": timeNow, "last_modified_at": timeNow, }). Where(goqu.I("id").Eq(pid)). Prepared(true).ToSQL() ok, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("删除指定园区(软删除)失败!", zap.Error(err)) return false, err } return ok.RowsAffected() > 0, nil } // 检索给定的园区详细信息列表 func (pr _ParkRepository) RetrieveParks(pids []string) ([]*model.Park, error) { pr.log.Info("检索给定的园区详细信息列表", zap.Strings("pids", pids)) if len(pids) == 0 { pr.log.Info("给定要检索的园区ID列表为空,执行快速返回。") return make([]*model.Park, 0), nil } ctx, cancel := global.TimeoutContext() defer cancel() var parks []*model.Park parkSql, parkArgs, _ := pr.ds. From("park"). Where(goqu.I("id").In(pids)). Prepared(true).ToSQL() if err := pgxscan.Select(ctx, global.DB, &parks, parkSql, parkArgs...); err != nil { pr.log.Error("检索给定的园区详细信息列表失败!", zap.Error(err)) return nil, err } return parks, nil } // 获取指定园区中的建筑 func (pr _ParkRepository) RetrieveParkBuildings(pid string) ([]*model.ParkBuilding, error) { pr.log.Info("获取指定园区中的建筑", zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() var buildings []*model.ParkBuilding buildingSql, buildingArgs, _ := pr.ds. From("park_building"). Where( goqu.I("park_id").Eq(pid), goqu.I("deleted_at").IsNull(), ). Order(goqu.I("created_at").Asc()). Prepared(true).ToSQL() if err := pgxscan.Select(ctx, global.DB, &buildings, buildingSql, buildingArgs...); err != nil { pr.log.Error("获取指定园区中的建筑失败!", zap.Error(err)) return nil, err } return buildings, nil } // 在指定园区中创建一个新建筑 func (pr _ParkRepository) CreateParkBuilding(pid, name string, floor *string) (bool, error) { pr.log.Info("在指定园区中创建一个新建筑", zap.String("pid", pid), zap.String("name", name), zap.Stringp("floor", floor)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() serial.StringSerialRequestChan <- 1 code := serial.Prefix("B", <-serial.StringSerialResponseChan) createSql, createArgs, _ := pr.ds. Insert("park_building"). Cols( "id", "park_id", "name", "floors", "enabled", "created_at", "last_modified_at", ). Vals(goqu.Vals{ code, pid, name, floor, true, timeNow, timeNow, }). Prepared(true).ToSQL() rs, err := global.DB.Exec(ctx, createSql, createArgs...) if err != nil { pr.log.Error("在指定园区中创建一个新建筑失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil } // 在指定园区中创建一个建筑,这个方法会使用事务 func (pr _ParkRepository) CreateParkBuildingWithTransaction(tx pgx.Tx, ctx context.Context, pid, name string, floor *string) (bool, error) { timeNow := types.Now() serial.StringSerialRequestChan <- 1 code := serial.Prefix("B", <-serial.StringSerialResponseChan) createSql, createArgs, _ := pr.ds. Insert("park_building"). Cols( "id", "park_id", "name", "floors", "enabled", "created_at", "last_modified_at", ). Vals(goqu.Vals{ code, pid, name, floor, true, timeNow, timeNow, }). Prepared(true).ToSQL() rs, err := tx.Exec(ctx, createSql, createArgs...) if err != nil { pr.log.Error("在指定园区中创建一个新建筑失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil } // 修改指定园区中指定建筑的信息 func (pr _ParkRepository) ModifyParkBuilding(id, pid, name string, floor *string) (bool, error) { pr.log.Info("修改指定园区中指定建筑的信息", zap.String("id", id), zap.String("pid", pid), zap.String("name", name), zap.Stringp("floor", floor)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park_building"). Set(goqu.Record{ "name": name, "floors": floor, "last_modified_at": timeNow, }). Where( goqu.I("id").Eq(id), goqu.I("park_id").Eq(pid), ). Prepared(true).ToSQL() rs, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("修改指定园区中指定建筑的信息失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil } // 修改指定建筑的可以状态 func (pr _ParkRepository) EnablingParkBuilding(id, pid string, enabled bool) (bool, error) { pr.log.Info("修改指定建筑的可以状态", zap.String("id", id), zap.String("pid", pid), zap.Bool("enabled", enabled)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park_building"). Set(goqu.Record{ "enabled": enabled, "last_modified_at": timeNow, }). Where( goqu.I("id").Eq(id), goqu.I("park_id").Eq(pid), ). Prepared(true).ToSQL() rs, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("修改指定建筑的可以状态失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil } // 删除指定建筑(软删除) func (pr _ParkRepository) DeleteParkBuilding(id, pid string) (bool, error) { pr.log.Info("删除指定建筑(软删除)", zap.String("id", id), zap.String("pid", pid)) ctx, cancel := global.TimeoutContext() defer cancel() timeNow := types.Now() updateSql, updateArgs, _ := pr.ds. Update("park_building"). Set(goqu.Record{ "deleted_at": timeNow, "last_modified_at": timeNow, }). Where( goqu.I("id").Eq(id), goqu.I("park_id").Eq(pid), ). Prepared(true).ToSQL() rs, err := global.DB.Exec(ctx, updateSql, updateArgs...) if err != nil { pr.log.Error("删除指定建筑(软删除)失败!", zap.Error(err)) return false, err } return rs.RowsAffected() > 0, nil }