订单相关以及佣金相关修复
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m57s

This commit is contained in:
2026-04-30 09:52:39 +08:00
parent 4f4e42f27e
commit 66e12e9629
29 changed files with 1199 additions and 181 deletions

View File

@@ -477,6 +477,28 @@ func (s *Service) fetchBuyerSnapshot(ctx context.Context, customerID uint) (phon
return phone, nickname
}
func (s *Service) buildPersonalCustomerOperatorSnapshot(ctx context.Context, customerID uint, nickname *string) (*uint, string, string) {
if customerID == 0 {
return nil, "", ""
}
name := ""
if nickname != nil {
name = strings.TrimSpace(*nickname)
}
if name == "" {
customer, err := s.personalCustomerStore.GetByID(ctx, customerID)
if err != nil {
s.logger.Warn("buildPersonalCustomerOperatorSnapshot: 查询个人客户失败", zap.Uint("customer_id", customerID), zap.Error(err))
} else if customer != nil {
name = strings.TrimSpace(customer.Nickname)
}
}
id := customerID
return &id, model.OperatorAccountTypePersonalCustomer, name
}
func (s *Service) buildPendingOrder(ctx context.Context, customerID uint, result *purchase_validation.PurchaseValidationResult, sellerCostPrice int64) (*model.Order, error) {
orderType := resolveOrderType(result)
if orderType == "" {
@@ -515,6 +537,7 @@ func (s *Service) buildPendingOrder(ctx context.Context, customerID uint, result
}
order.BuyerPhone, order.BuyerNickname = s.fetchBuyerSnapshot(ctx, customerID)
order.OperatorAccountID, order.OperatorAccountType, order.OperatorAccountName = s.buildPersonalCustomerOperatorSnapshot(ctx, customerID, order.BuyerNickname)
return order, nil
}

View File

@@ -78,8 +78,11 @@ func (s *Service) CalculateCommission(ctx context.Context, orderID uint) error {
return errors.Wrap(errors.CodeDatabaseError, err, "获取订单失败")
}
if order.CommissionStatus == model.CommissionStatusCalculated {
s.logger.Warn("订单佣金已计算,跳过", zap.String("order_id", fmt.Sprint(orderID)))
if order.CommissionStatus == model.CommissionStatusCompleted || order.CommissionStatus == model.CommissionStatusPendingReview {
s.logger.Warn("订单佣金流程已结束,跳过",
zap.String("order_id", fmt.Sprint(orderID)),
zap.Int("commission_status", order.CommissionStatus),
)
return nil
}
@@ -88,13 +91,8 @@ func (s *Service) CalculateCommission(ctx context.Context, orderID uint) error {
return errors.Wrap(errors.CodeInternalError, err, "计算成本价差佣金失败")
}
for _, record := range costDiffRecords {
if err := tx.Create(record).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "创建成本价差佣金记录失败")
}
if err := s.creditCommissionInTx(ctx, tx, record); err != nil {
return errors.Wrap(errors.CodeInternalError, err, "佣金入账失败")
}
if err := s.persistCommissionRecordsInTx(ctx, tx, costDiffRecords); err != nil {
return err
}
// 代购订单不触发一次性佣金和累计充值更新
@@ -110,8 +108,16 @@ func (s *Service) CalculateCommission(ctx context.Context, orderID uint) error {
}
}
if err := tx.Model(&model.Order{}).Where("id = ?", orderID).Update("commission_status", model.CommissionStatusCalculated).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "更新订单佣金状态失败")
commissionStatus, commissionResult, err := s.resolveOrderCommissionOutcomeInTx(tx, order.ID)
if err != nil {
return err
}
if err := tx.Model(&model.Order{}).Where("id = ?", orderID).Updates(map[string]any{
"commission_status": commissionStatus,
"commission_result": commissionResult,
}).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "更新订单佣金结果失败")
}
return nil
@@ -190,12 +196,7 @@ func (s *Service) CalculateCostDiffCommission(ctx context.Context, order *model.
Status: constants.CommissionStatusPendingReview,
Remark: fmt.Sprintf("套餐系列[%d]未分配给该代理(shop_id=%d),成本价差链路断裂,请人工核查", *order.SeriesID, currentShop.ID),
}
if createErr := s.commissionRecordStore.Create(ctx, pendingRecord); createErr != nil {
s.logger.Warn("创建待审佣金记录失败",
zap.Uint("shop_id", currentShop.ID),
zap.Uint("order_id", order.ID),
zap.Error(createErr))
}
records = append(records, pendingRecord)
break
}
@@ -284,13 +285,8 @@ func (s *Service) triggerOneTimeCommissionForCardInTx(ctx context.Context, tx *g
return err
}
for _, record := range records {
if err := tx.Create(record).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "创建一次性佣金记录失败")
}
if err := s.creditCommissionInTx(ctx, tx, record); err != nil {
return errors.Wrap(errors.CodeInternalError, err, "一次性佣金入账失败")
}
if err := s.persistCommissionRecordsInTx(ctx, tx, records); err != nil {
return err
}
card.SetFirstRechargeTriggeredBySeries(seriesID, true)
@@ -368,13 +364,8 @@ func (s *Service) triggerOneTimeCommissionForDeviceInTx(ctx context.Context, tx
return err
}
for _, record := range records {
if err := tx.Create(record).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "创建一次性佣金记录失败")
}
if err := s.creditCommissionInTx(ctx, tx, record); err != nil {
return errors.Wrap(errors.CodeInternalError, err, "一次性佣金入账失败")
}
if err := s.persistCommissionRecordsInTx(ctx, tx, records); err != nil {
return err
}
device.SetFirstRechargeTriggeredBySeries(seriesID, true)
@@ -544,12 +535,7 @@ func (s *Service) calculateChainOneTimeCommission(ctx context.Context, bottomSho
Status: constants.CommissionStatusPendingReview,
Remark: fmt.Sprintf("套餐系列[%d]未分配给该代理(shop_id=%d),一次性佣金链路断裂,请人工核查", seriesID, parentShopID),
}
if createErr := s.commissionRecordStore.Create(ctx, pendingRecord); createErr != nil {
s.logger.Warn("创建待审佣金记录失败",
zap.Uint("shop_id", parentShopID),
zap.Uint("order_id", order.ID),
zap.Error(createErr))
}
records = append(records, pendingRecord)
break
}
@@ -686,6 +672,48 @@ func (s *Service) creditCommissionInTx(ctx context.Context, tx *gorm.DB, record
return nil
}
func (s *Service) persistCommissionRecordsInTx(ctx context.Context, tx *gorm.DB, records []*model.CommissionRecord) error {
for _, record := range records {
if err := tx.Create(record).Error; err != nil {
return errors.Wrap(errors.CodeDatabaseError, err, "创建佣金记录失败")
}
if record.Status == constants.CommissionStatusPendingReview {
continue
}
if err := s.creditCommissionInTx(ctx, tx, record); err != nil {
return errors.Wrap(errors.CodeInternalError, err, "佣金入账失败")
}
}
return nil
}
func (s *Service) resolveOrderCommissionOutcomeInTx(tx *gorm.DB, orderID uint) (int, int, error) {
var pendingReviewCount int64
if err := tx.Model(&model.CommissionRecord{}).
Where("order_id = ? AND status = ?", orderID, constants.CommissionStatusPendingReview).
Count(&pendingReviewCount).Error; err != nil {
return 0, 0, errors.Wrap(errors.CodeDatabaseError, err, "统计待人工处理佣金记录失败")
}
if pendingReviewCount > 0 {
return model.CommissionStatusPendingReview, model.CommissionResultChainBroken, nil
}
var releasedCount int64
if err := tx.Model(&model.CommissionRecord{}).
Where("order_id = ? AND status = ? AND amount > 0", orderID, constants.CommissionStatusReleased).
Count(&releasedCount).Error; err != nil {
return 0, 0, errors.Wrap(errors.CodeDatabaseError, err, "统计已发放佣金记录失败")
}
if releasedCount > 0 {
return model.CommissionStatusCompleted, model.CommissionResultHasAmount, nil
}
return model.CommissionStatusCompleted, model.CommissionResultNoAmount, nil
}
func (s *Service) CreditCommission(ctx context.Context, record *model.CommissionRecord) error {
return s.db.Transaction(func(tx *gorm.DB) error {
return s.creditCommissionInTx(ctx, tx, record)

View File

@@ -206,6 +206,7 @@ func (s *Service) CreateAdminOrder(ctx context.Context, req *dto.CreateAdminOrde
}
userID := middleware.GetUserIDFromContext(ctx)
operatorAccountID, operatorAccountType, operatorAccountName := s.buildAccountOperatorSnapshot(ctx, userID, operatorUserType)
// 提取资源所属店铺ID
var seriesID *uint
@@ -261,44 +262,44 @@ func (s *Service) CreateAdminOrder(ctx context.Context, req *dto.CreateAdminOrde
actualPaidAmount = &actualPaidAmountVal
purchaseRole = model.PurchaseRoleSelfPurchase
} else {
isPlatformOwned := resourceShopID == nil || *resourceShopID == 0
isPlatformOwned := resourceShopID == nil || *resourceShopID == 0
if isPlatformOwned {
// ==== 子场景 1.1:平台自营(资源未分配给代理商)====
// 平台直接销售给终端用户,无代理商参与,使用零售价,无需查询分配配置
orderBuyerType = model.BuyerTypePersonal
orderBuyerID = 0
paymentMethod = model.PaymentMethodOffline
paymentStatus = model.PaymentStatusPaid
paidAt = &now
isPurchaseOnBehalf = false
sellerCostPrice = 0
operatorID = nil
operatorType = constants.OwnerTypePlatform
purchaseRole = model.PurchaseRoleSelfPurchase
actualPaidAmount = nil
} else {
// ==== 子场景 1.2:平台代购(资源属于代理商,平台代为购买)====
purchaseBuyerID, buyerCostPriceMap, buyerTotalCost, purchasePaidAt, err := s.resolvePurchaseOnBehalfInfo(ctx, validationResult)
if err != nil {
return nil, err
if isPlatformOwned {
// ==== 子场景 1.1:平台自营(资源未分配给代理商)====
// 平台直接销售给终端用户,无代理商参与,使用零售价,无需查询分配配置
orderBuyerType = model.BuyerTypePersonal
orderBuyerID = 0
paymentMethod = model.PaymentMethodOffline
paymentStatus = model.PaymentStatusPaid
paidAt = &now
isPurchaseOnBehalf = false
sellerCostPrice = 0
operatorID = nil
operatorType = constants.OwnerTypePlatform
purchaseRole = model.PurchaseRoleSelfPurchase
actualPaidAmount = nil
} else {
// ==== 子场景 1.2:平台代购(资源属于代理商,平台代为购买)====
purchaseBuyerID, buyerCostPriceMap, buyerTotalCost, purchasePaidAt, err := s.resolvePurchaseOnBehalfInfo(ctx, validationResult)
if err != nil {
return nil, err
}
orderBuyerType = model.BuyerTypeAgent
orderBuyerID = purchaseBuyerID
itemUnitPriceMap = buyerCostPriceMap
totalAmount = buyerTotalCost
paymentMethod = model.PaymentMethodOffline
paymentStatus = model.PaymentStatusPaid
paidAt = purchasePaidAt
isPurchaseOnBehalf = true
sellerCostPrice = buyerTotalCost
// 设置操作者信息(平台代购)
operatorID = nil
operatorType = constants.OwnerTypePlatform
purchaseRole = model.PurchaseRolePurchasedByPlatform
actualPaidAmount = nil
}
orderBuyerType = model.BuyerTypeAgent
orderBuyerID = purchaseBuyerID
itemUnitPriceMap = buyerCostPriceMap
totalAmount = buyerTotalCost
paymentMethod = model.PaymentMethodOffline
paymentStatus = model.PaymentStatusPaid
paidAt = purchasePaidAt
isPurchaseOnBehalf = true
sellerCostPrice = buyerTotalCost
// 设置操作者信息(平台代购)
operatorID = nil
operatorType = constants.OwnerTypePlatform
purchaseRole = model.PurchaseRolePurchasedByPlatform
actualPaidAmount = nil
}
}
} else if req.PaymentMethod == model.PaymentMethodWallet {
@@ -445,6 +446,9 @@ func (s *Service) CreateAdminOrder(ctx context.Context, req *dto.CreateAdminOrde
SellerShopID: sellerShopID,
SellerCostPrice: sellerCostPrice,
IsPurchaseOnBehalf: isPurchaseOnBehalf,
OperatorAccountID: operatorAccountID,
OperatorAccountType: operatorAccountType,
OperatorAccountName: operatorAccountName,
OperatorID: operatorID,
OperatorType: operatorType,
ActualPaidAmount: actualPaidAmount,
@@ -475,7 +479,7 @@ func (s *Service) CreateAdminOrder(ctx context.Context, req *dto.CreateAdminOrde
s.enqueueCommissionCalculation(ctx, order.ID)
}
s.markOrderCreated(ctx, idempotencyKey, order.ID)
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
} else if req.PaymentMethod == model.PaymentMethodWallet {
// 钱包支付:创建订单、扣款、激活套餐(在事务中完成)
@@ -489,7 +493,7 @@ func (s *Service) CreateAdminOrder(ctx context.Context, req *dto.CreateAdminOrde
return nil, err
}
s.markOrderCreated(ctx, idempotencyKey, order.ID)
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
} else {
// 不应该到这里DTO 验证已拒绝其他支付方式)
@@ -563,6 +567,8 @@ func (s *Service) CreateH5Order(ctx context.Context, req *dto.CreateOrderRequest
}
userID := middleware.GetUserIDFromContext(ctx)
operatorUserType := middleware.GetUserTypeFromContext(ctx)
operatorAccountID, operatorAccountType, operatorAccountName := s.buildAccountOperatorSnapshot(ctx, userID, operatorUserType)
// 提取资源所属店铺ID
var resourceShopID *uint
@@ -732,6 +738,9 @@ func (s *Service) CreateH5Order(ctx context.Context, req *dto.CreateOrderRequest
SellerShopID: sellerShopID,
SellerCostPrice: sellerCostPrice,
IsPurchaseOnBehalf: isPurchaseOnBehalf,
OperatorAccountID: operatorAccountID,
OperatorAccountType: operatorAccountType,
OperatorAccountName: operatorAccountName,
OperatorID: operatorID,
OperatorType: operatorType,
ActualPaidAmount: actualPaidAmount,
@@ -752,7 +761,7 @@ func (s *Service) CreateH5Order(ctx context.Context, req *dto.CreateOrderRequest
}
s.enqueueCommissionCalculation(ctx, order.ID)
s.markOrderCreated(ctx, idempotencyKey, order.ID)
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
} else if req.PaymentMethod == model.PaymentMethodWallet {
// 钱包支付:创建订单、扣款、激活套餐(在事务中完成)
@@ -766,7 +775,7 @@ func (s *Service) CreateH5Order(ctx context.Context, req *dto.CreateOrderRequest
return nil, err
}
s.markOrderCreated(ctx, idempotencyKey, order.ID)
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
} else {
// 其他支付方式创建待支付订单H5 端支持 wechat/alipay
@@ -777,7 +786,7 @@ func (s *Service) CreateH5Order(ctx context.Context, req *dto.CreateOrderRequest
return nil, err
}
s.markOrderCreated(ctx, idempotencyKey, order.ID)
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
}
}
@@ -909,6 +918,57 @@ func (s *Service) fetchBuyerSnapshot(ctx context.Context, customerID uint) (phon
return phone, nickname
}
func (s *Service) buildAccountOperatorSnapshot(ctx context.Context, userID uint, userType int) (*uint, string, string) {
if userID == 0 {
return nil, "", ""
}
var account model.Account
if err := s.db.WithContext(ctx).Where("id = ?", userID).First(&account).Error; err != nil {
s.logger.Warn("buildAccountOperatorSnapshot: 查询账号失败", zap.Uint("user_id", userID), zap.Error(err))
id := userID
return &id, orderOperatorAccountTypeFromUserType(userType), ""
}
id := account.ID
return &id, orderOperatorAccountTypeFromUserType(account.UserType), account.Username
}
func (s *Service) buildPersonalCustomerOperatorSnapshot(ctx context.Context, customerID uint, nickname *string) (*uint, string, string) {
if customerID == 0 {
return nil, "", ""
}
name := ""
if nickname != nil {
name = strings.TrimSpace(*nickname)
}
if name == "" && s.personalCustomerStore != nil {
customer, err := s.personalCustomerStore.GetByID(ctx, customerID)
if err != nil {
s.logger.Warn("buildPersonalCustomerOperatorSnapshot: 查询个人客户失败", zap.Uint("customer_id", customerID), zap.Error(err))
} else if customer != nil {
name = strings.TrimSpace(customer.Nickname)
}
}
id := customerID
return &id, model.OperatorAccountTypePersonalCustomer, name
}
func orderOperatorAccountTypeFromUserType(userType int) string {
switch userType {
case constants.UserTypeSuperAdmin, constants.UserTypePlatform:
return model.OperatorAccountTypePlatform
case constants.UserTypeAgent:
return model.OperatorAccountTypeAgent
case constants.UserTypeEnterprise:
return model.OperatorAccountTypeEnterprise
default:
return ""
}
}
// getCostPrice 查询店铺对套餐的成本价
// shopID: 店铺ID
// packageID: 套餐ID
@@ -1078,9 +1138,8 @@ func (s *Service) createOrderWithWalletPayment(ctx context.Context, order *model
return err
}
// 3. 事务外:佣金计算(异步)
// 仅兼容极少数“平台代购但走钱包事务”的特殊场景,普通钱包订单不在此处入队佣金
if order.PurchaseRole == model.PurchaseRolePurchasedByPlatform {
// 3. 事务外:所有已支付且适用差价佣金的订单都进入佣金计算
if order.CommissionStatus == model.CommissionStatusPending {
s.enqueueCommissionCalculation(ctx, order.ID)
}
@@ -1113,7 +1172,7 @@ func (s *Service) Get(ctx context.Context, id uint) (*dto.OrderResponse, error)
return nil, err
}
return s.buildOrderResponse(order, items), nil
return s.buildOrderResponse(ctx, order, items), nil
}
func (s *Service) List(ctx context.Context, req *dto.OrderListRequest, buyerType string, buyerID uint) (*dto.OrderListResponse, error) {
@@ -1204,7 +1263,7 @@ func (s *Service) List(ctx context.Context, req *dto.OrderListRequest, buyerType
var list []*dto.OrderResponse
for _, o := range orders {
list = append(list, s.buildOrderResponse(o, itemsMap[o.ID]))
list = append(list, s.buildOrderResponse(ctx, o, itemsMap[o.ID]))
}
return &dto.OrderListResponse{
@@ -1478,6 +1537,7 @@ func (s *Service) WalletPay(ctx context.Context, orderID uint, buyerType string,
// 根据资源类型选择对应的钱包系统
now := time.Now()
actualPaidAmount := order.TotalAmount
shouldEnqueueCommission := false
if resourceType == "shop" {
// 代理钱包系统(店铺)
@@ -1527,6 +1587,7 @@ func (s *Service) WalletPay(ctx context.Context, orderID uint, buyerType string,
actualPaidAmountSnapshot := actualPaidAmount
order.ActualPaidAmount = &actualPaidAmountSnapshot
shouldEnqueueCommission = true
walletResult := tx.Model(&model.AgentWallet{}).
Where("id = ? AND balance >= ? AND version = ?", wallet.ID, order.TotalAmount, wallet.Version).
@@ -1645,7 +1706,9 @@ func (s *Service) WalletPay(ctx context.Context, orderID uint, buyerType string,
return err
}
s.enqueueCommissionCalculation(ctx, orderID)
if shouldEnqueueCommission && order.CommissionStatus == model.CommissionStatusPending {
s.enqueueCommissionCalculation(ctx, orderID)
}
return nil
}
@@ -1659,6 +1722,8 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, pay
}
now := time.Now()
shouldResumeAfterPayment := false
shouldEnqueueCommission := false
err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
result := tx.Model(&model.Order{}).
Where("id = ? AND payment_status = ?", order.ID, model.PaymentStatusPending).
@@ -1694,6 +1759,8 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, pay
// 回调更新成功后,同步内存对象,确保激活套餐时写入 paid_amount 快照
actualPaidAmountSnapshot := actualPaidAmount
order.ActualPaidAmount = &actualPaidAmountSnapshot
shouldResumeAfterPayment = true
shouldEnqueueCommission = true
return s.activatePackage(ctx, tx, order)
})
@@ -1702,8 +1769,12 @@ func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, pay
return err
}
s.tryResumeAfterPayment(ctx, order)
s.enqueueCommissionCalculation(ctx, order.ID)
if shouldResumeAfterPayment {
s.tryResumeAfterPayment(ctx, order)
}
if shouldEnqueueCommission && order.CommissionStatus == model.CommissionStatusPending {
s.enqueueCommissionCalculation(ctx, order.ID)
}
return nil
}
@@ -2169,24 +2240,24 @@ func (s *Service) activateAddonPackage(ctx context.Context, tx *gorm.DB, order *
Creator: order.Creator,
Updater: order.Creator,
},
OrderID: order.ID,
OrderNo: order.OrderNo,
PackageID: pkg.ID,
PackageName: pkg.PackageName,
UsageType: order.OrderType,
DataLimitMB: pkg.RealDataMB,
OrderID: order.ID,
OrderNo: order.OrderNo,
PackageID: pkg.ID,
PackageName: pkg.PackageName,
UsageType: order.OrderType,
DataLimitMB: pkg.RealDataMB,
VirtualTotalMBSnapshot: virtualTotalMBSnapshot,
DisplayGainRatioSnapshot: displayGainRatioSnapshot,
EnableVirtualDataSnapshot: enableVirtualDataSnapshot,
Status: status,
Priority: priority,
MasterUsageID: &mainPackage.ID,
ActivatedAt: &activatedAt,
ExpiresAt: &expiresAt,
DataResetCycle: pkg.DataResetCycle,
PaidAmount: order.ActualPaidAmount,
PackagePriceConfigStatus: pkg.PriceConfigStatus,
PackageIsGift: pkg.IsGift,
Status: status,
Priority: priority,
MasterUsageID: &mainPackage.ID,
ActivatedAt: &activatedAt,
ExpiresAt: &expiresAt,
DataResetCycle: pkg.DataResetCycle,
PaidAmount: order.ActualPaidAmount,
PackagePriceConfigStatus: pkg.PriceConfigStatus,
PackageIsGift: pkg.IsGift,
}
if carrierType == "iot_card" {
@@ -2223,7 +2294,7 @@ func (s *Service) enqueueCommissionCalculation(ctx context.Context, orderID uint
zap.String("task_type", constants.TaskTypeCommission))
}
func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderItem) *dto.OrderResponse {
func (s *Service) buildOrderResponse(ctx context.Context, order *model.Order, items []*model.OrderItem) *dto.OrderResponse {
var itemResponses []*dto.OrderItemResponse
for _, item := range items {
itemResponses = append(itemResponses, &dto.OrderItemResponse{
@@ -2249,14 +2320,8 @@ func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderIte
statusText = "已退款"
}
// 查询操作者名称
operatorName := ""
if order.OperatorType == "agent" && order.OperatorID != nil {
var shop model.Shop
if err := s.db.Where("id = ?", *order.OperatorID).First(&shop).Error; err == nil {
operatorName = shop.ShopName
}
}
operatorID, operatorType, operatorName := s.resolveOrderOperatorView(ctx, order)
sellerShopName := s.resolveSellerShopName(ctx, order.SellerShopID)
// 生成派生字段
isPurchasedByParent := order.PurchaseRole == model.PurchaseRolePurchasedByParent
@@ -2288,6 +2353,7 @@ func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderIte
actualPaidAmountSnapshot := order.TotalAmount
actualPaidAmount = &actualPaidAmountSnapshot
}
commissionResult := s.resolveOrderCommissionResult(ctx, order)
return &dto.OrderResponse{
ID: order.ID,
@@ -2308,10 +2374,14 @@ func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderIte
IsPurchaseOnBehalf: order.IsPurchaseOnBehalf,
CommissionStatus: order.CommissionStatus,
CommissionStatusName: constants.GetOrderCommissionStatusName(order.CommissionStatus),
CommissionResult: commissionResult,
CommissionResultName: constants.GetOrderCommissionResultName(commissionResult),
CommissionConfigVersion: order.CommissionConfigVersion,
SellerShopID: order.SellerShopID,
SellerShopName: sellerShopName,
OperatorID: order.OperatorID,
OperatorType: order.OperatorType,
OperatorID: operatorID,
OperatorType: operatorType,
OperatorName: operatorName,
ActualPaidAmount: actualPaidAmount,
@@ -2331,6 +2401,90 @@ func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderIte
}
}
func (s *Service) resolveOrderOperatorView(ctx context.Context, order *model.Order) (*uint, string, string) {
if order.OperatorAccountID != nil || order.OperatorAccountType != "" || order.OperatorAccountName != "" {
return order.OperatorAccountID, order.OperatorAccountType, order.OperatorAccountName
}
if order.Source == constants.OrderSourceClient && order.BuyerType == model.BuyerTypePersonal {
operatorID, operatorType, operatorName := s.buildPersonalCustomerOperatorSnapshot(ctx, order.BuyerID, order.BuyerNickname)
if operatorID != nil || operatorType != "" || operatorName != "" {
return operatorID, operatorType, operatorName
}
}
if order.Creator > 0 {
operatorID, operatorType, operatorName := s.buildAccountOperatorSnapshot(ctx, order.Creator, 0)
if operatorID != nil || operatorType != "" || operatorName != "" {
return operatorID, operatorType, operatorName
}
}
if order.OperatorType == model.OperatorAccountTypeAgent && order.OperatorID != nil {
return nil, model.OperatorAccountTypeAgent, s.resolveLegacyOperatorShopName(ctx, *order.OperatorID)
}
if order.OperatorType == model.OperatorAccountTypePlatform {
return nil, model.OperatorAccountTypePlatform, "平台"
}
return nil, "", ""
}
func (s *Service) resolveLegacyOperatorShopName(ctx context.Context, shopID uint) string {
if shopID == 0 {
return ""
}
var shop model.Shop
if err := s.db.WithContext(ctx).Where("id = ?", shopID).First(&shop).Error; err != nil {
return ""
}
return shop.ShopName
}
func (s *Service) resolveSellerShopName(ctx context.Context, sellerShopID *uint) string {
if sellerShopID == nil || *sellerShopID == 0 {
return ""
}
var shop model.Shop
if err := s.db.WithContext(ctx).Where("id = ?", *sellerShopID).First(&shop).Error; err != nil {
return ""
}
return shop.ShopName
}
func (s *Service) resolveOrderCommissionResult(ctx context.Context, order *model.Order) int {
if order.CommissionResult != model.CommissionResultUnknown {
return order.CommissionResult
}
if order.CommissionStatus == model.CommissionStatusPending {
return model.CommissionResultUnknown
}
var pendingReviewCount int64
if err := s.db.WithContext(ctx).Model(&model.CommissionRecord{}).
Where("order_id = ? AND status = ?", order.ID, constants.CommissionStatusPendingReview).
Count(&pendingReviewCount).Error; err == nil && pendingReviewCount > 0 {
return model.CommissionResultChainBroken
}
var releasedCount int64
if err := s.db.WithContext(ctx).Model(&model.CommissionRecord{}).
Where("order_id = ? AND status = ? AND amount > 0", order.ID, constants.CommissionStatusReleased).
Count(&releasedCount).Error; err == nil && releasedCount > 0 {
return model.CommissionResultHasAmount
}
if order.CommissionStatus == model.CommissionStatusCompleted {
return model.CommissionResultNoAmount
}
return model.CommissionResultUnknown
}
// WechatPayJSAPI 发起微信 JSAPI 支付
// 通过 order.PaymentConfigID 动态加载支付配置,支持多商户场景
func (s *Service) WechatPayJSAPI(ctx context.Context, orderID uint, openID string, buyerType string, buyerID uint) (*dto.WechatPayJSAPIResponse, error) {

View File

@@ -627,7 +627,7 @@ func (s *Service) CreateWithdrawalRequest(ctx context.Context, shopID uint, req
ActualAmount: actualAmount,
WithdrawalMethod: req.WithdrawalMethod,
AccountInfo: accountInfoJSON,
Status: 1, // 待审核
Status: constants.WithdrawalStatusPending, // 待审核
}
withdrawalRequest.Creator = currentUserID
withdrawalRequest.Updater = currentUserID