242 lines
9.6 KiB
Go
242 lines
9.6 KiB
Go
package service
|
|
|
|
import (
|
|
"electricity_bill_calc/global"
|
|
"electricity_bill_calc/logger"
|
|
"electricity_bill_calc/model"
|
|
"electricity_bill_calc/repository"
|
|
"electricity_bill_calc/vo"
|
|
"fmt"
|
|
|
|
"github.com/samber/lo"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type _TenementService struct {
|
|
log *zap.Logger
|
|
}
|
|
|
|
var TenementService = _TenementService{
|
|
log: logger.Named("Service", "Tenement"),
|
|
}
|
|
|
|
// 列出指定商户下的全部计量表计,不包含公摊表计
|
|
func (ts _TenementService) ListMeter(pid, tid string) ([]*model.MeterDetail, error) {
|
|
ts.log.Info("列出指定商户下的全部表计", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
meterCodes, err := repository.TenementRepository.ListMeterCodesBelongsTo(pid, tid)
|
|
if err != nil {
|
|
ts.log.Error("列出指定商户下的全部表计失败,未能获取属于商户的表计编号", zap.Error(err))
|
|
return make([]*model.MeterDetail, 0), err
|
|
}
|
|
meters, err := repository.MeterRepository.ListMetersByIDs(pid, meterCodes)
|
|
if err != nil {
|
|
ts.log.Error("列出指定商户下的全部表计失败,未能获取表计编号对应的表计详细信息", zap.Error(err))
|
|
return make([]*model.MeterDetail, 0), err
|
|
}
|
|
return meters, nil
|
|
}
|
|
|
|
// 增加一个新的商户
|
|
func (ts _TenementService) CreateTenementRecord(pid string, creationForm *vo.TenementCreationForm) error {
|
|
ts.log.Info("增加一个新的商户", zap.String("Park", pid), zap.Any("Form", creationForm))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tx, err := global.DB.Begin(ctx)
|
|
if err != nil {
|
|
ts.log.Error("增加一个新商户失败的,未能启动数据库事务", zap.Error(err))
|
|
return fmt.Errorf("未能启动数据库事务,%w", err)
|
|
}
|
|
|
|
err = repository.TenementRepository.AddTenement(tx, ctx, pid, creationForm)
|
|
if err != nil {
|
|
ts.log.Error("增加一个新商户失败的,未能增加商户记录", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能增加商户记录,%w", err)
|
|
}
|
|
|
|
err = tx.Commit(ctx)
|
|
if err != nil {
|
|
ts.log.Error("增加一个新商户失败的,未能提交数据库事务", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能提交数据库事务,%w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 向商户绑定一个新表计
|
|
func (ts _TenementService) BindMeter(pid, tid, meterCode string, reading *vo.MeterReadingForm) error {
|
|
ts.log.Info("向商户绑定一个新表计", zap.String("Park", pid), zap.String("Tenement", tid), zap.String("Meter", meterCode))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tx, err := global.DB.Begin(ctx)
|
|
if err != nil {
|
|
ts.log.Error("向商户绑定一个新表计失败,未能启动数据库事务", zap.Error(err))
|
|
return fmt.Errorf("未能启动数据库事务,%w", err)
|
|
}
|
|
|
|
meterDetail, err := repository.MeterRepository.FetchMeterDetail(pid, meterCode)
|
|
if err != nil {
|
|
ts.log.Error("向商户绑定一个新表计失败,未能获取表计详细信息", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能获取表计详细信息,%w", err)
|
|
}
|
|
err = repository.TenementRepository.BindMeter(tx, ctx, pid, tid, meterCode,reading)
|
|
if err != nil {
|
|
ts.log.Error("向商户绑定一个新表计失败,未能绑定表计", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能绑定表计,%w", err)
|
|
}
|
|
ok, err := repository.MeterRepository.RecordReading(tx, ctx, pid, meterCode, meterDetail.MeterType, meterDetail.Ratio, reading)
|
|
if err != nil {
|
|
ts.log.Error("向商户绑定一个新表计失败,记录表计读数出现错误", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计读数出现错误,%w", err)
|
|
}
|
|
if !ok {
|
|
ts.log.Error("向商户绑定一个新表计失败,记录表计读数失败")
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计读数失败")
|
|
}
|
|
|
|
err = tx.Commit(ctx)
|
|
if err != nil {
|
|
ts.log.Error("向商户绑定一个新表计失败,未能提交数据库事务", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能提交数据库事务,%w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 解除商户与指定表计的绑定
|
|
func (ts _TenementService) UnbindMeter(pid, tid, meterCode string, reading *vo.MeterReadingForm) error {
|
|
ts.log.Info("解除商户与指定表计的绑定", zap.String("Park", pid), zap.String("Tenement", tid), zap.String("Meter", meterCode))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tx, err := global.DB.Begin(ctx)
|
|
if err != nil {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,未能启动数据库事务", zap.Error(err))
|
|
return fmt.Errorf("未能启动数据库事务,%w", err)
|
|
}
|
|
|
|
meterDetail, err := repository.MeterRepository.FetchMeterDetail(pid, meterCode)
|
|
if err != nil {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,未能获取表计详细信息", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能获取表计详细信息,%w", err)
|
|
}
|
|
err = repository.TenementRepository.UnbindMeter(tx, ctx, pid, tid, meterCode)
|
|
if err != nil {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,未能解除绑定", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能解除绑定,%w", err)
|
|
}
|
|
ok, err := repository.MeterRepository.RecordReading(tx, ctx, pid, meterCode, meterDetail.MeterType, meterDetail.Ratio, reading)
|
|
if err != nil {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,记录表计读数出现错误", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计读数出现错误,%w", err)
|
|
}
|
|
if !ok {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,记录表计读数失败")
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计读数失败")
|
|
}
|
|
|
|
err = tx.Commit(ctx)
|
|
if err != nil {
|
|
ts.log.Error("解除商户与指定表计的绑定失败,未能提交数据库事务", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能提交数据库事务,%w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 迁出指定商户
|
|
func (ts _TenementService) MoveOutTenement(pid, tid string, reading []*vo.MeterReadingFormWithCode) error {
|
|
ts.log.Info("迁出指定商户", zap.String("Park", pid), zap.String("Tenement", tid))
|
|
ctx, cancel := global.TimeoutContext()
|
|
defer cancel()
|
|
|
|
tx, err := global.DB.Begin(ctx)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能启动数据库事务", zap.Error(err))
|
|
return fmt.Errorf("未能启动数据库事务,%w", err)
|
|
}
|
|
|
|
meterCodes, err := repository.TenementRepository.ListMeterCodesBelongsTo(pid, tid)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能获取属于商户的表计编号", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能获取属于商户的表计编号,%w", err)
|
|
}
|
|
meters, err := repository.MeterRepository.ListMetersByIDs(pid, meterCodes)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能获取表涉及计编号对应的表计详细信息", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能获取涉及表计编号对应的表计详细信息,%w", err)
|
|
}
|
|
|
|
for _, meterCode := range meterCodes {
|
|
meterDetail, exists := lo.Find(meters, func(m *model.MeterDetail) bool {
|
|
return m.Code == meterCode
|
|
})
|
|
if !exists {
|
|
ts.log.Error("迁出指定商户失败,找不到指定表计的详细信息", zap.String("Meter", meterCode))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("找不到指定表计[%s]的详细信息,%w", meterCode, err)
|
|
}
|
|
if meterDetail.MeterType != model.METER_INSTALLATION_TENEMENT {
|
|
ts.log.Error("迁出指定商户失败,需要解绑的表计不是商户表计", zap.String("Meter", meterCode))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("需要解绑的表计[%s]不是商户表计,%w", meterCode, err)
|
|
}
|
|
reading, exists := lo.Find(reading, func(r *vo.MeterReadingFormWithCode) bool {
|
|
return r.Code == meterCode
|
|
})
|
|
if !exists {
|
|
ts.log.Error("迁出指定商户失败,找不到指定表计的抄表信息", zap.String("Meter", meterCode))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("找不到指定表计[%s]的抄表信息,%w", meterCode, err)
|
|
}
|
|
if reading.Validate() {
|
|
ts.log.Error("迁出指定商户失败,表计读数不能正确配平,尖锋电量、峰电量、谷电量之和超过总电量。", zap.String("Meter", meterCode))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("表计[%s]读数不能正确配平,尖锋电量、峰电量、谷电量之和超过总电量。", meterCode)
|
|
}
|
|
err = repository.TenementRepository.UnbindMeter(tx, ctx, pid, tid, meterCode)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能解除表计绑定", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能解除表计[%s]绑定,%w", meterCode, err)
|
|
}
|
|
ok, err := repository.MeterRepository.RecordReading(tx, ctx, pid, meterCode, meterDetail.MeterType, meterDetail.Ratio, &reading.MeterReadingForm)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,记录表计抄表信息出现错误", zap.String("Meter", meterCode), zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计[%s]抄表信息出现错误,%w", meterCode, err)
|
|
}
|
|
if !ok {
|
|
ts.log.Error("迁出指定商户失败,记录表计抄表数据失败", zap.String("Meter", meterCode))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("记录表计[%s]抄表数据失败", meterCode)
|
|
}
|
|
}
|
|
err = repository.TenementRepository.MoveOut(tx, ctx, pid, tid)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能迁出指定商户", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能迁出指定商户,%w", err)
|
|
}
|
|
|
|
err = tx.Commit(ctx)
|
|
if err != nil {
|
|
ts.log.Error("迁出指定商户失败,未能提交数据库事务", zap.Error(err))
|
|
tx.Rollback(ctx)
|
|
return fmt.Errorf("未能提交数据库事务,%w", err)
|
|
}
|
|
return nil
|
|
}
|