This commit is contained in:
2025-10-23 19:17:27 +08:00
parent 050809c471
commit 0acfb80849
9 changed files with 320 additions and 29 deletions

View File

@@ -35,6 +35,10 @@ service main {
@doc "订单退款" @doc "订单退款"
@handler AdminRefundOrder @handler AdminRefundOrder
post /refund/:id (AdminRefundOrderReq) returns (AdminRefundOrderResp) post /refund/:id (AdminRefundOrderReq) returns (AdminRefundOrderResp)
@doc "重新执行代理处理"
@handler AdminRetryAgentProcess
post /retry-agent-process/:id (AdminRetryAgentProcessReq) returns (AdminRetryAgentProcessResp)
} }
type ( type (
@@ -79,6 +83,8 @@ type (
PayTime string `json:"pay_time"` // 支付时间 PayTime string `json:"pay_time"` // 支付时间
RefundTime string `json:"refund_time"` // 退款时间 RefundTime string `json:"refund_time"` // 退款时间
IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是 IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
} }
// 详情请求 // 详情请求
@@ -102,6 +108,8 @@ type (
RefundTime string `json:"refund_time"` // 退款时间 RefundTime string `json:"refund_time"` // 退款时间
IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是 IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是
UpdateTime string `json:"update_time"` // 更新时间 UpdateTime string `json:"update_time"` // 更新时间
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
} }
// 创建请求 // 创建请求
@@ -164,4 +172,16 @@ type (
RefundNo string `json:"refund_no"` // 退款单号 RefundNo string `json:"refund_no"` // 退款单号
Amount float64 `json:"amount"` // 退款金额 Amount float64 `json:"amount"` // 退款金额
} }
// 重新执行代理处理请求
AdminRetryAgentProcessReq {
Id int64 `path:"id"` // 订单ID
}
// 重新执行代理处理响应
AdminRetryAgentProcessResp {
Status string `json:"status"` // 执行状态success-成功already_processed-已处理failed-失败
Message string `json:"message"` // 执行结果消息
ProcessedAt string `json:"processed_at"` // 处理时间
}
) )

View File

@@ -0,0 +1,29 @@
package admin_order
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"hm-server/app/main/api/internal/logic/admin_order"
"hm-server/app/main/api/internal/svc"
"hm-server/app/main/api/internal/types"
)
// 重新执行代理处理
func AdminRetryAgentProcessHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.AdminRetryAgentProcessReq
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := admin_order.NewAdminRetryAgentProcessLogic(r.Context(), svcCtx)
resp, err := l.AdminRetryAgentProcess(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -1,4 +1,6 @@
// Code generated by goctl. DO NOT EDIT. // Code generated by goctl. DO NOT EDIT.
// goctl 1.8.4
package handler package handler
import ( import (
@@ -310,6 +312,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/refund/:id", Path: "/refund/:id",
Handler: admin_order.AdminRefundOrderHandler(serverCtx), Handler: admin_order.AdminRefundOrderHandler(serverCtx),
}, },
{
// 重新执行代理处理
Method: http.MethodPost,
Path: "/retry-agent-process/:id",
Handler: admin_order.AdminRetryAgentProcessHandler(serverCtx),
},
{ {
// 更新订单 // 更新订单
Method: http.MethodPut, Method: http.MethodPut,

View File

@@ -47,6 +47,36 @@ func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderD
isPromotion = 1 isPromotion = 1
} }
// 判断是否为代理订单并获取代理处理状态
var isAgentOrder bool
var agentProcessStatus string
agentOrder, err := l.svcCtx.AgentOrderModel.FindOneByOrderId(l.ctx, order.Id)
if err == nil && agentOrder != nil {
isAgentOrder = true
// 查询代理佣金记录
commissions, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx,
l.svcCtx.AgentCommissionModel.SelectBuilder().Where("order_id = ?", order.Id), "")
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询代理佣金失败 err: %v", err)
}
if len(commissions) > 0 {
agentProcessStatus = "success"
} else {
// 检查订单状态,如果是已支付但无佣金记录,则为待处理或失败
if order.Status == "paid" {
agentProcessStatus = "pending"
} else {
agentProcessStatus = "failed"
}
}
} else {
isAgentOrder = false
agentProcessStatus = "not_agent"
}
// 获取查询状态 // 获取查询状态
var queryState string var queryState string
builder := l.svcCtx.QueryModel.SelectBuilder().Where("order_id = ?", order.Id).Columns("query_state") builder := l.svcCtx.QueryModel.SelectBuilder().Where("order_id = ?", order.Id).Columns("query_state")
@@ -90,6 +120,8 @@ func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderD
UpdateTime: order.UpdateTime.Format("2006-01-02 15:04:05"), UpdateTime: order.UpdateTime.Format("2006-01-02 15:04:05"),
IsPromotion: isPromotion, IsPromotion: isPromotion,
QueryState: queryState, QueryState: queryState,
IsAgentOrder: isAgentOrder,
AgentProcessStatus: agentProcessStatus,
} }
// 处理可选字段 // 处理可选字段

