package service import ( "electricity_bill_calc/cache" "electricity_bill_calc/global" "electricity_bill_calc/logger" "electricity_bill_calc/repository" "electricity_bill_calc/types" "fmt" "github.com/shopspring/decimal" "go.uber.org/zap" ) type _ChargeService struct { log *zap.Logger } var ChargeService = &_ChargeService{ log: logger.Named("Service", "Charge"), } // 创建一条新的用户充值记录,同时更新用户的服务期限 func (cs _ChargeService) RecordUserCharge(uid string, fee, discount, amount *decimal.Decimal, chargeTo types.Date, extendExpriationIgnoringSettle bool) (bool, error) { cs.log.Info( "创建一条新的用户充值记录。", zap.String("uid", uid), logger.DecimalFieldp("fee", fee), logger.DecimalFieldp("discount", discount), logger.DecimalFieldp("amount", amount), logger.DateField("chargeTo", chargeTo), zap.Bool("extendExpriationIgnoringSettle", extendExpriationIgnoringSettle), ) ctx, cancel := global.TimeoutContext() defer cancel() tx, err := global.DB.Begin(ctx) if err != nil { cs.log.Error("开启数据库事务失败。", zap.Error(err)) return false, err } ok, err := repository.ChargeRepository.CreateChargeRecord(tx, ctx, uid, fee, discount, amount, chargeTo) switch { case err == nil && !ok: cs.log.Error("未能成功创建用户充值记录", zap.Error(err)) tx.Rollback(ctx) return false, fmt.Errorf("未能成功创建用户充值记录") case err != nil: cs.log.Error("创建用户充值记录失败。", zap.Error(err)) tx.Rollback(ctx) return false, err } if extendExpriationIgnoringSettle { ok, err = repository.UserRepository.UpdateServiceExpiration(tx, ctx, uid, chargeTo.Time) switch { case err != nil: cs.log.Error("更新用户服务期限失败。", zap.Error(err)) tx.Rollback(ctx) return false, err case !ok: cs.log.Error("未能成功更新用户服务期限", zap.Error(err)) tx.Rollback(ctx) return false, fmt.Errorf("未能成功更新用户服务期限") } } err = tx.Commit(ctx) if err != nil { cs.log.Error("提交数据库事务失败。", zap.Error(err)) return false, err } cache.AbolishRelation("charge") cache.AbolishRelation(fmt.Sprintf("user:%s", uid)) return true, nil } // 撤销用户的某一条充值记录,同时重新设置用户的服务期限 func (cs _ChargeService) CancelUserCharge(uid string, seq int64) (bool, error) { cs.log.Info("撤销用户的充值记录。", zap.String("uid", uid), zap.Int64("seq", seq)) ctx, cancel := global.TimeoutContext() defer cancel() tx, err := global.DB.Begin(ctx) if err != nil { cs.log.Error("开启数据库事务失败。", zap.Error(err)) return false, err } ok, err := repository.ChargeRepository.CancelCharge(tx, ctx, uid, seq) switch { case err == nil && !ok: cs.log.Error("未能成功撤销用户充值记录", zap.Error(err)) tx.Rollback(ctx) return false, fmt.Errorf("未能成功撤销用户充值记录") case err != nil: cs.log.Error("撤销用户充值记录失败。", zap.Error(err)) tx.Rollback(ctx) return false, err } if ok { lastValidCharge, err := repository.ChargeRepository.LatestValidChargeTo(tx, ctx, uid) if err != nil { cs.log.Error("查询用户最近一次有效的充值记录失败。", zap.Error(err)) tx.Rollback(ctx) return false, err } ok, err = repository.UserRepository.UpdateServiceExpiration(tx, ctx, uid, lastValidCharge.Time) if err != nil || !ok { cs.log.Error("更新用户服务期限失败。", zap.Error(err)) tx.Rollback(ctx) return false, err } } err = tx.Commit(ctx) if err != nil { cs.log.Error("提交数据库事务失败。", zap.Error(err)) return false, err } cache.AbolishRelation("charge") cache.AbolishRelation(fmt.Sprintf("user:%s", uid)) return true, nil }