474 lines
15 KiB
Go
474 lines
15 KiB
Go
package repository
|
||
|
||
import (
|
||
"electricity_bill_calc/cache"
|
||
"electricity_bill_calc/global"
|
||
"electricity_bill_calc/logger"
|
||
"electricity_bill_calc/model"
|
||
"electricity_bill_calc/tools"
|
||
"electricity_bill_calc/tools/serial"
|
||
"electricity_bill_calc/tools/time"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"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 _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))
|
||
cacheConditions := []string{
|
||
uid,
|
||
}
|
||
if parks, err := cache.RetrieveSearch[[]*model.Park]("park_belongs", cacheConditions...); err == nil && parks != nil {
|
||
pr.log.Info("已经从缓存获取到了指定用户下的所有园区。")
|
||
return *parks, nil
|
||
}
|
||
ctx, cancel := global.TimeoutContext()
|
||
defer cancel()
|
||
|
||
var parks []*model.Park
|
||
parkQuerySql, parkParams, _ := pr.ds.
|
||
From("park").
|
||
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
|
||
}
|
||
|
||
cache.CacheSearch(parks, []string{"park", fmt.Sprintf("park:%s", uid)}, "park_belongs", cacheConditions...)
|
||
|
||
return parks, nil
|
||
}
|
||
|
||
// 检查并确定指定园区的归属情况
|
||
func (pr _ParkRepository) IsParkBelongs(pid, uid string) (bool, error) {
|
||
pr.log.Info("检查并确定指定园区的归属情况", zap.String("pid", pid), zap.String("uid", uid))
|
||
cacheConditions := []string{
|
||
pid, "belongs", uid,
|
||
}
|
||
if exists, err := cache.CheckExists("park", cacheConditions...); err == nil && exists {
|
||
pr.log.Info("已经从缓存获取到了指定园区的归属情况。")
|
||
return true, nil
|
||
}
|
||
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
|
||
}
|
||
|
||
if count > 0 {
|
||
cache.CacheExists([]string{"park", fmt.Sprintf("park:%s", uid)}, "park", cacheConditions...)
|
||
}
|
||
|
||
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 := time.Now()
|
||
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{
|
||
serial.GeneratePrefixedUniqueSerialString("P"),
|
||
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
|
||
}
|
||
|
||
cache.AbolishRelation("park")
|
||
|
||
return rs.RowsAffected() > 0, nil
|
||
}
|
||
|
||
// 获取指定园区的详细信息
|
||
func (pr _ParkRepository) RetrieveParkDetail(pid string) (*model.Park, error) {
|
||
pr.log.Info("获取指定园区的详细信息", zap.String("pid", pid))
|
||
if park, err := cache.RetrieveEntity[model.Park]("park", pid); err == nil && park != nil {
|
||
pr.log.Info("已经从缓存获取到了指定园区的详细信息。")
|
||
return park, nil
|
||
}
|
||
ctx, cancel := global.TimeoutContext()
|
||
defer cancel()
|
||
|
||
var park model.Park
|
||
parkSql, parkArgs, _ := pr.ds.
|
||
From("park").
|
||
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
|
||
}
|
||
|
||
cache.CacheEntity(park, []string{"park", fmt.Sprintf("park:%s", pid)}, "park", pid)
|
||
|
||
return &park, nil
|
||
}
|
||
|
||
// 获取园区对应的用户ID
|
||
func (pr _ParkRepository) RetrieveParkbelongs(pid string) (string, error) {
|
||
pr.log.Info("获取园区对应的用户ID", zap.String("pid", pid))
|
||
if uid, err := cache.RetrieveEntity[string]("park_belongs", pid); err == nil && uid != nil {
|
||
pr.log.Info("已经从缓存获取到了园区对应的用户ID。")
|
||
return *uid, nil
|
||
}
|
||
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
|
||
}
|
||
|
||
cache.CacheEntity(uid, []string{"park", fmt.Sprintf("park:%s", pid)}, "park_belongs", pid)
|
||
|
||
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 := time.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
|
||
}
|
||
|
||
if ok.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park")
|
||
cache.AbolishRelation(fmt.Sprintf("park:%s", pid))
|
||
}
|
||
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 := time.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
|
||
}
|
||
|
||
if ok.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park")
|
||
cache.AbolishRelation(fmt.Sprintf("park:%s", pid))
|
||
}
|
||
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 := time.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
|
||
}
|
||
|
||
if ok.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park")
|
||
cache.AbolishRelation(fmt.Sprintf("park:%s", pid))
|
||
}
|
||
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
|
||
}
|
||
cacheConditions := []string{strings.Join(pids, ",")}
|
||
if parks, err := cache.RetrieveSearch[[]*model.Park]("park", cacheConditions...); err == nil && parks != nil {
|
||
pr.log.Info("已经从缓存获取到了给定的园区详细信息列表。")
|
||
return *parks, 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
|
||
}
|
||
|
||
cache.CacheSearch(parks, []string{"park", fmt.Sprintf("park:%s", strings.Join(pids, ":"))}, "park", cacheConditions...)
|
||
|
||
return parks, nil
|
||
}
|
||
|
||
// 获取指定园区中的建筑
|
||
func (pr _ParkRepository) RetrieveParkBuildings(pid string) ([]*model.ParkBuilding, error) {
|
||
pr.log.Info("获取指定园区中的建筑", zap.String("pid", pid))
|
||
if buildings, err := cache.RetrieveSearch[[]*model.ParkBuilding]("park_building", pid); err == nil && buildings != nil {
|
||
pr.log.Info("已经从缓存获取到了指定园区中的建筑。")
|
||
return *buildings, nil
|
||
}
|
||
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
|
||
}
|
||
|
||
cache.CacheSearch(buildings, []string{"park_building", fmt.Sprintf("park_building:%s", pid)}, "park_building", pid)
|
||
|
||
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 := time.Now()
|
||
createSql, createArgs, _ := pr.ds.
|
||
Insert("park_building").
|
||
Cols(
|
||
"id", "park_id", "name", "floors", "enabled", "created_at", "last_modified_at",
|
||
).
|
||
Vals(goqu.Vals{
|
||
serial.GeneratePrefixedUniqueSerialString("B"),
|
||
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
|
||
}
|
||
|
||
if rs.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park_building")
|
||
cache.AbolishRelation(fmt.Sprintf("park_building:%s", pid))
|
||
}
|
||
|
||
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 := time.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
|
||
}
|
||
|
||
if rs.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park_building")
|
||
cache.AbolishRelation(fmt.Sprintf("park_building:%s", pid))
|
||
}
|
||
|
||
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 := time.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
|
||
}
|
||
|
||
if rs.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park_building")
|
||
cache.AbolishRelation(fmt.Sprintf("park_building:%s", pid))
|
||
}
|
||
|
||
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 := time.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
|
||
}
|
||
|
||
if rs.RowsAffected() > 0 {
|
||
cache.AbolishRelation("park_building")
|
||
cache.AbolishRelation(fmt.Sprintf("park_building:%s", pid))
|
||
}
|
||
|
||
return rs.RowsAffected() > 0, nil
|
||
}
|