diff --git a/app/main/api/desc/admin/order.api b/app/main/api/desc/admin/order.api index 426c456..6ef8ab9 100644 --- a/app/main/api/desc/admin/order.api +++ b/app/main/api/desc/admin/order.api @@ -35,6 +35,10 @@ service main { @doc "订单退款" @handler AdminRefundOrder post /refund/:id (AdminRefundOrderReq) returns (AdminRefundOrderResp) + + @doc "重新执行代理处理" + @handler AdminRetryAgentProcess + post /retry-agent-process/:id (AdminRetryAgentProcessReq) returns (AdminRetryAgentProcessResp) } type ( @@ -79,6 +83,8 @@ type ( PayTime string `json:"pay_time"` // 支付时间 RefundTime string `json:"refund_time"` // 退款时间 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"` // 退款时间 IsPromotion int64 `json:"is_promotion"` // 是否推广订单:0-否,1-是 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"` // 退款单号 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"` // 处理时间 + } ) \ No newline at end of file diff --git a/app/main/api/internal/handler/admin_order/adminretryagentprocesshandler.go b/app/main/api/internal/handler/admin_order/adminretryagentprocesshandler.go new file mode 100644 index 0000000..df80c70 --- /dev/null +++ b/app/main/api/internal/handler/admin_order/adminretryagentprocesshandler.go @@ -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) + } + } +} diff --git a/app/main/api/internal/handler/routes.go b/app/main/api/internal/handler/routes.go index 56c39c3..a01ee81 100644 --- a/app/main/api/internal/handler/routes.go +++ b/app/main/api/internal/handler/routes.go @@ -1,4 +1,6 @@ // Code generated by goctl. DO NOT EDIT. +// goctl 1.8.4 + package handler import ( @@ -310,6 +312,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/refund/:id", Handler: admin_order.AdminRefundOrderHandler(serverCtx), }, + { + // 重新执行代理处理 + Method: http.MethodPost, + Path: "/retry-agent-process/:id", + Handler: admin_order.AdminRetryAgentProcessHandler(serverCtx), + }, { // 更新订单 Method: http.MethodPut, diff --git a/app/main/api/internal/logic/admin_order/admingetorderdetaillogic.go b/app/main/api/internal/logic/admin_order/admingetorderdetaillogic.go index 585fa78..c12a133 100644 --- a/app/main/api/internal/logic/admin_order/admingetorderdetaillogic.go +++ b/app/main/api/internal/logic/admin_order/admingetorderdetaillogic.go @@ -47,6 +47,36 @@ func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderD 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 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"), IsPromotion: isPromotion, QueryState: queryState, + IsAgentOrder: isAgentOrder, + AgentProcessStatus: agentProcessStatus, } // 处理可选字段 diff --git a/app/main/api/internal/logic/admin_order/admingetorderlistlogic.go b/app/main/api/internal/logic/admin_order/admingetorderlistlogic.go index 9538bf0..60c5bd4 100644 --- a/app/main/api/internal/logic/admin_order/admingetorderlistlogic.go +++ b/app/main/api/internal/logic/admin_order/admingetorderlistlogic.go @@ -102,6 +102,8 @@ func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListR // 并发获取产品信息和查询状态 productMap := make(map[int64]string) queryStateMap := make(map[int64]string) + agentOrderMap := make(map[int64]bool) // 代理订单映射 + agentProcessStatusMap := make(map[int64]string) // 代理处理状态映射 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 { 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) } diff --git a/app/main/api/internal/logic/admin_order/adminretryagentprocesslogic.go b/app/main/api/internal/logic/admin_order/adminretryagentprocesslogic.go new file mode 100644 index 0000000..87ec195 --- /dev/null +++ b/app/main/api/internal/logic/admin_order/adminretryagentprocesslogic.go @@ -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 +} diff --git a/app/main/api/internal/service/agentService.go b/app/main/api/internal/service/agentService.go index d57e5db..c6c9b3a 100644 --- a/app/main/api/internal/service/agentService.go +++ b/app/main/api/internal/service/agentService.go @@ -12,6 +12,7 @@ import ( type AgentService struct { config config.Config + OrderModel model.OrderModel AgentModel model.AgentModel AgentAuditModel model.AgentAuditModel AgentClosureModel model.AgentClosureModel @@ -30,7 +31,7 @@ type AgentService struct { 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, agentCommissionDeductionModel model.AgentCommissionDeductionModel, agentWalletModel model.AgentWalletModel, agentLinkModel model.AgentLinkModel, agentOrderModel model.AgentOrderModel, agentRewardsModel model.AgentRewardsModel, agentMembershipConfigModel model.AgentMembershipConfigModel, @@ -41,6 +42,7 @@ func NewAgentService(c config.Config, agentModel model.AgentModel, agentAuditMod return &AgentService{ config: c, + OrderModel: orderModel, AgentModel: agentModel, AgentAuditModel: agentAuditModel, AgentClosureModel: agentClosureModel, @@ -271,6 +273,10 @@ func (l *AgentService) CommissionCost(ctx context.Context, descendantId int64, A // 拥有则查看该上级设定的成本 agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) if findAgentMembershipUserConfigModelErr != nil { + // 如果上级没有配置该产品的定价规则,则跳过成本计算 + if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) { + return 0, nil + } return 0, findAgentMembershipUserConfigModelErr } @@ -301,6 +307,10 @@ func (l *AgentService) CommissionPricing(ctx context.Context, descendantId int64 // 拥有则查看该上级设定的成本 agentMembershipUserConfigModel, findAgentMembershipUserConfigModelErr := l.AgentMembershipUserConfigModel.FindOneByAgentIdProductId(ctx, AncestorId, productID) if findAgentMembershipUserConfigModelErr != nil { + // 如果上级没有配置该产品的定价规则,则跳过成本计算 + if errors.Is(findAgentMembershipUserConfigModelErr, model.ErrNotFound) { + return 0, nil + } return 0, findAgentMembershipUserConfigModelErr } @@ -522,3 +532,57 @@ func (l *AgentService) GiveWithdrawReward(ctx context.Context, agentID int64, wi 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) +} diff --git a/app/main/api/internal/svc/servicecontext.go b/app/main/api/internal/svc/servicecontext.go index fca2c84..0822069 100644 --- a/app/main/api/internal/svc/servicecontext.go +++ b/app/main/api/internal/svc/servicecontext.go @@ -192,7 +192,7 @@ func NewServiceContext(c config.Config) *ServiceContext { apiRequestService := service.NewApiRequestService(c, featureModel, productFeatureModel, tianyuanapi) verificationService := service.NewVerificationService(c, tianyuanapi, apiRequestService) asynqService := service.NewAsynqService(c) - agentService := service.NewAgentService(c, agentModel, agentAuditModel, agentClosureModel, + agentService := service.NewAgentService(c, orderModel, agentModel, agentAuditModel, agentClosureModel, agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel, diff --git a/app/main/api/internal/types/types.go b/app/main/api/internal/types/types.go index e84d3cf..d38d31a 100644 --- a/app/main/api/internal/types/types.go +++ b/app/main/api/internal/types/types.go @@ -1,4 +1,6 @@ // Code generated by goctl. DO NOT EDIT. +// goctl 1.8.4 + package types type ActiveReward struct { @@ -433,20 +435,22 @@ type AdminGetOrderDetailReq struct { } type AdminGetOrderDetailResp struct { - Id int64 `json:"id"` // 订单ID - OrderNo string `json:"order_no"` // 商户订单号 - PlatformOrderId string `json:"platform_order_id"` // 支付订单号 - ProductName string `json:"product_name"` // 产品名称 - PaymentPlatform string `json:"payment_platform"` // 支付方式 - PaymentScene string `json:"payment_scene"` // 支付平台 - Amount float64 `json:"amount"` // 金额 - Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败 - QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中 - CreateTime string `json:"create_time"` // 创建时间 - PayTime string `json:"pay_time"` // 支付时间 - RefundTime string `json:"refund_time"` // 退款时间 - IsPromotion int64 `json:"is_promotion"` // 是否推广订单:0-否,1-是 - UpdateTime string `json:"update_time"` // 更新时间 + Id int64 `json:"id"` // 订单ID + OrderNo string `json:"order_no"` // 商户订单号 + PlatformOrderId string `json:"platform_order_id"` // 支付订单号 + ProductName string `json:"product_name"` // 产品名称 + PaymentPlatform string `json:"payment_platform"` // 支付方式 + PaymentScene string `json:"payment_scene"` // 支付平台 + Amount float64 `json:"amount"` // 金额 + Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败 + QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中 + CreateTime string `json:"create_time"` // 创建时间 + PayTime string `json:"pay_time"` // 支付时间 + RefundTime string `json:"refund_time"` // 退款时间 + IsPromotion int64 `json:"is_promotion"` // 是否推广订单:0-否,1-是 + 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 { @@ -680,6 +684,16 @@ type AdminResetPasswordResp struct { 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 { Id int64 `json:"id"` RoleId int64 `json:"role_id"` @@ -1581,19 +1595,21 @@ type NotificationListItem struct { } type OrderListItem struct { - Id int64 `json:"id"` // 订单ID - OrderNo string `json:"order_no"` // 商户订单号 - PlatformOrderId string `json:"platform_order_id"` // 支付订单号 - ProductName string `json:"product_name"` // 产品名称 - PaymentPlatform string `json:"payment_platform"` // 支付方式 - PaymentScene string `json:"payment_scene"` // 支付平台 - Amount float64 `json:"amount"` // 金额 - Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败 - QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中 - CreateTime string `json:"create_time"` // 创建时间 - PayTime string `json:"pay_time"` // 支付时间 - RefundTime string `json:"refund_time"` // 退款时间 - IsPromotion int64 `json:"is_promotion"` // 是否推广订单:0-否,1-是 + Id int64 `json:"id"` // 订单ID + OrderNo string `json:"order_no"` // 商户订单号 + PlatformOrderId string `json:"platform_order_id"` // 支付订单号 + ProductName string `json:"product_name"` // 产品名称 + PaymentPlatform string `json:"payment_platform"` // 支付方式 + PaymentScene string `json:"payment_scene"` // 支付平台 + Amount float64 `json:"amount"` // 金额 + Status string `json:"status"` // 支付状态:pending-待支付,paid-已支付,refunded-已退款,closed-已关闭,failed-支付失败 + QueryState string `json:"query_state"` // 查询状态:pending-待查询,success-查询成功,failed-查询失败 processing-查询中 + CreateTime string `json:"create_time"` // 创建时间 + PayTime string `json:"pay_time"` // 支付时间 + RefundTime string `json:"refund_time"` // 退款时间 + 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 {