View File

@@ -102,6 +102,8 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
// 并发获取产品信息和查询状态 // 并发获取产品信息和查询状态
productMap := make(map[int64]string) productMap := make(map[int64]string)
queryStateMap := make(map[int64]string) queryStateMap := make(map[int64]string)
agentOrderMap := make(map[int64]bool) // 代理订单映射
agentProcessStatusMap := make(map[int64]string) // 代理处理状态映射
var mu sync.Mutex var mu sync.Mutex
// 批量获取查询状态 // 批量获取查询状态
@@ -160,6 +162,60 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
} }
} }
} }
// 批量获取代理订单状态
agentOrders, err := l.svcCtx.AgentOrderModel.FindAll(l.ctx,
l.svcCtx.AgentOrderModel.SelectBuilder().Where(squirrel.Eq{"order_id": orderIds}), "")
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 批量查询代理订单失败 err: %v", err)
}
// 记录代理订单
for _, agentOrder := range agentOrders {
agentOrderMap[agentOrder.OrderId] = true
}
// 对于代理订单,查询代理处理状态
if len(agentOrders) > 0 {
agentOrderIds := make([]int64, 0, len(agentOrders))
for _, agentOrder := range agentOrders {
agentOrderIds = append(agentOrderIds, agentOrder.OrderId)
}
// 查询代理佣金记录
commissions, err := l.svcCtx.AgentCommissionModel.FindAll(l.ctx,
l.svcCtx.AgentCommissionModel.SelectBuilder().Where(squirrel.Eq{"order_id": agentOrderIds}), "")
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 批量查询代理佣金失败 err: %v", err)
}
// 记录有佣金记录的订单为处理成功
processedOrderIds := make(map[int64]bool)
for _, commission := range commissions {
processedOrderIds[commission.OrderId] = true
}
// 创建订单状态映射,避免重复查找
orderStatusMap := make(map[int64]string)
for _, order := range orders {
orderStatusMap[order.Id] = order.Status
}
// 设置代理处理状态
for _, agentOrder := range agentOrders {
orderId := agentOrder.OrderId
if processedOrderIds[orderId] {
agentProcessStatusMap[orderId] = "success"
} else {
// 检查订单状态,如果是已支付但无佣金记录,则为待处理或失败
if orderStatusMap[orderId] == "paid" {
agentProcessStatusMap[orderId] = "pending"
} else {
agentProcessStatusMap[orderId] = "failed"
}
}
}
}
} }
// 并发获取产品信息 // 并发获取产品信息
@@ -222,6 +278,16 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR
if err == nil && promotionOrder != nil { if err == nil && promotionOrder != nil {
item.IsPromotion = 1 item.IsPromotion = 1
} }
// 设置代理订单相关字段
if agentOrderMap[order.Id] {
item.IsAgentOrder = true
item.AgentProcessStatus = agentProcessStatusMap[order.Id]
} else {
item.IsAgentOrder = false
item.AgentProcessStatus = "not_agent"
}
resp.Items = append(resp.Items, item) resp.Items = append(resp.Items, item)
} }

View File

