f
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type AdminCreateOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreateOrderLogic {
|
||||
return &AdminCreateOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminCreateOrderLogic) AdminCreateOrder(req *types.AdminCreateOrderReq) (resp *types.AdminCreateOrderResp, err error) {
|
||||
// 生成订单号
|
||||
orderNo := fmt.Sprintf("%dADMIN", time.Now().UnixNano())
|
||||
|
||||
// 根据产品名称查询产品ID
|
||||
builder := l.svcCtx.ProductModel.SelectBuilder()
|
||||
builder = builder.Where("product_name = ? AND del_state = ?", req.ProductName, 0)
|
||||
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, builder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 查询产品失败 err: %v", err)
|
||||
}
|
||||
if len(products) == 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("产品不存在: %s", req.ProductName)), "AdminCreateOrder, 查询产品失败 err: %v", err)
|
||||
}
|
||||
product := products[0]
|
||||
|
||||
// 创建订单对象
|
||||
order := &model.Order{
|
||||
OrderNo: orderNo,
|
||||
PlatformOrderId: sql.NullString{String: req.PlatformOrderId, Valid: req.PlatformOrderId != ""},
|
||||
ProductId: product.Id,
|
||||
PaymentPlatform: req.PaymentPlatform,
|
||||
PaymentScene: req.PaymentScene,
|
||||
Amount: req.Amount,
|
||||
Status: req.Status,
|
||||
}
|
||||
|
||||
// 使用事务处理订单创建
|
||||
var orderId int64
|
||||
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
// 插入订单
|
||||
result, err := l.svcCtx.OrderModel.Insert(ctx, session, order)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 创建订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 获取订单ID
|
||||
orderId, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 获取订单ID失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 如果是推广订单,创建推广订单记录
|
||||
if req.IsPromotion == 1 {
|
||||
promotionOrder := &model.AdminPromotionOrder{
|
||||
OrderId: orderId,
|
||||
Version: 1,
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
_, err = l.svcCtx.AdminPromotionOrderModel.Insert(ctx, session, promotionOrder)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 创建推广订单失败 err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AdminCreateOrderResp{
|
||||
Id: orderId,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type AdminDeleteOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminDeleteOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteOrderLogic {
|
||||
return &AdminDeleteOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminDeleteOrderLogic) AdminDeleteOrder(req *types.AdminDeleteOrderReq) (resp *types.AdminDeleteOrderResp, err error) {
|
||||
// 获取订单信息
|
||||
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 查询订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 使用事务删除订单
|
||||
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
// 软删除订单
|
||||
err := l.svcCtx.OrderModel.DeleteSoft(ctx, session, order)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 删除订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 删除关联的推广订单记录
|
||||
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(ctx, order.Id)
|
||||
if err == nil && promotionOrder != nil {
|
||||
err = l.svcCtx.AdminPromotionOrderModel.DeleteSoft(ctx, session, promotionOrder)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 删除推广订单失败 err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AdminDeleteOrderResp{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/globalkey"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetOrderDetailLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderDetailLogic {
|
||||
return &AdminGetOrderDetailLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderDetailReq) (resp *types.AdminGetOrderDetailResp, err error) {
|
||||
// 获取订单信息
|
||||
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 获取产品信息
|
||||
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, order.ProductId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询产品失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 判断是否为推广订单
|
||||
var isPromotion int64
|
||||
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(l.ctx, order.Id)
|
||||
if err == nil && promotionOrder != nil {
|
||||
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")
|
||||
queries, err := l.svcCtx.QueryModel.FindAll(l.ctx, builder, "")
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询查询状态失败 err: %v", err)
|
||||
}
|
||||
|
||||
if len(queries) > 0 {
|
||||
queryState = queries[0].QueryState
|
||||
} else {
|
||||
// 查询清理日志
|
||||
cleanupBuilder := l.svcCtx.QueryCleanupDetailModel.SelectBuilder().
|
||||
Where("order_id = ?", order.Id).
|
||||
Where("del_state = ?", globalkey.DelStateNo).
|
||||
OrderBy("create_time DESC").
|
||||
Limit(1)
|
||||
cleanupDetails, err := l.svcCtx.QueryCleanupDetailModel.FindAll(l.ctx, cleanupBuilder, "")
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询清理日志失败 err: %v", err)
|
||||
}
|
||||
|
||||
if len(cleanupDetails) > 0 {
|
||||
queryState = model.QueryStateCleaned
|
||||
} else {
|
||||
queryState = ""
|
||||
}
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetOrderDetailResp{
|
||||
Id: order.Id,
|
||||
OrderNo: order.OrderNo,
|
||||
PlatformOrderId: order.PlatformOrderId.String,
|
||||
ProductName: product.ProductName,
|
||||
PaymentPlatform: order.PaymentPlatform,
|
||||
PaymentScene: order.PaymentScene,
|
||||
Amount: order.Amount,
|
||||
SalesCost: order.SalesCost,
|
||||
Status: order.Status,
|
||||
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
UpdateTime: order.UpdateTime.Format("2006-01-02 15:04:05"),
|
||||
IsPromotion: isPromotion,
|
||||
QueryState: queryState,
|
||||
IsAgentOrder: isAgentOrder,
|
||||
AgentProcessStatus: agentProcessStatus,
|
||||
}
|
||||
|
||||
// 处理可选字段
|
||||
if order.PayTime.Valid {
|
||||
resp.PayTime = order.PayTime.Time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
if order.RefundTime.Valid {
|
||||
resp.RefundTime = order.RefundTime.Time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/globalkey"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/mr"
|
||||
)
|
||||
|
||||
type AdminGetOrderListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderListLogic {
|
||||
return &AdminGetOrderListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListReq) (resp *types.AdminGetOrderListResp, err error) {
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder()
|
||||
if req.OrderNo != "" {
|
||||
builder = builder.Where("order_no = ?", req.OrderNo)
|
||||
}
|
||||
if req.PlatformOrderId != "" {
|
||||
builder = builder.Where("platform_order_id = ?", req.PlatformOrderId)
|
||||
}
|
||||
if req.ProductName != "" {
|
||||
builder = builder.Where("product_id IN (SELECT id FROM product WHERE product_name LIKE ?)", "%"+req.ProductName+"%")
|
||||
}
|
||||
if req.PaymentPlatform != "" {
|
||||
builder = builder.Where("payment_platform = ?", req.PaymentPlatform)
|
||||
}
|
||||
if req.PaymentScene != "" {
|
||||
builder = builder.Where("payment_scene = ?", req.PaymentScene)
|
||||
}
|
||||
if req.Amount > 0 {
|
||||
builder = builder.Where("amount = ?", req.Amount)
|
||||
}
|
||||
if req.Status != "" {
|
||||
builder = builder.Where("status = ?", req.Status)
|
||||
}
|
||||
if req.IsPromotion != -1 {
|
||||
builder = builder.Where("id IN (SELECT order_id FROM admin_promotion_order WHERE del_state = 0)")
|
||||
}
|
||||
// 时间范围查询
|
||||
if req.CreateTimeStart != "" {
|
||||
builder = builder.Where("create_time >= ?", req.CreateTimeStart)
|
||||
}
|
||||
if req.CreateTimeEnd != "" {
|
||||
builder = builder.Where("create_time <= ?", req.CreateTimeEnd)
|
||||
}
|
||||
if req.PayTimeStart != "" {
|
||||
builder = builder.Where("pay_time >= ?", req.PayTimeStart)
|
||||
}
|
||||
if req.PayTimeEnd != "" {
|
||||
builder = builder.Where("pay_time <= ?", req.PayTimeEnd)
|
||||
}
|
||||
if req.RefundTimeStart != "" {
|
||||
builder = builder.Where("refund_time >= ?", req.RefundTimeStart)
|
||||
}
|
||||
if req.RefundTimeEnd != "" {
|
||||
builder = builder.Where("refund_time <= ?", req.RefundTimeEnd)
|
||||
}
|
||||
|
||||
// 并发获取总数和列表
|
||||
var total int64
|
||||
var orders []*model.Order
|
||||
err = mr.Finish(func() error {
|
||||
var err error
|
||||
total, err = l.svcCtx.OrderModel.FindCount(l.ctx, builder, "id")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询订单总数失败 err: %v", err)
|
||||
}
|
||||
return nil
|
||||
}, func() error {
|
||||
var err error
|
||||
orders, err = l.svcCtx.OrderModel.FindPageListByPage(l.ctx, builder, req.Page, req.PageSize, "id DESC")
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询订单列表失败 err: %v", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 并发获取产品信息和查询状态
|
||||
productMap := make(map[int64]string)
|
||||
queryStateMap := make(map[int64]string)
|
||||
agentOrderMap := make(map[int64]bool) // 代理订单映射
|
||||
agentProcessStatusMap := make(map[int64]string) // 代理处理状态映射
|
||||
|
||||
var mu sync.Mutex
|
||||
|
||||
// 批量获取查询状态
|
||||
if len(orders) > 0 {
|
||||
orderIds := make([]int64, 0, len(orders))
|
||||
for _, order := range orders {
|
||||
orderIds = append(orderIds, order.Id)
|
||||
}
|
||||
|
||||
// 1. 先查询当前查询状态
|
||||
builder := l.svcCtx.QueryModel.SelectBuilder().
|
||||
Where(squirrel.Eq{"order_id": orderIds}).
|
||||
Columns("order_id", "query_state")
|
||||
queries, err := l.svcCtx.QueryModel.FindAll(l.ctx, builder, "")
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 批量查询查询状态失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 2. 记录已找到查询状态的订单ID
|
||||
foundOrderIds := make(map[int64]bool)
|
||||
for _, query := range queries {
|
||||
queryStateMap[query.OrderId] = query.QueryState
|
||||
foundOrderIds[query.OrderId] = true
|
||||
}
|
||||
|
||||
// 3. 查找未找到查询状态的订单是否在清理日志中
|
||||
notFoundOrderIds := make([]int64, 0)
|
||||
for _, orderId := range orderIds {
|
||||
if !foundOrderIds[orderId] {
|
||||
notFoundOrderIds = append(notFoundOrderIds, orderId)
|
||||
}
|
||||
}
|
||||
|
||||
if len(notFoundOrderIds) > 0 {
|
||||
// 查询清理日志
|
||||
cleanupBuilder := l.svcCtx.QueryCleanupDetailModel.SelectBuilder().
|
||||
Where(squirrel.Eq{"order_id": notFoundOrderIds}).
|
||||
Where("del_state = ?", globalkey.DelStateNo).
|
||||
OrderBy("create_time DESC")
|
||||
cleanupDetails, err := l.svcCtx.QueryCleanupDetailModel.FindAll(l.ctx, cleanupBuilder, "")
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询清理日志失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 记录已清理的订单状态
|
||||
for _, detail := range cleanupDetails {
|
||||
if _, exists := queryStateMap[detail.OrderId]; !exists {
|
||||
queryStateMap[detail.OrderId] = model.QueryStateCleaned // 使用常量标记为已清除状态
|
||||
}
|
||||
}
|
||||
|
||||
// 对于既没有查询状态也没有清理记录的订单,不设置状态(保持为空字符串)
|
||||
for _, orderId := range notFoundOrderIds {
|
||||
if _, exists := queryStateMap[orderId]; !exists {
|
||||
queryStateMap[orderId] = "" // 未知状态保持为空字符串
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取代理订单状态
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 并发获取产品信息
|
||||
err = mr.MapReduceVoid(func(source chan<- interface{}) {
|
||||
for _, order := range orders {
|
||||
source <- order
|
||||
}
|
||||
}, func(item interface{}, writer mr.Writer[struct{}], cancel func(error)) {
|
||||
order := item.(*model.Order)
|
||||
|
||||
// 获取产品信息
|
||||
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, order.ProductId)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询产品信息失败 err: %v", err))
|
||||
return
|
||||
}
|
||||
mu.Lock()
|
||||
if product != nil {
|
||||
productMap[product.Id] = product.ProductName
|
||||
} else {
|
||||
productMap[order.ProductId] = "" // 产品不存在时设置为空字符串
|
||||
}
|
||||
mu.Unlock()
|
||||
writer.Write(struct{}{})
|
||||
}, func(pipe <-chan struct{}, cancel func(error)) {
|
||||
for range pipe {
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetOrderListResp{
|
||||
Total: total,
|
||||
Items: make([]types.OrderListItem, 0, len(orders)),
|
||||
}
|
||||
|
||||
for _, order := range orders {
|
||||
item := types.OrderListItem{
|
||||
Id: order.Id,
|
||||
OrderNo: order.OrderNo,
|
||||
PlatformOrderId: order.PlatformOrderId.String,
|
||||
ProductName: productMap[order.ProductId],
|
||||
PaymentPlatform: order.PaymentPlatform,
|
||||
PaymentScene: order.PaymentScene,
|
||||
Amount: order.Amount,
|
||||
SalesCost: order.SalesCost,
|
||||
Status: order.Status,
|
||||
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
QueryState: queryStateMap[order.Id],
|
||||
}
|
||||
if order.PayTime.Valid {
|
||||
item.PayTime = order.PayTime.Time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
if order.RefundTime.Valid {
|
||||
item.RefundTime = order.RefundTime.Time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
// 判断是否为推广订单
|
||||
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(l.ctx, order.Id)
|
||||
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)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetOrderSourceStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderSourceStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderSourceStatisticsLogic {
|
||||
return &AdminGetOrderSourceStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderSourceStatisticsLogic) AdminGetOrderSourceStatistics(req *types.AdminGetOrderSourceStatisticsReq) (resp *types.AdminGetOrderSourceStatisticsResp, err error) {
|
||||
// 查询所有有产品ID的订单
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder()
|
||||
builder = builder.Where("product_id IS NOT NULL")
|
||||
|
||||
// 获取所有符合条件的订单
|
||||
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "id DESC")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单列表失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单列表失败: %w", err)
|
||||
}
|
||||
|
||||
logx.Infof("获取到订单数量: %d", len(orders))
|
||||
|
||||
// 统计每个产品的订单数量
|
||||
productCountMap := make(map[int64]int64)
|
||||
for _, order := range orders {
|
||||
productCountMap[order.ProductId]++
|
||||
}
|
||||
|
||||
// 构建返回结果
|
||||
items := make([]types.OrderSourceStatisticsItem, 0, len(productCountMap))
|
||||
for productId, count := range productCountMap {
|
||||
// 获取产品信息
|
||||
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, productId)
|
||||
if err != nil {
|
||||
logx.Errorf("查询产品信息失败 productId=%d, err=%v", productId, err)
|
||||
// 如果查询失败,使用默认值
|
||||
items = append(items, types.OrderSourceStatisticsItem{
|
||||
ProductName: "未知产品",
|
||||
OrderCount: count,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
items = append(items, types.OrderSourceStatisticsItem{
|
||||
ProductName: product.ProductName,
|
||||
OrderCount: count,
|
||||
})
|
||||
}
|
||||
|
||||
// 按订单数量降序排序
|
||||
for i := 0; i < len(items)-1; i++ {
|
||||
for j := i + 1; j < len(items); j++ {
|
||||
if items[i].OrderCount < items[j].OrderCount {
|
||||
items[i], items[j] = items[j], items[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logx.Infof("查询到订单来源统计数据: %d 个产品,订单总数: %d", len(items), len(orders))
|
||||
return &types.AdminGetOrderSourceStatisticsResp{
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 定义结果结构体
|
||||
type OrderSourceResult struct {
|
||||
ProductName string `db:"product_name"`
|
||||
OrderCount int64 `db:"order_count"`
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetOrderStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetOrderStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderStatisticsLogic {
|
||||
return &AdminGetOrderStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetOrderStatisticsLogic) AdminGetOrderStatistics(req *types.AdminGetOrderStatisticsReq) (resp *types.AdminGetOrderStatisticsResp, err error) {
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
var startTime, endTime time.Time
|
||||
|
||||
// 根据时间维度设置时间范围和格式
|
||||
switch req.Dimension {
|
||||
case "day":
|
||||
// 日:当月1号到今天
|
||||
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
|
||||
case "month":
|
||||
// 月:今年1月到当月
|
||||
startTime = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), 1, 23, 59, 59, 999999999, now.Location()).AddDate(0, 1, -1)
|
||||
case "year":
|
||||
// 年:过去5年
|
||||
startTime = time.Date(now.Year()-5, 1, 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), 12, 31, 23, 59, 59, 999999999, now.Location())
|
||||
case "all":
|
||||
// 全部:所有时间,但按日统计
|
||||
startTime = time.Date(2020, 1, 1, 0, 0, 0, 0, now.Location()) // 假设从2020年开始
|
||||
endTime = now
|
||||
default:
|
||||
// 默认为日
|
||||
startTime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
endTime = time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 999999999, now.Location())
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("create_time >= ? AND create_time <= ?", startTime, endTime).
|
||||
Where("status = ?", "paid") // 只统计已支付的订单
|
||||
|
||||
// 查询所有符合条件的订单
|
||||
orders, err := l.svcCtx.OrderModel.FindAll(l.ctx, builder, "create_time ASC")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单统计数据失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单统计数据失败: %w", err)
|
||||
}
|
||||
|
||||
// 按日期分组统计
|
||||
dateMap := make(map[string]*types.OrderStatisticsItem)
|
||||
|
||||
for _, order := range orders {
|
||||
var dateKey string
|
||||
if req.Dimension == "year" {
|
||||
dateKey = order.CreateTime.Format("2006")
|
||||
} else if req.Dimension == "month" {
|
||||
dateKey = order.CreateTime.Format("2006-01")
|
||||
} else {
|
||||
dateKey = order.CreateTime.Format("2006-01-02")
|
||||
}
|
||||
|
||||
if item, exists := dateMap[dateKey]; exists {
|
||||
item.Count++
|
||||
item.Amount += order.Amount
|
||||
} else {
|
||||
dateMap[dateKey] = &types.OrderStatisticsItem{
|
||||
Date: dateKey,
|
||||
Count: 1,
|
||||
Amount: order.Amount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为切片
|
||||
items := make([]types.OrderStatisticsItem, 0, len(dateMap))
|
||||
for date := range dateMap {
|
||||
items = append(items, *dateMap[date])
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetOrderStatisticsResp{
|
||||
Items: items,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetRefundStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetRefundStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetRefundStatisticsLogic {
|
||||
return &AdminGetRefundStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetRefundStatisticsLogic) AdminGetRefundStatistics(req *types.AdminGetRefundStatisticsReq) (resp *types.AdminGetRefundStatisticsResp, err error) {
|
||||
// 获取今日的开始和结束时间
|
||||
today := time.Now()
|
||||
startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
|
||||
endOfDay := startOfDay.Add(24 * time.Hour)
|
||||
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder()
|
||||
|
||||
// 查询总退款金额(status=refunded表示已退款)
|
||||
totalBuilder := builder.Where("status = ?", "refunded")
|
||||
totalRefundAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, totalBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询总退款金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询总退款金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询今日退款金额(status=refunded表示已退款,且退款时间为今日)
|
||||
todayBuilder := builder.Where("status = ? AND refund_time >= ? AND refund_time < ?", "refunded", startOfDay, endOfDay)
|
||||
todayRefundAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, todayBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日退款金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日退款金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetRefundStatisticsResp{
|
||||
TotalRefundAmount: totalRefundAmount,
|
||||
TodayRefundAmount: todayRefundAmount,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AdminGetRevenueStatisticsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminGetRevenueStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetRevenueStatisticsLogic {
|
||||
return &AdminGetRevenueStatisticsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminGetRevenueStatisticsLogic) AdminGetRevenueStatistics(req *types.AdminGetRevenueStatisticsReq) (resp *types.AdminGetRevenueStatisticsResp, err error) {
|
||||
// 获取今日的开始和结束时间
|
||||
today := time.Now()
|
||||
startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location())
|
||||
endOfDay := startOfDay.Add(24 * time.Hour)
|
||||
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.OrderModel.SelectBuilder()
|
||||
|
||||
// 查询总流水收入金额(status=paid表示已支付)
|
||||
totalRevenueBuilder := builder.Where("status = ?", "paid")
|
||||
totalRevenueAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, totalRevenueBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询总收入金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询总收入金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询今日流水收入金额(status=paid表示已支付,且支付时间为今日)
|
||||
todayRevenueBuilder := builder.Where("status = ? AND pay_time >= ? AND pay_time < ?", "paid", startOfDay, endOfDay)
|
||||
todayRevenueAmount, err := l.svcCtx.OrderModel.FindSum(l.ctx, todayRevenueBuilder, "amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日收入金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日收入金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询代理订单金额总和(只查询agent_platform_deduction表,不进行联表)
|
||||
deductionAmount, err := l.svcCtx.AgentPlatformDeductionModel.FindSum(
|
||||
l.ctx,
|
||||
l.svcCtx.AgentPlatformDeductionModel.SelectBuilder(),
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询代理订单金额总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询代理订单金额总和失败: %w", err)
|
||||
}
|
||||
|
||||
// 计算非代理订单金额,使用订单表作为主表,关联agent_platform_deduction表,查询没有代理记录的订单
|
||||
// 使用子查询方式避免JOIN,与order/list接口保持一致的查询风格
|
||||
nonDeductionBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND id NOT IN (SELECT order_id FROM agent_platform_deduction WHERE order_id IS NOT NULL)", "paid")
|
||||
nonDeductionAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
nonDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询非代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询非代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 查询订单成本总和(只查询order表,不进行联表)
|
||||
orderCostBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND del_state = 0", "paid")
|
||||
orderCostAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
orderCostBuilder,
|
||||
"sales_cost")
|
||||
if err != nil {
|
||||
logx.Errorf("查询订单成本总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询订单成本总和失败: %w", err)
|
||||
}
|
||||
// 计算总利润 = 代理订单金额总和 + 非代理订单金额总和 - 订单成本总和
|
||||
// 总收入 = 代理订单金额 + 非代理订单金额
|
||||
// 总利润 = 总收入 - 所有订单成本
|
||||
totalProfitAmount := deductionAmount + nonDeductionAmount - orderCostAmount
|
||||
|
||||
// 计算今日利润 = 今日代理订单金额 + 今日非代理订单金额 - 今日订单成本总和
|
||||
|
||||
// 1. 查询今日代理订单金额
|
||||
todayDeductionBuilder := l.svcCtx.AgentPlatformDeductionModel.SelectBuilder().
|
||||
Where("create_time >= ? AND create_time < ?", startOfDay, endOfDay)
|
||||
todayDeductionAmount, err := l.svcCtx.AgentPlatformDeductionModel.FindSum(
|
||||
l.ctx,
|
||||
todayDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 2. 查询今日非代理订单金额
|
||||
todayNonDeductionBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND pay_time >= ? AND pay_time < ? AND id NOT IN (SELECT order_id FROM agent_platform_deduction WHERE order_id IS NOT NULL)",
|
||||
"paid", startOfDay, endOfDay)
|
||||
todayNonDeductionAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
todayNonDeductionBuilder,
|
||||
"amount")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日非代理订单金额失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日非代理订单金额失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 查询今日订单成本总和
|
||||
todayOrderCostBuilder := l.svcCtx.OrderModel.SelectBuilder().
|
||||
Where("status = ? AND pay_time >= ? AND pay_time < ?", "paid", startOfDay, endOfDay)
|
||||
todayOrderCostAmount, err := l.svcCtx.OrderModel.FindSum(
|
||||
l.ctx,
|
||||
todayOrderCostBuilder,
|
||||
"sales_cost")
|
||||
if err != nil {
|
||||
logx.Errorf("查询今日订单成本总和失败: %v", err)
|
||||
return nil, fmt.Errorf("查询今日订单成本总和失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 计算今日利润 = 今日代理订单金额 + 今日非代理订单金额 - 今日订单成本总和
|
||||
todayProfitAmount := todayDeductionAmount + todayNonDeductionAmount - todayOrderCostAmount
|
||||
|
||||
// 构建响应
|
||||
resp = &types.AdminGetRevenueStatisticsResp{
|
||||
TotalRevenueAmount: totalRevenueAmount,
|
||||
TodayRevenueAmount: todayRevenueAmount,
|
||||
TotalProfitAmount: totalProfitAmount,
|
||||
TodayProfitAmount: todayProfitAmount,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
199
app/main/api/internal/logic/admin_order/adminrefundorderlogic.go
Normal file
199
app/main/api/internal/logic/admin_order/adminrefundorderlogic.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
paylogic "tyc-server/app/main/api/internal/logic/pay"
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
const (
|
||||
PaymentPlatformAlipay = "alipay"
|
||||
PaymentPlatformWechat = "wechat"
|
||||
OrderStatusPaid = "paid"
|
||||
RefundNoPrefix = "refund-"
|
||||
)
|
||||
|
||||
type AdminRefundOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminRefundOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRefundOrderLogic {
|
||||
return &AdminRefundOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq) (resp *types.AdminRefundOrderResp, err error) {
|
||||
// 获取并验证订单
|
||||
order, err := l.getAndValidateOrder(req.Id, req.RefundAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 根据支付平台处理退款
|
||||
switch order.PaymentPlatform {
|
||||
case PaymentPlatformAlipay:
|
||||
return l.handleAlipayRefund(order, req)
|
||||
case PaymentPlatformWechat:
|
||||
return l.handleWechatRefund(order, req)
|
||||
default:
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("不支持的支付平台"), "AdminRefundOrder, 不支持的支付平台: %s", order.PaymentPlatform)
|
||||
}
|
||||
}
|
||||
|
||||
// getAndValidateOrder 获取并验证订单信息
|
||||
func (l *AdminRefundOrderLogic) getAndValidateOrder(orderId int64, refundAmount float64) (*model.Order, error) {
|
||||
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, orderId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 检查订单状态
|
||||
if order.Status != OrderStatusPaid {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("订单状态不正确,无法退款"), "AdminRefundOrder, 订单状态: %s", order.Status)
|
||||
}
|
||||
|
||||
// 检查退款金额
|
||||
if refundAmount > order.Amount {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("退款金额不能大于订单金额"), "AdminRefundOrder, 退款金额: %f, 订单金额: %f", refundAmount, order.Amount)
|
||||
}
|
||||
|
||||
return order, nil
|
||||
}
|
||||
|
||||
// handleAlipayRefund 处理支付宝退款
|
||||
func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
|
||||
// 调用支付宝退款接口
|
||||
refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.OrderNo, req.RefundAmount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 支付宝退款失败 err: %v", err)
|
||||
}
|
||||
|
||||
refundNo := l.generateRefundNo(order.OrderNo)
|
||||
|
||||
if refundResp.IsSuccess() {
|
||||
// 支付宝退款成功,创建成功记录
|
||||
err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, refundResp.TradeNo, model.OrderStatusRefunded, model.OrderRefundStatusSuccess)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 退款成功后,按本次退款金额更新代理佣金状态并扣除钱包金额
|
||||
// 注意:refundAmount 为本次实际退款金额,可以是部分退款
|
||||
_ = paylogic.HandleCommissionAndWalletDeduction(l.ctx, l.svcCtx, nil, order, req.RefundAmount)
|
||||
|
||||
return &types.AdminRefundOrderResp{
|
||||
Status: model.OrderStatusRefunded,
|
||||
RefundNo: refundNo,
|
||||
Amount: req.RefundAmount,
|
||||
}, nil
|
||||
} else {
|
||||
// 支付宝退款失败,创建失败记录但不更新订单状态
|
||||
err = l.createRefundRecordOnly(order, req, refundNo, refundResp.TradeNo, model.OrderRefundStatusFailed)
|
||||
if err != nil {
|
||||
logx.Errorf("创建退款失败记录时出错: %v", err)
|
||||
}
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("退款失败: %v", refundResp.Msg)), "AdminRefundOrder, 支付宝退款失败")
|
||||
}
|
||||
}
|
||||
|
||||
// handleWechatRefund 处理微信退款
|
||||
func (l *AdminRefundOrderLogic) handleWechatRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
|
||||
// 调用微信退款接口
|
||||
err := l.svcCtx.WechatPayService.WeChatRefund(l.ctx, order.OrderNo, req.RefundAmount, order.Amount)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 微信退款失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 微信退款是异步的,创建pending状态的退款记录
|
||||
// 注意:代理佣金扣除将在微信退款回调成功后再执行,不在此处提前扣除
|
||||
refundNo := l.generateRefundNo(order.OrderNo)
|
||||
err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", model.OrderStatusRefunding, model.OrderRefundStatusPending)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AdminRefundOrderResp{
|
||||
Status: model.OrderRefundStatusPending,
|
||||
RefundNo: refundNo,
|
||||
Amount: req.RefundAmount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// createRefundRecordAndUpdateOrder 创建退款记录并更新订单状态
|
||||
func (l *AdminRefundOrderLogic) createRefundRecordAndUpdateOrder(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, orderStatus, refundStatus string) error {
|
||||
return l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
// 创建退款记录
|
||||
refund := &model.OrderRefund{
|
||||
RefundNo: refundNo,
|
||||
PlatformRefundId: l.createNullString(platformRefundId),
|
||||
OrderId: order.Id,
|
||||
UserId: order.UserId,
|
||||
ProductId: order.ProductId,
|
||||
RefundAmount: req.RefundAmount,
|
||||
RefundReason: l.createNullString(req.RefundReason),
|
||||
Status: refundStatus, // 使用传入的状态,不再硬编码
|
||||
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||
}
|
||||
|
||||
if _, err := l.svcCtx.OrderRefundModel.Insert(ctx, session, refund); err != nil {
|
||||
return fmt.Errorf("创建退款记录失败: %v", err)
|
||||
}
|
||||
|
||||
// 更新订单状态
|
||||
order.Status = orderStatus
|
||||
if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
|
||||
return fmt.Errorf("更新订单状态失败: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// createRefundRecordOnly 仅创建退款记录,不更新订单状态(用于退款失败的情况)
|
||||
func (l *AdminRefundOrderLogic) createRefundRecordOnly(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, refundStatus string) error {
|
||||
refund := &model.OrderRefund{
|
||||
RefundNo: refundNo,
|
||||
PlatformRefundId: l.createNullString(platformRefundId),
|
||||
OrderId: order.Id,
|
||||
UserId: order.UserId,
|
||||
ProductId: order.ProductId,
|
||||
RefundAmount: req.RefundAmount,
|
||||
RefundReason: l.createNullString(req.RefundReason),
|
||||
Status: refundStatus,
|
||||
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||
}
|
||||
|
||||
_, err := l.svcCtx.OrderRefundModel.Insert(l.ctx, nil, refund)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建退款记录失败: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateRefundNo 生成退款单号
|
||||
func (l *AdminRefundOrderLogic) generateRefundNo(orderNo string) string {
|
||||
return fmt.Sprintf("%s%s", RefundNoPrefix, orderNo)
|
||||
}
|
||||
|
||||
// createNullString 创建 sql.NullString
|
||||
func (l *AdminRefundOrderLogic) createNullString(value string) sql.NullString {
|
||||
return sql.NullString{
|
||||
String: value,
|
||||
Valid: value != "",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-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
|
||||
}
|
||||
113
app/main/api/internal/logic/admin_order/adminupdateorderlogic.go
Normal file
113
app/main/api/internal/logic/admin_order/adminupdateorderlogic.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package admin_order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"tyc-server/app/main/api/internal/svc"
|
||||
"tyc-server/app/main/api/internal/types"
|
||||
"tyc-server/app/main/model"
|
||||
"tyc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type AdminUpdateOrderLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminUpdateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateOrderLogic {
|
||||
return &AdminUpdateOrderLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminUpdateOrderLogic) AdminUpdateOrder(req *types.AdminUpdateOrderReq) (resp *types.AdminUpdateOrderResp, err error) {
|
||||
// 获取原订单信息
|
||||
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 查询订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 更新订单字段
|
||||
if req.OrderNo != nil {
|
||||
order.OrderNo = *req.OrderNo
|
||||
}
|
||||
if req.PlatformOrderId != nil {
|
||||
order.PlatformOrderId = sql.NullString{String: *req.PlatformOrderId, Valid: true}
|
||||
}
|
||||
if req.PaymentPlatform != nil {
|
||||
order.PaymentPlatform = *req.PaymentPlatform
|
||||
}
|
||||
if req.PaymentScene != nil {
|
||||
order.PaymentScene = *req.PaymentScene
|
||||
}
|
||||
if req.Amount != nil {
|
||||
order.Amount = *req.Amount
|
||||
}
|
||||
if req.Status != nil {
|
||||
order.Status = *req.Status
|
||||
}
|
||||
if req.PayTime != nil {
|
||||
payTime, err := time.Parse("2006-01-02 15:04:05", *req.PayTime)
|
||||
if err == nil {
|
||||
order.PayTime = sql.NullTime{Time: payTime, Valid: true}
|
||||
}
|
||||
}
|
||||
if req.RefundTime != nil {
|
||||
refundTime, err := time.Parse("2006-01-02 15:04:05", *req.RefundTime)
|
||||
if err == nil {
|
||||
order.RefundTime = sql.NullTime{Time: refundTime, Valid: true}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用事务更新订单
|
||||
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
// 更新订单
|
||||
_, err := l.svcCtx.OrderModel.Update(ctx, session, order)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 更新订单失败 err: %v", err)
|
||||
}
|
||||
|
||||
// 处理推广订单状态
|
||||
if req.IsPromotion != nil {
|
||||
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(ctx, order.Id)
|
||||
if err == nil && promotionOrder != nil {
|
||||
// 如果存在推广订单记录但不需要推广,则删除
|
||||
if *req.IsPromotion == 0 {
|
||||
err = l.svcCtx.AdminPromotionOrderModel.DeleteSoft(ctx, session, promotionOrder)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 删除推广订单失败 err: %v", err)
|
||||
}
|
||||
}
|
||||
} else if *req.IsPromotion == 1 {
|
||||
// 如果需要推广但不存在记录,则创建
|
||||
newPromotionOrder := &model.AdminPromotionOrder{
|
||||
OrderId: order.Id,
|
||||
Version: 1,
|
||||
}
|
||||
_, err = l.svcCtx.AdminPromotionOrderModel.Insert(ctx, session, newPromotionOrder)
|
||||
if err != nil {
|
||||
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 创建推广订单失败 err: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AdminUpdateOrderResp{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user