feat: publish member notices and balance-aware order settlement
Deploy olons-admin production / deploy (push) Successful in 8m50s

This commit is contained in:
richjohnrambo
2026-10-22 21:56:06 +08:00
parent 5a5540785d
commit 70ef3d9d04
10 changed files with 457 additions and 163 deletions
@@ -3,6 +3,7 @@ package sys
import (
"context"
"fmt"
"math"
"hotgo/internal/consts"
"hotgo/internal/dao"
@@ -173,6 +174,10 @@ func (s *sSysRechargeOrder) Review(ctx context.Context, in *sysin.RechargeReview
rc.UpdatedBy: contexts.GetUserId(ctx),
}
if in.Decision == consts.FinanceDecisionApprove {
tradeOrders, lockErr := NewSysTradeOrder().lockBalancePendingOrders(ctx, order.MemberId)
if lockErr != nil {
return lockErr
}
wc := dao.WalletAccount.Columns()
var account *entity.WalletAccount
if scanErr := handler.Model(dao.WalletAccount.Ctx(ctx), &handler.Option{FilterTenant: true}).Where(wc.MemberId, order.MemberId).Where(wc.Currency, order.Currency).LockUpdate().Scan(&account); scanErr != nil {
@@ -181,6 +186,9 @@ func (s *sSysRechargeOrder) Review(ctx context.Context, in *sysin.RechargeReview
if account == nil || account.AccountStatus != 1 {
return gerror.New("会员钱包不存在或不可入账")
}
if in.PaidAmount > 0 && account.AvailableAmount > math.MaxInt64-in.PaidAmount {
return gerror.New("充值金额超出钱包处理范围")
}
after := account.AvailableAmount + in.PaidAmount
lc := dao.WalletLedger.Columns()
result, insertErr := dao.WalletLedger.Ctx(ctx).
@@ -205,6 +213,9 @@ func (s *sSysRechargeOrder) Review(ctx context.Context, in *sysin.RechargeReview
if rows != 1 {
return gerror.New("钱包余额已变化,请重试")
}
if err = NewSysTradeOrder().completeBalancePendingOrders(ctx, tradeOrders); err != nil {
return err
}
status = consts.RechargeSuccess
updateData[rc.RechargeStatus] = status
updateData[rc.PaidAmount] = in.PaidAmount
@@ -251,6 +262,10 @@ func (s *sSysRechargeOrder) Execute(ctx context.Context, in *sysin.FinanceExecut
now := gtime.Now()
ledgerId := uint64(0)
if input.Decision == consts.FinanceDecisionApprove {
tradeOrders, lockErr := NewSysTradeOrder().lockBalancePendingOrders(ctx, order.MemberId)
if lockErr != nil {
return lockErr
}
wc := dao.WalletAccount.Columns()
var account *entity.WalletAccount
if err := handler.Model(dao.WalletAccount.Ctx(ctx), &handler.Option{FilterTenant: true}).Where(wc.MemberId, order.MemberId).Where(wc.Currency, order.Currency).LockUpdate().Scan(&account); err != nil {
@@ -259,6 +274,9 @@ func (s *sSysRechargeOrder) Execute(ctx context.Context, in *sysin.FinanceExecut
if account == nil || account.AccountStatus != 1 {
return gerror.New("会员钱包不存在或不可入账")
}
if input.PaidAmount > 0 && account.AvailableAmount > math.MaxInt64-input.PaidAmount {
return gerror.New("充值金额超出钱包处理范围")
}
after := account.AvailableAmount + input.PaidAmount
lc := dao.WalletLedger.Columns()
result, err := dao.WalletLedger.Ctx(ctx).Fields(lc.LedgerNo, lc.AccountId, lc.MemberId, lc.BizType, lc.BizNo, lc.EntryType, lc.Direction, lc.Amount, lc.BeforeAmount, lc.AfterAmount, lc.Currency, lc.IdempotencyKey, lc.Remark, lc.OperatorId, lc.OccurredAt).Hook(hook.SaveTenant).Data(g.Map{lc.LedgerNo: "WL" + gtime.Now().Format("YmdHis") + grand.S(7), lc.AccountId: account.Id, lc.MemberId: order.MemberId, lc.BizType: "recharge", lc.BizNo: order.RechargeNo, lc.EntryType: "available", lc.Direction: consts.WalletDirectionIncome, lc.Amount: input.PaidAmount, lc.BeforeAmount: account.AvailableAmount, lc.AfterAmount: after, lc.Currency: account.Currency, lc.IdempotencyKey: fmt.Sprintf("recharge:%d", order.Id), lc.Remark: input.ReasonText, lc.OperatorId: contexts.GetUserId(ctx), lc.OccurredAt: now}).Insert()
@@ -275,6 +293,9 @@ func (s *sSysRechargeOrder) Execute(ctx context.Context, in *sysin.FinanceExecut
if rows != 1 {
return gerror.New("钱包余额已变化,请重试")
}
if err = NewSysTradeOrder().completeBalancePendingOrders(ctx, tradeOrders); err != nil {
return err
}
_, err = s.model(ctx).WherePri(order.Id).Data(g.Map{rc.RechargeStatus: consts.RechargeSuccess, rc.PaidAmount: input.PaidAmount, rc.ExternalNo: input.ExternalNo, rc.LedgerId: ledgerId, rc.ReviewedAt: now, rc.CreditedAt: now, rc.UpdatedBy: contexts.GetUserId(ctx)}).Update()
if err != nil {
return err