@@ -0,0 +1,56 @@
package admin_order
import (
"context"
"time"
"hm-server/app/main/api/internal/svc"
"hm-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminRetryAgentProcessLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 重新执行代理处理
func NewAdminRetryAgentProcessLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRetryAgentProcessLogic {
return &AdminRetryAgentProcessLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminRetryAgentProcessLogic) AdminRetryAgentProcess(req *types.AdminRetryAgentProcessReq) (resp *types.AdminRetryAgentProcessResp, err error) {
// 调用AgentService的重新执行代理处理方法
err = l.svcCtx.AgentService.RetryAgentProcess(l.ctx, req.Id)
if err != nil {
// 检查是否是"已经处理"的错误
if err.Error() == "代理处理已经成功,无需重新执行" {
return &types.AdminRetryAgentProcessResp{
Status: "already_processed",
Message: "代理处理已经成功,无需重新执行",
ProcessedAt: time.Now().Format("2006-01-02 15:04:05"),
}, nil
}
// 其他错误
logx.Errorf("重新执行代理处理失败订单ID: %d, 错误: %v", req.Id, err)
return &types.AdminRetryAgentProcessResp{
Status: "failed",
Message: err.Error(),
ProcessedAt: time.Now().Format("2006-01-02 15:04:05"),
}, nil
}
// 执行成功
return &types.AdminRetryAgentProcessResp{
Status: "success",
Message: "代理处理重新执行成功",
ProcessedAt: time.Now().Format("2006-01-02 15:04:05"),
}, nil
}

View File

@@ -12,6 +12,7 @@ import (
type AgentService struct { type AgentService struct {
config config.Config config config.Config
OrderModel model.OrderModel
AgentModel model.AgentModel AgentModel model.AgentModel
AgentAuditModel model.AgentAuditModel AgentAuditModel model.AgentAuditModel
AgentClosureModel model.AgentClosureModel AgentClosureModel model.AgentClosureModel
@@ -30,7 +31,7 @@ type AgentService struct {
AgentWithdrawalModel model.AgentWithdrawalModel AgentWithdrawalModel model.AgentWithdrawalModel
} }
func NewAgentService(c config.Config, agentModel model.AgentModel, agentAuditModel model.AgentAuditModel, func NewAgentService(c config.Config, orderModel model.OrderModel, agentModel model.AgentModel, agentAuditModel model.AgentAuditModel,
agentClosureModel model.AgentClosureModel, agentCommissionModel model.AgentCommissionModel, agentClosureModel model.AgentClosureModel, agentCommissionModel model.AgentCommissionModel,
agentCommissionDeductionModel model.AgentCommissionDeductionModel, agentWalletModel model.AgentWalletModel, agentLinkModel model.AgentLinkModel, agentOrderModel model.AgentOrderModel, agentRewardsModel model.AgentRewardsModel, agentCommissionDeductionModel model.AgentCommissionDeductionModel, agentWalletModel model.AgentWalletModel, agentLinkModel model.AgentLinkModel, agentOrderModel model.AgentOrderModel, agentRewardsModel model.AgentRewardsModel,
agentMembershipConfigModel model.AgentMembershipConfigModel, agentMembershipConfigModel model.AgentMembershipConfigModel,
@@ -41,6 +42,7 @@ func NewAgentService(c config.Config, agentModel model.AgentModel, agentAuditMod
return &AgentService{ return &AgentService{
config: c, config: c,
OrderModel: orderModel,
AgentModel: agentModel, AgentModel: agentModel,
AgentAuditModel: agentAuditModel, AgentAuditModel: agentAuditModel,
AgentClosureModel: agentClosureModel, AgentClosureModel: agentClosureModel,
@@ -271,6 +273,10 @@ func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, A
// 拥有则查看该上级设定的成本 // 拥有则查看该上级设定的成本
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
if findAgentMembershipUserConfigModelErr != nil { if findAgentMembershipUserConfigModelErr != nil {
// 如果上级没有配置该产品的定价规则,则跳过成本计算
if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) {
return 0, nil
}
return 0, findAgentMembershipUserConfigModelErr return 0, findAgentMembershipUserConfigModelErr
} }
@@ -301,6 +307,10 @@ func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64
// 拥有则查看该上级设定的成本 // 拥有则查看该上级设定的成本
agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID)
if findAgentMembershipUserConfigModelErr != nil { if findAgentMembershipUserConfigModelErr != nil {
// 如果上级没有配置该产品的定价规则,则跳过成本计算
if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) {
return 0, nil
}
return 0, findAgentMembershipUserConfigModelErr return 0, findAgentMembershipUserConfigModelErr
} }
@@ -522,3 +532,57 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi
return nil return nil
} }
// CheckAgentProcessStatus 检查代理处理事务是否已成功
func (l *AgentService) CheckAgentProcessStatus(ctx context.Context, orderID int64) (bool, error) {
// 检查是否存在代理订单记录
_, err := l.AgentOrderModel.FindOneByOrderId(ctx, orderID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
// 没有代理订单记录,说明不是代理推广订单
return true, nil
}
return false, err
}
// 检查是否存在代理佣金记录
// 使用SelectBuilder查询该订单的佣金记录
selectBuilder := l.AgentCommissionModel.SelectBuilder()
selectBuilder = selectBuilder.Where("order_id = ?", orderID)
selectBuilder = selectBuilder.Where("del_state = ?", 0) // 未删除
commissions, err := l.AgentCommissionModel.FindAll(ctx, selectBuilder, "")
if err != nil {
return false, err
}
// 如果存在佣金记录,说明代理处理已成功
return len(commissions) > 0, nil
}
// RetryAgentProcess 重新执行代理处理事务
func (l *AgentService) RetryAgentProcess(ctx context.Context, orderID int64) error {
// 首先检查订单是否存在
order, err := l.OrderModel.FindOne(ctx, orderID)
if err != nil {
return err
}
// 检查订单状态是否为已支付
if order.Status != "paid" {
return errors.New("订单状态不是已支付,无法执行代理处理")
}
// 检查代理处理是否已经成功
alreadyProcessed, err := l.CheckAgentProcessStatus(ctx, orderID)
if err != nil {
return err
}
if alreadyProcessed {
return errors.New("代理处理已经成功,无需重新执行")
}
// 执行代理处理
return l.AgentProcess(ctx, order)
}

View File

@@ -192,7 +192,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
apiRequestService := service.NewApiRequestService(c, featureModel, productFeatureModel, tianyuanapi) apiRequestService := service.NewApiRequestService(c, featureModel, productFeatureModel, tianyuanapi)
verificationService := service.NewVerificationService(c, tianyuanapi, apiRequestService) verificationService := service.NewVerificationService(c, tianyuanapi, apiRequestService)
asynqService := service.NewAsynqService(c) asynqService := service.NewAsynqService(c)
agentService := service.NewAgentService(c, agentModel, agentAuditModel, agentClosureModel, agentService := service.NewAgentService(c, orderModel, agentModel, agentAuditModel, agentClosureModel,
agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel,
agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel,
agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel, agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel,

View File

@@ -1,4 +1,6 @@
// Code generated by goctl. DO NOT EDIT. // Code generated by goctl. DO NOT EDIT.
// goctl 1.8.4
package types package types
type ActiveReward struct { type ActiveReward struct {
@@ -447,6 +449,8 @@ type AdminGetOrderDetailResp struct {
RefundTime string `json:"refund_time"` // 退款时间 RefundTime string `json:"refund_time"` // 退款时间
IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是 IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是
UpdateTime string `json:"update_time"` // 更新时间 UpdateTime string `json:"update_time"` // 更新时间
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
} }
type AdminGetOrderListReq struct { type AdminGetOrderListReq struct {
@@ -680,6 +684,16 @@ type AdminResetPasswordResp struct {
Success bool `json:"success"` // 是否成功 Success bool `json:"success"` // 是否成功
} }
type AdminRetryAgentProcessReq struct {
Id int64 `path:"id"` // 订单ID
}
type AdminRetryAgentProcessResp struct {
Status string `json:"status"` // 执行状态success-成功already_processed-已处理failed-失败
Message string `json:"message"` // 执行结果消息
ProcessedAt string `json:"processed_at"` // 处理时间
}
type AdminRoleApiInfo struct { type AdminRoleApiInfo struct {
Id int64 `json:"id"` Id int64 `json:"id"`
RoleId int64 `json:"role_id"` RoleId int64 `json:"role_id"`
@@ -1594,6 +1608,8 @@ type OrderListItem struct {
PayTime string `json:"pay_time"` // 支付时间 PayTime string `json:"pay_time"` // 支付时间
RefundTime string `json:"refund_time"` // 退款时间 RefundTime string `json:"refund_time"` // 退款时间
IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是 IsPromotion int64 `json:"is_promotion"` // 是否推广订单0-否1-是
IsAgentOrder bool `json:"is_agent_order"` // 是否是代理订单
AgentProcessStatus string `json:"agent_process_status"` // 代理事务处理状态not_agent-非代理订单success-处理成功failed-处理失败pending-待处理
} }
type PaymentCheckReq struct { type PaymentCheckReq struct {