first commit

This commit is contained in:
2026-09-11 01:47:20 +08:00
commit 303207d3cc
74 changed files with 8348 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
package service
import (
"context"
"strings"
"git.lzcwy.cn/zhengchiliu/zt-closet-manage-backend/global"
"git.lzcwy.cn/zhengchiliu/zt-closet-manage-backend/internal/dto"
"git.lzcwy.cn/zhengchiliu/zt-closet-manage-backend/internal/mysqldao"
"git.lzcwy.cn/zhengchiliu/zt-closet-manage-backend/internal/mysqlmodel"
"git.lzcwy.cn/zhengchiliu/zt-closet-manage-backend/pkg/errcode"
)
// OrderService 订单与退款管理服务。
type OrderService struct {
orderDao *mysqldao.OrderDao
refundDao *mysqldao.RefundDao
}
// NewOrderService 创建订单服务。
func NewOrderService() *OrderService {
return &OrderService{
orderDao: mysqldao.NewOrderDao(),
refundDao: mysqldao.NewRefundDao(),
}
}
// List 分页查询订单。
func (s *OrderService) List(ctx context.Context, request *dto.OrderListRequest) (*dto.OrderListResponse, *errcode.Error) {
ctx, span := global.Tracer.Start(ctx, "svc.AdminOrderList")
defer span.End()
page, pageSize := normalizePage(request.Page, request.PageSize)
list, total, err := s.orderDao.OrderList(ctx, mysqldao.OrderListParams{
OrderNo: strings.TrimSpace(request.OrderNo),
UserID: request.UserID,
Status: request.Status,
Page: page,
Size: pageSize,
})
if err != nil {
return nil, errcode.DatabaseError
}
items := make([]dto.OrderItem, 0, len(list))
for i := range list {
items = append(items, buildOrderItem(&list[i]))
}
return &dto.OrderListResponse{
PageResponse: dto.PageResponse{Total: total, Page: page, PageSize: pageSize},
List: items,
}, nil
}
// Get 订单详情。
func (s *OrderService) Get(ctx context.Context, orderNo string) (*dto.OrderItem, *errcode.Error) {
ctx, span := global.Tracer.Start(ctx, "svc.AdminOrderGet")
defer span.End()
order, err := s.orderDao.OrderGetByOrderNo(ctx, orderNo)
if err != nil {
if isNotFound(err) {
return nil, errcode.OrderNotFound
}
return nil, errcode.DatabaseError
}
item := buildOrderItem(order)
return &item, nil
}
// RefundList 分页查询退款单。
func (s *OrderService) RefundList(ctx context.Context, request *dto.RefundListRequest) (*dto.RefundListResponse, *errcode.Error) {
ctx, span := global.Tracer.Start(ctx, "svc.AdminRefundList")
defer span.End()
page, pageSize := normalizePage(request.Page, request.PageSize)
// status 未传时 query 绑定为 nil,与「待处理=0」天然区分。
withStatus := request.Status != nil
var status int8
if withStatus {
status = *request.Status
}
list, total, err := s.refundDao.RefundList(ctx, mysqldao.RefundListParams{
Status: status,
WithStatus: withStatus,
OrderNo: strings.TrimSpace(request.OrderNo),
Page: page,
Size: pageSize,
})
if err != nil {
return nil, errcode.DatabaseError
}
items := make([]dto.RefundItem, 0, len(list))
for i := range list {
items = append(items, buildRefundItem(&list[i]))
}
return &dto.RefundListResponse{
PageResponse: dto.PageResponse{Total: total, Page: page, PageSize: pageSize},
List: items,
}, nil
}
// RefundApprove 审核通过:待处理(0) → 退款中(1)。
// 实际打款由运营在微信商户平台人工完成,业务服务退款回调负责后续「成功(2)」流转与权益回收。
func (s *OrderService) RefundApprove(ctx context.Context, adminID int64, refundNo string, request *dto.RefundAuditRequest) *errcode.Error {
ctx, span := global.Tracer.Start(ctx, "svc.AdminRefundApprove")
defer span.End()
if _, err := s.refundDao.RefundGetByRefundNo(ctx, refundNo); err != nil {
if isNotFound(err) {
return errcode.RefundNotFound
}
return errcode.DatabaseError
}
ok, err := s.refundDao.RefundTransition(ctx, refundNo, RefundStatusPending, RefundStatusProcessing, "")
if err != nil {
return errcode.DatabaseError
}
if !ok {
return errcode.RefundStatusInvalid.WithDetails("仅待处理状态的退款单可审核")
}
return nil
}
// RefundReject 审核驳回:待处理(0) → 失败(3),记录驳回原因。
func (s *OrderService) RefundReject(ctx context.Context, adminID int64, refundNo string, request *dto.RefundAuditRequest) *errcode.Error {
ctx, span := global.Tracer.Start(ctx, "svc.AdminRefundReject")
defer span.End()
if _, err := s.refundDao.RefundGetByRefundNo(ctx, refundNo); err != nil {
if isNotFound(err) {
return errcode.RefundNotFound
}
return errcode.DatabaseError
}
ok, err := s.refundDao.RefundTransition(ctx, refundNo, RefundStatusPending, RefundStatusFailed, strings.TrimSpace(request.Reason))
if err != nil {
return errcode.DatabaseError
}
if !ok {
return errcode.RefundStatusInvalid.WithDetails("仅待处理状态的退款单可审核")
}
return nil
}
// buildOrderItem 订单模型 → 响应。
func buildOrderItem(o *mysqlmodel.Order) dto.OrderItem {
return dto.OrderItem{
OrderNo: o.OrderNo,
UserID: o.UserID,
GoodsID: o.GoodsID,
GoodsName: o.GoodsName,
UnitPrice: o.UnitPrice,
TotalAmount: o.TotalAmount,
PayAmount: o.PayAmount,
PayChannel: o.PayChannel,
OrderStatus: o.OrderStatus,
TransactionID: o.TransactionID,
MemberDays: o.MemberDays,
UploadQuota: o.CosQuota,
AIRecommendQuota: o.AIRecommendQuota,
ClosetShareQuota: o.ClosetShareQuota,
OutfitShareQuota: o.OutfitShareQuota,
ExpireTime: o.ExpireTime,
PayTime: o.PayTime,
RefundTime: o.RefundTime,
RefundAmount: o.RefundAmount,
Remark: o.Remark,
XPayProductID: o.XPayProductID,
XPayPlatform: o.XPayPlatform,
XPayEnv: o.XPayEnv,
CreatedAt: o.CreatedAt,
}
}
// buildRefundItem 退款单模型 → 响应。
func buildRefundItem(r *mysqlmodel.RefundFlowLog) dto.RefundItem {
return dto.RefundItem{
RefundNo: r.RefundNo,
OrderNo: r.OrderNo,
UserID: r.UserID,
RefundAmount: r.RefundAmount,
RefundReason: r.RefundReason,
Status: r.Status,
ApplyTime: r.ApplyTime,
SuccessTime: r.SuccessTime,
FailReason: r.FailReason,
CreatedAt: r.CreatedAt,
}
}