459 lines
15 KiB
Go
459 lines
15 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"electricity_bill_calc/config"
|
|
"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"
|
|
"electricity_bill_calc/vo"
|
|
"fmt"
|
|
|
|
"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 _TenementRepository struct {
|
|
log *zap.Logger
|
|
ds goqu.DialectWrapper
|
|
}
|
|
|
|
var TenementRepository = _TenementRepository{
|
|
log: logger.Named("Repository", "Tenement"),
|
|
ds: goqu.Dialect("postgres"),
|
|
}
|
|
|
|
// 判断指定商户是否属于指定用户的管辖
|
|
func (tr _TenementRepository) IsTenementBelongs(tid, uid string) (bool, error) {
|
|
tr.log.Info("检查指定商户是否属于指定企业管辖", zap.String("Tenement", tid), zap.String("Enterprise", uid))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
countSql, countArgs, _ := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
Join(goqu.T("park").As("p"), goqu.On(goqu.I("t.park_id").Eq(goqu.I("p.id")))).
|
|
Select(goqu.COUNT("t.*")).
|
|
Where(
|
|
goqu.I("t.id").Eq(tid),
|
|
goqu.I("p.user_id").Eq(uid),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
var count int
|
|
if err := pgxscan.Get(ctx, global.DB, &count, countSql, countArgs...); err != nil {
|
|
tr.log.Error("检查指定商户是否属于指定企业管辖失败", zap.Error(err))
|
|
return false, err
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// 列出指定园区中的所有商户
|
|
func (tr _TenementRepository) ListTenements(pid string, page uint, keyword, building *string, startDate, endDate *types.Date, state int) ([]*model.Tenement, int64, error) {
|
|
tr.log.Info(
|
|
"检索查询指定园区中符合条件的商户",
|
|
zap.String("Park", pid),
|
|
zap.Uint("Page", page),
|
|
zap.Stringp("Keyword", keyword),
|
|
zap.Stringp("Building", building),
|
|
logger.DateFieldp("StartDate", startDate),
|
|
logger.DateFieldp("EndDate", endDate),
|
|
zap.Int("State", state),
|
|
)
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tenementQuery := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("t.building")))).
|
|
Select("t.*", goqu.I("b.name").As("building_name")).
|
|
Where(goqu.I("t.park_id").Eq(pid))
|
|
countQuery := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
Select(goqu.COUNT("t.*")).
|
|
Where(goqu.I("t.park_id").Eq(pid))
|
|
|
|
if keyword != nil && len(*keyword) > 0 {
|
|
pattern := fmt.Sprintf("%%%s%%", *keyword)
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.full_name").ILike(pattern),
|
|
goqu.I("t.short_name").ILike(pattern),
|
|
goqu.I("t.abbr").ILike(pattern),
|
|
goqu.I("t.contact_name").ILike(pattern),
|
|
goqu.I("t.contact_phone").ILike(pattern),
|
|
goqu.I("t.address").ILike(pattern),
|
|
),
|
|
)
|
|
countQuery = countQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.full_name").ILike(pattern),
|
|
goqu.I("t.short_name").ILike(pattern),
|
|
goqu.I("t.abbr").ILike(pattern),
|
|
goqu.I("t.contact_name").ILike(pattern),
|
|
goqu.I("t.contact_phone").ILike(pattern),
|
|
goqu.I("t.address").ILike(pattern),
|
|
),
|
|
)
|
|
}
|
|
|
|
if building != nil && len(*building) > 0 {
|
|
tenementQuery = tenementQuery.Where(goqu.I("t.building").Eq(*building))
|
|
countQuery = countQuery.Where(goqu.I("t.building").Eq(*building))
|
|
}
|
|
|
|
if startDate != nil {
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.moved_in_at").Gte(startDate.ToBeginningOfDate()),
|
|
goqu.I("t.moved_out_at").Gte(startDate.ToBeginningOfDate()),
|
|
),
|
|
)
|
|
countQuery = countQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.moved_in_at").Gte(startDate.ToBeginningOfDate()),
|
|
goqu.I("t.moved_out_at").Gte(startDate.ToBeginningOfDate()),
|
|
),
|
|
)
|
|
}
|
|
|
|
if endDate != nil {
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.moved_in_at").Lte(endDate.ToEndingOfDate()),
|
|
goqu.I("t.moved_out_at").Lte(endDate.ToEndingOfDate()),
|
|
),
|
|
)
|
|
countQuery = countQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.moved_in_at").Lte(endDate.ToEndingOfDate()),
|
|
goqu.I("t.moved_out_at").Lte(endDate.ToEndingOfDate()),
|
|
),
|
|
)
|
|
}
|
|
|
|
if state == 0 {
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.I("t.moved_out_at").IsNull(),
|
|
)
|
|
countQuery = countQuery.Where(
|
|
goqu.I("t.moved_out_at").IsNull(),
|
|
)
|
|
} else {
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.I("t.moved_out_at").IsNotNull(),
|
|
)
|
|
countQuery = countQuery.Where(
|
|
goqu.I("t.moved_out_at").IsNotNull(),
|
|
)
|
|
}
|
|
|
|
startRow := (page - 1) * config.ServiceSettings.ItemsPageSize
|
|
tenementQuery = tenementQuery.Order(goqu.I("t.created_at").Desc()).Limit(config.ServiceSettings.ItemsPageSize).Offset(startRow)
|
|
|
|
tenementSql, tenementArgs, _ := tenementQuery.Prepared(true).ToSQL()
|
|
countSql, countArgs, _ := countQuery.Prepared(true).ToSQL()
|
|
|
|
var (
|
|
tenements []*model.Tenement = make([]*model.Tenement, 0)
|
|
total int64
|
|
)
|
|
if err := pgxscan.Select(ctx, global.DB, &tenements, tenementSql, tenementArgs...); err != nil {
|
|
tr.log.Error("检索查询指定园区中符合条件的商户失败", zap.Error(err))
|
|
return tenements, 0, err
|
|
}
|
|
if err := pgxscan.Get(ctx, global.DB, &total, countSql, countArgs...); err != nil {
|
|
tr.log.Error("检索查询指定园区中符合条件的商户总数量失败", zap.Error(err))
|
|
return tenements, 0, err
|
|
}
|
|
return tenements, total, nil
|
|
}
|
|
|
|
// 查询指定园区中某一商户下的所有表计编号,不包含公摊表计
|
|
func (tr _TenementRepository) ListMeterCodesBelongsTo(pid, tid string) ([]string, error) {
|
|
tr.log.Info("查询指定商户下所有的表计编号", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
sql, args, _ := tr.ds.
|
|
From("tenement_meter").
|
|
Select("meter_id").
|
|
Where(
|
|
goqu.I("park_id").Eq(pid),
|
|
goqu.I("tenement_id").Eq(tid),
|
|
goqu.I("disassociated_at").IsNull(),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
|
|
var meterCodes []string = make([]string, 0)
|
|
if err := pgxscan.Select(ctx, global.DB, &meterCodes, sql, args...); err != nil {
|
|
tr.log.Error("查询指定商户下所有的表计编号失败", zap.Error(err))
|
|
return meterCodes, err
|
|
}
|
|
return meterCodes, nil
|
|
}
|
|
|
|
// 在指定园区中创建一个新的商户
|
|
func (tr _TenementRepository) AddTenement(tx pgx.Tx, ctx context.Context, pid string, tenement *vo.TenementCreationForm) error {
|
|
tr.log.Info("在指定园区中创建一个新的商户", zap.String("Park", pid))
|
|
|
|
serial.StringSerialRequestChan <- 1
|
|
tenementId := serial.Prefix("T", <-serial.StringSerialResponseChan)
|
|
currentTime := types.Now()
|
|
if _, err := tx.Exec(
|
|
ctx,
|
|
"INSERT INTO tenement (id, park_id, full_name, short_name, abbr, address, contact_name, contact_phone, building, on_floor, invoice_info, moved_in_at, created_at, last_modified_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)",
|
|
[]interface{}{
|
|
tenementId,
|
|
pid,
|
|
tenement.Name,
|
|
tenement.ShortName,
|
|
tools.PinyinAbbr(tenement.Name),
|
|
tenement.Address,
|
|
tenement.Contact,
|
|
tenement.Phone,
|
|
tenement.Building,
|
|
tenement.OnFloor,
|
|
&model.InvoiceTitle{
|
|
Name: tenement.Name,
|
|
USCI: tenement.USCI,
|
|
Address: tools.DefaultOrEmptyStr(tenement.InvoiceAddress, ""),
|
|
Phone: tools.DefaultOrEmptyStr(tenement.InvoicePhone, ""),
|
|
Bank: tools.DefaultOrEmptyStr(tenement.Bank, ""),
|
|
Account: tools.DefaultOrEmptyStr(tenement.Account, ""),
|
|
},
|
|
currentTime,
|
|
currentTime,
|
|
currentTime,
|
|
}...,
|
|
); err != nil {
|
|
tr.log.Error("在指定园区中创建一个新的商户失败", zap.Error(err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 向园区中指定商户下绑定一个新的表计
|
|
func (tr _TenementRepository) BindMeter(tx pgx.Tx, ctx context.Context, pid, tid, meter string) error {
|
|
tr.log.Info("向园区中指定商户下绑定一个新的表计", zap.String("Park", pid), zap.String("Tenement", tid), zap.String("Meter", meter))
|
|
|
|
createSql, createArgs, _ := tr.ds.
|
|
Insert("tenement_meter").
|
|
Cols(
|
|
"park_id", "tenement_id", "meter_id", "associated_at",
|
|
).
|
|
Vals(
|
|
goqu.Vals{
|
|
pid,
|
|
tid,
|
|
meter,
|
|
types.Now(),
|
|
},
|
|
).
|
|
Prepared(true).ToSQL()
|
|
if _, err := tx.Exec(ctx, createSql, createArgs...); err != nil {
|
|
tr.log.Error("向园区中指定商户下绑定一个新的表计失败", zap.Error(err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 将指定商户与指定表计解绑
|
|
func (tr _TenementRepository) UnbindMeter(tx pgx.Tx, ctx context.Context, pid, tid, meter string) error {
|
|
tr.log.Info("将指定商户与指定表计解绑", zap.String("Park", pid), zap.String("Tenement", tid), zap.String("Meter", meter))
|
|
|
|
updateSql, updateArgs, _ := tr.ds.
|
|
Update("tenement_meter").
|
|
Set(
|
|
goqu.Record{
|
|
"disassociated_at": types.Now(),
|
|
},
|
|
).
|
|
Where(
|
|
goqu.I("park_id").Eq(pid),
|
|
goqu.I("tenement_id").Eq(tid),
|
|
goqu.I("meter_id").Eq(meter),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
if _, err := tx.Exec(ctx, updateSql, updateArgs...); err != nil {
|
|
tr.log.Error("将指定商户与指定表计解绑失败", zap.Error(err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 修改指定商户的信息
|
|
func (tr _TenementRepository) UpdateTenement(pid, tid string, tenement *vo.TenementCreationForm) error {
|
|
tr.log.Info("修改指定商户的信息", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
updateSql, updateArgs, _ := tr.ds.
|
|
Update("tenement").
|
|
Set(
|
|
goqu.Record{
|
|
"full_name": tenement.Name,
|
|
"short_name": tenement.ShortName,
|
|
"abbr": tools.PinyinAbbr(tenement.Name),
|
|
"address": tenement.Address,
|
|
"contact_name": tenement.Contact,
|
|
"contact_phone": tenement.Phone,
|
|
"building": tenement.Building,
|
|
"on_floor": tenement.OnFloor,
|
|
"invoice_info": &model.InvoiceTitle{
|
|
Name: tenement.Name,
|
|
USCI: tenement.USCI,
|
|
Address: tools.DefaultOrEmptyStr(tenement.InvoiceAddress, ""),
|
|
Phone: tools.DefaultOrEmptyStr(tenement.InvoicePhone, ""),
|
|
Bank: tools.DefaultOrEmptyStr(tenement.Bank, ""),
|
|
Account: tools.DefaultOrEmptyStr(tenement.Account, ""),
|
|
},
|
|
"last_modified_at": types.Now(),
|
|
},
|
|
).
|
|
Where(
|
|
goqu.I("id").Eq(tid),
|
|
goqu.I("park_id").Eq(pid),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
if _, err := global.DB.Exec(ctx, updateSql, updateArgs...); err != nil {
|
|
tr.log.Error("修改指定商户的信息失败", zap.Error(err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 迁出指定商户
|
|
func (tr _TenementRepository) MoveOut(tx pgx.Tx, ctx context.Context, pid, tid string) error {
|
|
tr.log.Info("迁出指定商户", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
|
|
updateSql, updateArgs, _ := tr.ds.
|
|
Update("tenement").
|
|
Set(
|
|
goqu.Record{
|
|
"moved_out_at": types.Now(),
|
|
},
|
|
).
|
|
Where(
|
|
goqu.I("id").Eq(tid),
|
|
goqu.I("park_id").Eq(pid),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
if _, err := tx.Exec(ctx, updateSql, updateArgs...); err != nil {
|
|
tr.log.Error("迁出指定商户失败", zap.Error(err))
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 列出用于下拉列表的符合指定条件的商户信息
|
|
func (tr _TenementRepository) ListForSelect(uid string, pid, keyword *string, limit *uint) ([]*model.Tenement, error) {
|
|
tr.log.Info("列出用于下拉列表的符合指定条件的商户信息", zap.String("Ent", uid), zap.String("Park", tools.DefaultOrEmptyStr(pid, "All")), zap.Stringp("Keyword", keyword), zap.Uintp("Limit", limit))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tenementQuery := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("t.building")))).
|
|
Join(goqu.T("park").As("p"), goqu.On(goqu.I("p.id").Eq(goqu.I("t.park_id")))).
|
|
Select(
|
|
"t.*", goqu.I("b.name").As("building_name"),
|
|
).
|
|
Where(
|
|
goqu.I("p.user_id").Eq(uid),
|
|
goqu.I("t.moved_out_at").IsNull(),
|
|
)
|
|
|
|
if pid != nil && len(*pid) > 0 {
|
|
tenementQuery = tenementQuery.Where(goqu.I("p.id").Eq(*pid))
|
|
}
|
|
|
|
if keyword != nil && len(*keyword) > 0 {
|
|
pattern := fmt.Sprintf("%%%s%%", *keyword)
|
|
tenementQuery = tenementQuery.Where(
|
|
goqu.Or(
|
|
goqu.I("t.full_name").ILike(pattern),
|
|
goqu.I("t.short_name").ILike(pattern),
|
|
goqu.I("t.abbr").ILike(pattern),
|
|
),
|
|
)
|
|
}
|
|
|
|
tenementQuery = tenementQuery.Order(goqu.I("t.created_at").Desc())
|
|
|
|
if limit != nil && *limit > 0 {
|
|
tenementQuery = tenementQuery.Limit(*limit)
|
|
}
|
|
|
|
tenementSql, tenementArgs, _ := tenementQuery.Prepared(true).ToSQL()
|
|
|
|
var tenements = make([]*model.Tenement, 0)
|
|
if err := pgxscan.Select(ctx, global.DB, &tenements, tenementSql, tenementArgs...); err != nil {
|
|
tr.log.Error("列出用于下拉列表的符合指定条件的商户信息失败", zap.Error(err))
|
|
return tenements, err
|
|
}
|
|
return tenements, nil
|
|
}
|
|
|
|
// 列出指定园区中在指定时间区间内存在过入住的商户
|
|
func (tr _TenementRepository) ListTenementsInTimeRange(pid string, start, end types.Date) ([]*model.Tenement, error) {
|
|
tr.log.Info("列出指定园区中在指定时间区间内存在过入住的商户", zap.String("Park", pid), logger.DateField("Start", start), logger.DateField("End", end))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tenementQuery := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("t.building")))).
|
|
Select(
|
|
"t.*", goqu.I("b.name").As("building_name"),
|
|
).
|
|
Where(
|
|
goqu.I("t.park_id").Eq(pid),
|
|
goqu.I("t.moved_in_at").Lte(end.ToEndingOfDate()),
|
|
goqu.Or(
|
|
goqu.I("t.moved_out_at").IsNull(),
|
|
goqu.I("t.moved_out_at").Gte(start.ToBeginningOfDate()),
|
|
),
|
|
).
|
|
Order(goqu.I("t.created_at").Desc())
|
|
|
|
tenementSql, tenementArgs, _ := tenementQuery.Prepared(true).ToSQL()
|
|
|
|
var tenements = make([]*model.Tenement, 0)
|
|
if err := pgxscan.Select(ctx, global.DB, &tenements, tenementSql, tenementArgs...); err != nil {
|
|
tr.log.Error("列出指定园区中在指定时间区间内存在过入住的商户失败", zap.Error(err))
|
|
return tenements, err
|
|
}
|
|
|
|
return tenements, nil
|
|
}
|
|
|
|
// 获取指定园区中指定商户的详细信息
|
|
func (tr _TenementRepository) RetrieveTenementDetail(pid, tid string) (*model.Tenement, error) {
|
|
tr.log.Info("获取指定园区中指定商户的详细信息", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tenementSql, tenementArgs, _ := tr.ds.
|
|
From(goqu.T("tenement").As("t")).
|
|
LeftJoin(goqu.T("park_building").As("b"), goqu.On(goqu.I("b.id").Eq(goqu.I("t.building")))).
|
|
Select(
|
|
"t.*", goqu.I("b.name").As("building_name"),
|
|
).
|
|
Where(
|
|
goqu.I("t.id").Eq(tid),
|
|
goqu.I("t.park_id").Eq(pid),
|
|
).
|
|
Prepared(true).ToSQL()
|
|
var tenement model.Tenement
|
|
if err := pgxscan.Get(ctx, global.DB, &tenement, tenementSql, tenementArgs...); err != nil {
|
|
tr.log.Error("获取指定园区中指定商户的详细信息失败", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
return &tenement, nil
|
|
}
|