Files
ai_dianshang/server/internal/service/order.go
2025-11-17 14:11:46 +08:00

1581 lines
50 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"dianshang/internal/model"
"dianshang/internal/repository"
"dianshang/pkg/utils"
"errors"
"fmt"
"log"
"time"
)
// OrderService 订单服务
type OrderService struct {
orderRepo *repository.OrderRepository
productRepo *repository.ProductRepository
userRepo *repository.UserRepository
couponRepo *repository.CouponRepository
}
// NewOrderService 创建订单服务
func NewOrderService(orderRepo *repository.OrderRepository, productRepo *repository.ProductRepository, userRepo *repository.UserRepository, couponRepo *repository.CouponRepository) *OrderService {
return &OrderService{
orderRepo: orderRepo,
productRepo: productRepo,
userRepo: userRepo,
couponRepo: couponRepo,
}
}
// CreateOrderRequest 创建订单请求
type CreateOrderRequest struct {
AddressID uint `json:"address_id" binding:"required"`
Items []CreateOrderItemRequest `json:"items" binding:"required,min=1"`
Remark string `json:"remark"`
CouponID *uint `json:"coupon_id,omitempty"`
}
// CreateOrderItemRequest 创建订单项请求
type CreateOrderItemRequest struct {
ProductID uint `json:"product_id" binding:"required"`
SpecID uint `json:"spec_id"`
SKUID uint `json:"sku_id"`
Quantity int `json:"quantity" binding:"required,min=1"`
SpecName string `json:"spec_name"`
SpecValue string `json:"spec_value"`
SpecInfo interface{} `json:"spec_info"` // 改为interface{}以支持数组和对象
}
// MergeOrdersRequest 合并订单请求
type MergeOrdersRequest struct {
OrderIDs []string `json:"order_ids" binding:"required,min=2"`
}
// CreateOrder 创建订单
func (s *OrderService) CreateOrder(userID uint, req *CreateOrderRequest) (*model.Order, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
// 检查收货地址是否存在
address, err := s.userRepo.GetAddressByID(req.AddressID)
if err != nil || address.UserID != userID {
return nil, errors.New("收货地址不存在")
}
// 创建订单
order := &model.Order{
OrderNo: utils.GenerateOrderNo(),
UserID: userID,
Status: 1, // 待付款
PayMethod: "wechat", // 微信支付
ReceiverAddress: address.ProvinceName + address.CityName + address.DistrictName + address.DetailAddress,
ReceiverName: address.Name,
ReceiverPhone: address.Phone,
Remark: req.Remark,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
var totalAmount float64
var orderItems []model.OrderItem
// 处理订单项
for _, item := range req.Items {
// 检查产品是否存在
product, err := s.productRepo.GetByID(item.ProductID)
if err != nil {
return nil, errors.New("产品不存在")
}
// 检查库存和获取价格优先检查SKU库存和价格
var actualPrice float64
if item.SKUID > 0 {
// 如果有SKU检查SKU库存并使用SKU价格
sku, err := s.productRepo.GetSKUByID(item.SKUID)
if err != nil {
return nil, errors.New("SKU不存在")
}
if sku.Stock < item.Quantity {
return nil, errors.New("SKU库存不足: " + product.Name)
}
actualPrice = sku.Price
} else {
// 如果没有SKU检查商品总库存并使用商品价格
if product.Stock < item.Quantity {
return nil, errors.New("产品库存不足: " + product.Name)
}
actualPrice = product.Price
}
// 计算金额
itemAmount := actualPrice * float64(item.Quantity)
totalAmount += itemAmount
// 创建订单项
var specID *uint
var skuID *uint
if item.SpecID > 0 {
specID = &item.SpecID
}
if item.SKUID > 0 {
skuID = &item.SKUID
}
// 处理SpecInfo类型转换
var specInfo model.JSONMap
if item.SpecInfo != nil {
switch v := item.SpecInfo.(type) {
case map[string]interface{}:
specInfo = model.JSONMap(v)
case []interface{}:
// 如果是数组转换为map格式
specInfo = make(model.JSONMap)
for _, spec := range v {
if specObj, ok := spec.(map[string]interface{}); ok {
if title, hasTitle := specObj["specTitle"]; hasTitle {
if value, hasValue := specObj["specValue"]; hasValue {
if titleStr, ok := title.(string); ok {
specInfo[titleStr] = value
}
}
}
}
}
default:
specInfo = make(model.JSONMap)
}
}
orderItem := model.OrderItem{
ProductID: item.ProductID,
SpecID: specID,
SKUID: skuID,
Quantity: item.Quantity,
Price: actualPrice,
TotalPrice: itemAmount,
ProductName: product.Name,
ProductImage: product.MainImage,
SpecName: item.SpecName,
SpecValue: item.SpecValue,
SpecInfo: specInfo,
}
orderItems = append(orderItems, orderItem)
}
order.TotalAmount = totalAmount
order.ShippingFee = 0 // 免运费
// 处理优惠券
var couponAmount float64
if req.CouponID != nil && *req.CouponID > 0 {
log.Printf("🎫 [优惠券验证] 开始处理优惠券 - 用户ID: %d, 接收到的优惠券ID: %d, 订单总金额: %.2f", userID, *req.CouponID, totalAmount)
// 获取用户优惠券
userCoupon, err := s.couponRepo.GetUserCouponByID(*req.CouponID)
if err != nil {
log.Printf("❌ [优惠券验证] 获取用户优惠券失败 - 用户ID: %d, 优惠券ID: %d, 错误: %v", userID, *req.CouponID, err)
return nil, errors.New("用户优惠券不存在")
}
log.Printf("✅ [优惠券验证] 成功获取用户优惠券 - 用户优惠券ID: %d, 优惠券模板ID: %d, 优惠券名称: %s, 状态: %d, 用户ID: %d",
userCoupon.ID, userCoupon.CouponID, userCoupon.Coupon.Name, userCoupon.Status, userCoupon.UserID)
// 验证用户优惠券是否可用
if err := s.validateUserCoupon(userCoupon, userID, totalAmount); err != nil {
log.Printf("❌ [优惠券验证] 用户优惠券验证失败 - 用户ID: %d, 优惠券ID: %d, 错误: %v", userID, *req.CouponID, err)
return nil, err
}
// 计算优惠金额
couponAmount = s.calculateCouponDiscount(&userCoupon.Coupon, totalAmount)
log.Printf("💰 [优惠券验证] 优惠金额计算完成 - 原价: %.2f, 优惠金额: %.2f, 实付金额: %.2f", totalAmount, couponAmount, totalAmount-couponAmount)
order.CouponID = req.CouponID
order.CouponAmount = couponAmount
} else {
log.Printf(" [优惠券验证] 未使用优惠券 - 用户ID: %d", userID)
}
order.PayAmount = totalAmount - couponAmount
// 保存订单
if err := s.orderRepo.Create(order); err != nil {
return nil, err
}
// 保存订单项
for i := range orderItems {
orderItems[i].OrderID = order.ID
if err := s.orderRepo.CreateOrderItem(&orderItems[i]); err != nil {
return nil, err
}
}
// 预扣库存(防止超卖)
for i, item := range req.Items {
var err error
if item.SKUID > 0 {
// 如果有SKU同时扣减SKU库存和商品库存
err = s.productRepo.DeductStockWithSKU(item.ProductID, &item.SKUID, item.Quantity)
} else {
// 如果没有SKU只扣减商品库存
err = s.productRepo.ReserveStock(item.ProductID, item.Quantity)
}
if err != nil {
// 如果预扣失败,需要恢复之前已预扣的库存
for j := 0; j < i; j++ {
prevItem := req.Items[j]
if prevItem.SKUID > 0 {
s.productRepo.RestoreStockWithSKU(prevItem.ProductID, &prevItem.SKUID, prevItem.Quantity)
} else {
s.productRepo.RestoreStock(prevItem.ProductID, prevItem.Quantity)
}
}
return nil, errors.New("库存预扣失败: " + err.Error())
}
}
// 清空购物车中的相关商品
for _, item := range req.Items {
s.orderRepo.RemoveFromCart(userID, item.ProductID)
}
// 如果使用了优惠券,标记为已使用
if req.CouponID != nil && *req.CouponID > 0 {
userCoupon, err := s.couponRepo.GetUserCouponByID(*req.CouponID)
if err != nil {
return nil, errors.New("用户优惠券不存在")
}
if err := s.couponRepo.UseCoupon(userCoupon.ID, order.ID); err != nil {
return nil, errors.New("使用优惠券失败")
}
}
return order, nil
}
// validateCoupon 验证优惠券是否可用
func (s *OrderService) validateCoupon(coupon *model.Coupon, userID uint, orderAmount float64) error {
// 检查优惠券状态
if coupon.Status != 1 {
return errors.New("优惠券不可用")
}
// 检查有效期
now := time.Now()
if coupon.StartTime.After(now) {
return errors.New("优惠券尚未生效")
}
if coupon.EndTime.Before(now) {
return errors.New("优惠券已过期")
}
// 检查最低消费金额 (MinAmount是分需要转换为元)
minAmount := float64(coupon.MinAmount) / 100
if orderAmount < minAmount {
return fmt.Errorf("订单金额不满足优惠券使用条件,最低需要%.2f元", minAmount)
}
// 检查用户是否拥有此优惠券且未使用
userCoupon, err := s.couponRepo.GetUserCouponByID(coupon.ID)
if err != nil {
return errors.New("您没有此优惠券")
}
if userCoupon.Status != 0 {
return errors.New("优惠券已使用或已过期")
}
return nil
}
// validateUserCoupon 验证用户优惠券是否可用
func (s *OrderService) validateUserCoupon(userCoupon *model.UserCoupon, userID uint, orderAmount float64) error {
log.Printf("🔍 [优惠券验证] 开始详细验证 - 用户ID: %d, 用户优惠券ID: %d", userID, userCoupon.ID)
// 首先检查优惠券是否属于当前用户
log.Printf("👤 [优惠券验证] 检查优惠券所有权 - 当前用户ID: %d, 优惠券所属用户ID: %d", userID, userCoupon.UserID)
if userCoupon.UserID != userID {
log.Printf("❌ [优惠券验证] 优惠券不属于当前用户 - 当前用户: %d, 优惠券所属用户: %d", userID, userCoupon.UserID)
return errors.New("无权使用该优惠券")
}
// 检查用户优惠券状态
log.Printf("📋 [优惠券验证] 检查用户优惠券状态 - 状态: %d (0=未使用, 1=已使用, 2=已过期)", userCoupon.Status)
if userCoupon.Status != 0 {
log.Printf("❌ [优惠券验证] 用户优惠券状态不可用 - 状态: %d", userCoupon.Status)
return errors.New("优惠券已使用或已过期")
}
// 检查优惠券状态
log.Printf("📋 [优惠券验证] 检查优惠券模板状态 - 状态: %d (1=可用)", userCoupon.Coupon.Status)
if userCoupon.Coupon.Status != 1 {
log.Printf("❌ [优惠券验证] 优惠券模板状态不可用 - 状态: %d", userCoupon.Coupon.Status)
return errors.New("优惠券不可用")
}
// 检查有效期
now := time.Now()
log.Printf("⏰ [优惠券验证] 检查有效期 - 当前时间: %s, 开始时间: %s, 结束时间: %s",
now.Format("2006-01-02 15:04:05"),
userCoupon.Coupon.StartTime.Format("2006-01-02 15:04:05"),
userCoupon.Coupon.EndTime.Format("2006-01-02 15:04:05"))
if userCoupon.Coupon.StartTime.After(now) {
log.Printf("❌ [优惠券验证] 优惠券尚未生效")
return errors.New("优惠券尚未生效")
}
if userCoupon.Coupon.EndTime.Before(now) {
log.Printf("❌ [优惠券验证] 优惠券已过期")
return errors.New("优惠券已过期")
}
// 检查最低消费金额 (MinAmount是分需要转换为元)
minAmount := float64(userCoupon.Coupon.MinAmount) / 100
log.Printf("💰 [优惠券验证] 检查最低消费金额 - 订单金额: %.2f元, 最低要求: %.2f元", orderAmount, minAmount)
if orderAmount < minAmount {
log.Printf("❌ [优惠券验证] 订单金额不满足最低消费要求")
return fmt.Errorf("订单金额不满足优惠券使用条件,最低需要%.2f元", minAmount)
}
log.Printf("✅ [优惠券验证] 所有验证通过 - 用户ID: %d, 用户优惠券ID: %d", userID, userCoupon.ID)
return nil
}
// calculateCouponDiscount 计算优惠券折扣金额
func (s *OrderService) calculateCouponDiscount(coupon *model.Coupon, orderAmount float64) float64 {
switch coupon.Type {
case 1: // 固定金额 (Value是分需要转换为元)
discountAmount := float64(coupon.Value)
if discountAmount > orderAmount {
return orderAmount
}
return discountAmount
case 2: // 百分比折扣 (Value是折扣如85表示8.5折)
discountRate := float64(coupon.Value) / 100 // 85 -> 0.85
discount := orderAmount * (1 - discountRate) // 计算优惠金额
return discount
case 3: // 免运费
// 这里可以返回运费金额目前运费为0所以返回0
return 0
default:
return 0
}
}
// GetUserOrders 获取用户订单列表
func (s *OrderService) GetUserOrders(userID uint, status, page, pageSize int) ([]model.Order, *utils.Pagination, error) {
if page <= 0 {
page = 1
}
if pageSize <= 0 || pageSize > 100 {
pageSize = 20
}
offset := (page - 1) * pageSize
orders, total, err := s.orderRepo.GetUserOrders(userID, status, offset, pageSize)
if err != nil {
return nil, nil, err
}
pagination := utils.NewPagination(page, pageSize)
pagination.Total = total
return orders, pagination, nil
}
// GetUserOrderStatistics 获取用户订单统计
func (s *OrderService) GetUserOrderStatistics(userID uint) (map[string]interface{}, error) {
stats, err := s.orderRepo.GetUserOrderStatistics(userID)
if err != nil {
return nil, err
}
return stats, nil
}
// GetOrderDetail 获取订单详情
func (s *OrderService) GetOrderDetail(userID uint, orderID uint) (*model.Order, error) {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return nil, errors.New("订单不存在")
}
// 检查订单是否属于当前用户
if order.UserID != userID {
return nil, errors.New("无权访问该订单")
}
return order, nil
}
// GetOrderDetailByOrderNo 通过订单号获取订单详情(支持订单号或微信订单号)
func (s *OrderService) GetOrderDetailByOrderNo(userID uint, orderNo string) (*model.Order, error) {
var order *model.Order
var err error
// 先尝试使用订单号查询
order, err = s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
// 如果订单号查询失败,尝试使用微信订单号查询
order, err = s.orderRepo.GetOrderByWechatOutTradeNo(orderNo)
if err != nil {
return nil, errors.New("订单不存在")
}
}
// 检查订单是否属于当前用户
if order.UserID != userID {
return nil, errors.New("无权访问该订单")
}
return order, nil
}
// GetOrderByOrderNo 通过订单号获取订单信息(不验证用户权限,用于支付回调等场景)
func (s *OrderService) GetOrderByOrderNo(orderNo string) (*model.Order, error) {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return nil, errors.New("订单不存在")
}
return order, nil
}
// PayOrder 支付订单
func (s *OrderService) PayOrder(userID uint, orderNo string) error {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单是否属于当前用户
if order.UserID != userID {
return errors.New("无权操作该订单")
}
// 检查订单状态
if order.Status != 1 {
return errors.New("订单状态不正确")
}
// 库存已在订单创建时预扣,支付成功时无需再次扣减
fmt.Printf("💰 [PayOrder] 支付成功,库存已在订单创建时预扣 - 订单号: %s\n", orderNo)
// 获取订单项以更新销量
orderItems, err := s.orderRepo.GetOrderItems(order.ID)
if err != nil {
fmt.Printf("❌ [PayOrder] 获取订单项失败: %v\n", err)
return errors.New("获取订单项失败")
}
// 支付成功时更新销量
for _, item := range orderItems {
err := s.productRepo.UpdateSales(item.ProductID, item.Quantity)
if err != nil {
fmt.Printf("❌ [PayOrder] 更新销量失败 - 产品ID: %d, 数量: %d, 错误: %v\n", item.ProductID, item.Quantity, err)
// 销量更新失败不影响支付成功,只记录日志
} else {
fmt.Printf("✅ [PayOrder] 支付成功,更新销量 - 产品ID: %d, 数量: %d\n", item.ProductID, item.Quantity)
}
}
// 模拟支付成功,更新订单状态
updates := map[string]interface{}{
"status": 2, // 待发货
"pay_status": 1, // 已支付
"pay_time": time.Now(),
"updated_at": time.Now(),
}
// 添加调试日志
fmt.Printf("🔄 [PayOrder] 开始更新订单 %s用户ID: %d\n", orderNo, userID)
fmt.Printf("🔄 [PayOrder] 更新数据: %+v\n", updates)
err = s.orderRepo.UpdateByOrderNo(orderNo, updates)
if err != nil {
fmt.Printf("❌ [PayOrder] 数据库更新失败: %v\n", err)
// 如果订单更新失败,库存已在创建时预扣,无需额外处理
return err
}
fmt.Printf("✅ [PayOrder] 数据库更新成功\n")
return nil
}
// GetPendingOrdersCount 获取待处理订单数量
func (s *OrderService) GetPendingOrdersCount() (int64, error) {
return s.orderRepo.GetPendingOrdersCount()
}
// GetRegionStatistics 获取地区统计
func (s *OrderService) GetRegionStatistics(startDate, endDate string) ([]map[string]interface{}, error) {
// 简化实现,返回基础地区统计数据
var results []map[string]interface{}
// 模拟地区数据
regions := []string{"北京", "上海", "广州", "深圳", "杭州", "南京", "成都", "武汉"}
for i, region := range regions {
results = append(results, map[string]interface{}{
"region": region,
"order_count": 100 - i*8,
"order_amount": float64(10000 - i*800),
})
}
return results, nil
}
// GetPaymentMethodStatistics 获取支付方式统计
func (s *OrderService) GetPaymentMethodStatistics(startDate, endDate string) ([]map[string]interface{}, error) {
// 简化实现,返回基础支付方式统计数据
var results []map[string]interface{}
// 模拟支付方式数据
paymentMethods := []map[string]interface{}{
{"method": "微信支付", "count": 150, "amount": 15000.0},
{"method": "支付宝", "count": 120, "amount": 12000.0},
{"method": "银行卡", "count": 80, "amount": 8000.0},
{"method": "余额支付", "count": 50, "amount": 5000.0},
}
results = paymentMethods
return results, nil
}
// GetRefundStatistics 获取退款统计
func (s *OrderService) GetRefundStatistics(startDate, endDate string) (map[string]interface{}, error) {
// 简化实现,返回基础退款统计数据
result := map[string]interface{}{
"total_refund_count": 25,
"total_refund_amount": 2500.0,
"refund_rate": 0.05, // 5%退款率
"avg_refund_amount": 100.0,
"refund_reasons": []map[string]interface{}{
{"reason": "商品质量问题", "count": 10},
{"reason": "不喜欢", "count": 8},
{"reason": "尺寸不合适", "count": 5},
{"reason": "其他", "count": 2},
},
}
return result, nil
}
// RefundOrderDuplicate 申请退款(重复方法,已移除)
func (s *OrderService) RefundOrderDuplicate(userID uint, orderNo string) error {
log.Printf("[服务层] 开始处理退款申请: userID=%d, orderNo=%s", userID, orderNo)
// 获取订单信息
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
log.Printf("[服务层] 退款申请失败: 订单不存在, orderNo=%s, error=%v", orderNo, err)
return errors.New("订单不存在")
}
log.Printf("[服务层] 找到订单: ID=%d, UserID=%d, Status=%d, CreatedAt=%v",
order.ID, order.UserID, order.Status, order.CreatedAt)
// 验证用户权限
if order.UserID != userID {
log.Printf("[服务层] 退款申请失败: 订单不属于当前用户, orderUserID=%d, requestUserID=%d", order.UserID, userID)
return errors.New("无权操作此订单")
}
// 验证订单状态是否允许退款(已付款状态)
if order.Status != 2 && order.Status != 3 && order.Status != 4 {
log.Printf("[服务层] 退款申请失败: 订单状态不允许退款, currentStatus=%d", order.Status)
return errors.New("订单状态不允许退款")
}
// 获取订单项以恢复库存和减少销量
orderItems, err := s.orderRepo.GetOrderItems(order.ID)
if err != nil {
log.Printf("[服务层] 获取订单项失败: %v", err)
return errors.New("获取订单项失败")
}
// 恢复库存
for _, item := range orderItems {
err := s.productRepo.RestoreStock(item.ProductID, item.Quantity)
if err != nil {
log.Printf("❌ [RefundOrder] 恢复库存失败 - 产品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
} else {
log.Printf("✅ [RefundOrder] 成功恢复库存 - 产品ID: %d, 数量: %d", item.ProductID, item.Quantity)
}
}
// 如果订单已完成状态为4需要减少销量
if order.Status == 4 {
for _, item := range orderItems {
err := s.productRepo.UpdateSales(item.ProductID, -item.Quantity) // 负数表示减少
if err != nil {
log.Printf("❌ [RefundOrder] 减少销量失败 - 产品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
} else {
log.Printf("✅ [RefundOrder] 成功减少销量 - 产品ID: %d, 数量: %d", item.ProductID, item.Quantity)
}
}
}
// 更新订单状态为退款中(8)
log.Printf("[服务层] 更新订单状态为退款中: 原状态=%d", order.Status)
updates := map[string]interface{}{
"status": 8, // 退款中状态
"refund_time": time.Now(),
"updated_at": time.Now(),
}
// 保存订单更新
if err := s.orderRepo.UpdateByOrderNo(orderNo, updates); err != nil {
log.Printf("[服务层] 更新订单状态失败: %v", err)
return err
}
log.Printf("[服务层] 退款申请处理成功: orderNo=%s", orderNo)
return nil
}
// CancelOrder 取消订单
func (s *OrderService) CancelOrder(userID uint, orderNo string) error {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单是否属于当前用户
if order.UserID != userID {
return errors.New("无权操作该订单")
}
// 检查订单状态(只有待付款的订单可以取消)
if order.Status != 1 {
return errors.New("订单状态不正确,无法取消")
}
// 恢复库存
items, err := s.orderRepo.GetOrderItems(order.ID)
if err == nil {
for _, item := range items {
var err error
if item.SKUID != nil && *item.SKUID > 0 {
// 如果有SKU同时恢复SKU库存和商品库存
err = s.productRepo.RestoreStockWithSKU(item.ProductID, item.SKUID, item.Quantity)
} else {
// 如果没有SKU只恢复商品库存
err = s.productRepo.RestoreStock(item.ProductID, item.Quantity)
}
if err != nil {
log.Printf("恢复库存失败 - 商品ID: %d, SKU ID: %v, 数量: %d, 错误: %v", item.ProductID, item.SKUID, item.Quantity, err)
}
}
// 取消订单时只需恢复库存,无需减少销量(因为只有待付款订单才能取消,销量尚未增加)
}
// 恢复优惠券(如果订单使用了优惠券)
if order.CouponID != nil && *order.CouponID > 0 {
// 根据订单ID查找对应的用户优惠券
userCoupon, err := s.couponRepo.GetUserCouponByOrderID(order.ID)
if err != nil {
log.Printf("查找用户优惠券失败: orderID=%d, couponID=%d, error=%v", order.ID, *order.CouponID, err)
} else {
if err := s.couponRepo.RestoreCoupon(userCoupon.ID); err != nil {
log.Printf("恢复优惠券失败: userCouponID=%d, orderID=%d, error=%v", userCoupon.ID, order.ID, err)
} else {
log.Printf("优惠券恢复成功: userCouponID=%d, orderID=%d", userCoupon.ID, order.ID)
}
}
// 不阻止订单取消,只记录日志
}
// 更新订单状态
updates := map[string]interface{}{
"status": 6, // 已取消
"updated_at": time.Now(),
}
return s.orderRepo.UpdateByOrderNo(orderNo, updates)
}
// RemindShip 提醒发货
func (s *OrderService) RemindShip(userID uint, orderNo string) error {
log.Printf("[服务层] ===== 提醒发货服务开始 =====")
log.Printf("[服务层] 提醒发货参数: userID=%d, orderNo=%s", userID, orderNo)
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
log.Printf("[服务层] 提醒发货失败: 订单不存在, orderNo=%s, error=%v", orderNo, err)
return errors.New("订单不存在")
}
log.Printf("[服务层] 找到订单: ID=%d, UserID=%d, Status=%d, CreatedAt=%v",
order.ID, order.UserID, order.Status, order.CreatedAt)
// 检查订单是否属于当前用户
if order.UserID != userID {
log.Printf("[服务层] 提醒发货失败: 订单不属于当前用户, orderUserID=%d, requestUserID=%d", order.UserID, userID)
return errors.New("无权操作该订单")
}
// 检查订单状态(只有已付款/待发货的订单可以提醒发货)
if order.Status != 2 && order.Status != 3 {
log.Printf("[服务层] 提醒发货失败: 订单状态不正确, currentStatus=%d, 期望状态=2或3", order.Status)
return errors.New("订单状态不正确,无法提醒发货")
}
// 检查订单创建时间如果是刚创建的订单10分钟内提示用户稍后再试
if time.Since(order.CreatedAt) < 10*time.Minute {
log.Printf("[服务层] 提醒发货失败: 订单创建时间过短, 创建时间=%v, 当前时间=%v, 需等待=%v",
order.CreatedAt, time.Now(), 10*time.Minute-time.Since(order.CreatedAt))
return errors.New("订单刚创建请10分钟后再提醒发货")
}
// 这里可以添加实际的提醒逻辑,比如发送通知给商家
// 1. 发送短信通知商家
// 2. 发送邮件通知商家
// 3. 在商家后台系统中创建提醒记录
// 4. 推送消息到商家APP
log.Printf("[服务层] 🔔 提醒发货成功: 用户 %d 提醒发货订单 %s", userID, orderNo)
log.Printf("[服务层] 📦 商家将收到发货提醒通知")
return nil
}
// RefundOrderLegacy 申请退款(旧方法)
func (s *OrderService) RefundOrderLegacy(userID uint, orderNo string) error {
// 此方法已被移除使用上面的RefundOrder方法
return nil
// 获取订单信息
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
log.Printf("[服务层] 退款申请失败: 订单不存在, orderNo=%s, error=%v", orderNo, err)
return errors.New("订单不存在")
}
log.Printf("[服务层] 找到订单: ID=%d, UserID=%d, Status=%d, CreatedAt=%v",
order.ID, order.UserID, order.Status, order.CreatedAt)
// 验证用户权限
if order.UserID != userID {
log.Printf("[服务层] 退款申请失败: 订单不属于当前用户, orderUserID=%d, requestUserID=%d", order.UserID, userID)
return errors.New("无权操作此订单")
}
// 验证订单状态是否允许退款(已付款状态)
if order.Status != 2 && order.Status != 3 {
log.Printf("[服务层] 退款申请失败: 订单状态不允许退款, currentStatus=%d", order.Status)
return errors.New("订单状态不允许退款,只有已付款待发货的订单可以申请退款")
}
// 更新订单状态为已退款(9)
log.Printf("[服务层] 更新订单状态为已退款: 原状态=%d", order.Status)
updates := map[string]interface{}{
"status": 9, // 已退款状态
"refund_time": time.Now(),
"updated_at": time.Now(),
}
// 保存订单更新
if err := s.orderRepo.UpdateByOrderNo(orderNo, updates); err != nil {
log.Printf("[服务层] 更新订单状态失败: %v", err)
return err
}
log.Printf("[服务层] 退款申请处理成功: orderNo=%s", orderNo)
return nil
}
// ConfirmReceive 确认收货
func (s *OrderService) ConfirmReceive(userID uint, orderNo string) error {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单是否属于当前用户
if order.UserID != userID {
return errors.New("无权操作该订单")
}
// 检查订单状态(只有已发货(4)或待收货(5)的订单可以确认收货)
if order.Status != 4 && order.Status != 5 {
return errors.New("订单状态不正确")
}
fmt.Printf("✅ [ConfirmReceive] 确认收货成功 - 订单号: %s (销量已在支付时更新)\n", orderNo)
// 更新订单状态
updates := map[string]interface{}{
"status": 6, // 已完成
"receive_time": time.Now(),
"updated_at": time.Now(),
}
return s.orderRepo.UpdateByOrderNo(orderNo, updates)
}
// GetOrderList 获取订单列表(管理员)
func (s *OrderService) GetOrderList(page, pageSize int, conditions map[string]interface{}) ([]model.Order, *utils.Pagination, error) {
if page <= 0 {
page = 1
}
if pageSize <= 0 || pageSize > 100 {
pageSize = 20
}
offset := (page - 1) * pageSize
orders, total, err := s.orderRepo.GetList(offset, pageSize, conditions)
if err != nil {
return nil, nil, err
}
pagination := utils.NewPagination(page, pageSize)
pagination.Total = total
return orders, pagination, nil
}
// ShipOrder 发货(管理员)
func (s *OrderService) ShipOrder(orderNo, logisticsCompany, logisticsNo string) error {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单状态(只有待发货的订单可以发货)
if order.Status != 2 && order.Status != 3 {
return errors.New("订单状态不正确")
}
// 更新订单状态
updates := map[string]interface{}{
"status": 4, // 已发货
"logistics_company": logisticsCompany,
"logistics_no": logisticsNo,
"shipped_at": time.Now(),
"updated_at": time.Now(),
}
return s.orderRepo.UpdateByOrderNo(orderNo, updates)
}
// ShipOrderByID 通过订单ID发货
func (s *OrderService) ShipOrderByID(orderID uint, logisticsCompany, logisticsNo string) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单状态(只有待发货的订单可以发货)
if order.Status != 2 && order.Status != 3 {
return errors.New("订单状态不正确")
}
// 更新订单状态
updates := map[string]interface{}{
"status": 4, // 已发货
"logistics_company": logisticsCompany,
"logistics_no": logisticsNo,
"shipped_at": time.Now(),
"updated_at": time.Now(),
}
return s.orderRepo.Update(orderID, updates)
}
// MergeOrders 合并订单
func (s *OrderService) MergeOrders(userID uint, req *MergeOrdersRequest) (*model.Order, error) {
// 1. 验证订单数量
if len(req.OrderIDs) < 2 {
return nil, errors.New("至少需要选择2个订单进行合并")
}
// 2. 获取所有要合并的订单
var orders []model.Order
var orderIDs []uint
for _, orderIDStr := range req.OrderIDs {
orderID := uint(0)
if _, err := fmt.Sscanf(orderIDStr, "%d", &orderID); err != nil {
return nil, errors.New("订单ID格式错误")
}
orderIDs = append(orderIDs, orderID)
}
// 获取订单详情
for _, orderID := range orderIDs {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return nil, errors.New("订单不存在")
}
// 验证订单所有权
if order.UserID != userID {
return nil, errors.New("无权限操作此订单")
}
orders = append(orders, *order)
}
// 3. 验证订单合并条件
if err := s.validateOrdersForMerge(orders); err != nil {
return nil, err
}
// 4. 创建合并后的新订单
mergedOrder, err := s.createMergedOrder(orders)
if err != nil {
return nil, err
}
// 5. 删除原订单
for _, orderID := range orderIDs {
if err := s.orderRepo.Delete(orderID); err != nil {
// 如果删除失败,需要回滚新创建的订单
s.orderRepo.Delete(mergedOrder.ID)
return nil, errors.New("合并订单失败,请重试")
}
}
return mergedOrder, nil
}
// validateOrdersForMerge 验证订单是否可以合并
func (s *OrderService) validateOrdersForMerge(orders []model.Order) error {
if len(orders) < 2 {
return errors.New("至少需要2个订单才能合并")
}
firstOrder := orders[0]
for _, order := range orders {
// 检查订单状态:只能合并未支付的订单
if order.Status != 1 || order.PayStatus != 0 {
return errors.New("只能合并未支付的订单")
}
// 检查用户ID是否一致
if order.UserID != firstOrder.UserID {
return errors.New("只能合并同一用户的订单")
}
// 检查收货地址是否一致
if order.ReceiverName != firstOrder.ReceiverName ||
order.ReceiverPhone != firstOrder.ReceiverPhone ||
order.ReceiverAddress != firstOrder.ReceiverAddress {
return errors.New("只能合并相同收货地址的订单")
}
}
return nil
}
// createMergedOrder 创建合并后的订单
func (s *OrderService) createMergedOrder(orders []model.Order) (*model.Order, error) {
firstOrder := orders[0]
// 创建新订单
mergedOrder := &model.Order{
OrderNo: utils.GenerateOrderNo(),
UserID: firstOrder.UserID,
StoreID: firstOrder.StoreID,
Status: 1, // 待付款
PayStatus: 0, // 未支付
ReceiverName: firstOrder.ReceiverName,
ReceiverPhone: firstOrder.ReceiverPhone,
ReceiverAddress: firstOrder.ReceiverAddress,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
// 合并所有订单项
var allOrderItems []model.OrderItem
var totalAmount float64
var totalDiscountAmount float64
var totalCouponAmount float64
var totalShippingFee float64
for _, order := range orders {
// 累加金额
totalAmount += order.TotalAmount
totalDiscountAmount += order.DiscountAmount
totalCouponAmount += order.CouponAmount
totalShippingFee += order.ShippingFee
// 收集订单项
for _, item := range order.OrderItems {
newItem := model.OrderItem{
OrderID: mergedOrder.ID,
ProductID: item.ProductID,
SKUID: item.SKUID,
Quantity: item.Quantity,
Price: item.Price,
TotalPrice: item.TotalPrice,
ProductName: item.ProductName,
ProductImage: item.ProductImage,
SpecInfo: item.SpecInfo,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
allOrderItems = append(allOrderItems, newItem)
}
}
// 设置合并后的金额
mergedOrder.TotalAmount = totalAmount
mergedOrder.PayAmount = totalAmount - totalDiscountAmount - totalCouponAmount + totalShippingFee
mergedOrder.DiscountAmount = totalDiscountAmount
mergedOrder.CouponAmount = totalCouponAmount
mergedOrder.ShippingFee = totalShippingFee
mergedOrder.OrderItems = allOrderItems
// 保存到数据库
if err := s.orderRepo.Create(mergedOrder); err != nil {
return nil, err
}
return mergedOrder, nil
}
// GetOrderListForAdmin 获取订单列表(管理员专用)
func (s *OrderService) GetOrderListForAdmin(page, pageSize int, conditions map[string]interface{}) ([]model.Order, *utils.Pagination, error) {
return s.GetOrderList(page, pageSize, conditions)
}
// GetOrderDetailForAdmin 获取订单详情(管理员专用)
func (s *OrderService) GetOrderDetailForAdmin(orderID uint) (*model.Order, error) {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return nil, errors.New("订单不存在")
}
return order, nil
}
// UpdateOrderStatusByAdmin 更新订单状态(管理员专用)
func (s *OrderService) UpdateOrderStatusByAdmin(orderID uint, status int, adminRemark string) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
// 验证状态转换的合法性
if !s.isValidStatusTransition(order.Status, status) {
return errors.New("无效的状态转换")
}
updates := map[string]interface{}{
"status": status,
"admin_remark": adminRemark,
"updated_at": time.Now(),
}
// 根据状态设置相应的时间字段
switch status {
case 2: // 已付款
updates["pay_time"] = time.Now()
case 4: // 已发货
updates["ship_time"] = time.Now()
case 6: // 已完成
updates["receive_time"] = time.Now()
case 7: // 已取消
updates["cancel_time"] = time.Now()
}
return s.orderRepo.Update(orderID, updates)
}
// RefundOrder 退款订单(管理员专用)
func (s *OrderService) RefundOrder(orderID uint, refundAmount float64, refundReason string, adminID uint) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
log.Printf("🔍 [RefundOrder] 订单状态检查 - 订单ID: %d, 当前状态: %d, 状态名称: %s", orderID, order.Status, s.getOrderStatusName(order.Status))
// 检查订单状态
if order.Status != 2 && order.Status != 3 && order.Status != 4 && order.Status != 5 {
log.Printf("❌ [RefundOrder] 订单状态不允许退款 - 订单ID: %d, 状态: %d", orderID, order.Status)
return errors.New("订单状态不允许退款")
}
log.Printf("✅ [RefundOrder] 订单状态检查通过 - 订单ID: %d, 状态: %d", orderID, order.Status)
// 检查退款金额
if refundAmount <= 0 || refundAmount > order.PayAmount {
return errors.New("退款金额无效")
}
// 获取订单商品项
orderItems, err := s.orderRepo.GetOrderItems(order.ID)
if err != nil {
log.Printf("获取订单商品项失败: %v", err)
return errors.New("获取订单商品项失败")
}
// 恢复库存
for _, item := range orderItems {
err := s.productRepo.RestoreStock(item.ProductID, item.Quantity)
if err != nil {
log.Printf("恢复库存失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
}
}
// 如果订单已支付,需要减少销量(因为销量在支付时就增加了)
if order.Status >= 2 && order.PayStatus == 1 {
for _, item := range orderItems {
err := s.productRepo.UpdateSales(item.ProductID, -item.Quantity)
if err != nil {
log.Printf("❌ [RefundOrder] 减少销量失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
} else {
log.Printf("✅ [RefundOrder] 退款成功,减少销量 - 商品ID: %d, 数量: %d", item.ProductID, item.Quantity)
}
}
}
updates := map[string]interface{}{
"status": 9, // 已退款
"refund_amount": refundAmount,
"refund_reason": refundReason,
"refund_time": time.Now(),
"updated_at": time.Now(),
}
log.Printf("🔄 [RefundOrder] 准备更新订单 - 订单ID: %d", orderID)
log.Printf("🔄 [RefundOrder] 更新字段: %+v", updates)
err = s.orderRepo.Update(orderID, updates)
if err != nil {
log.Printf("❌ [RefundOrder] 数据库更新失败 - 订单ID: %d, 错误: %v", orderID, err)
return err
}
log.Printf("✅ [RefundOrder] 数据库更新成功 - 订单ID: %d", orderID)
return nil
}
// CancelOrderByAdmin 取消订单(管理员专用)
func (s *OrderService) CancelOrderByAdmin(orderID uint, cancelReason string, adminID uint) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单状态
if order.Status == 6 || order.Status == 7 || order.Status == 9 {
return errors.New("订单已完成、已取消或已退款,无法取消")
}
// 恢复库存
items, err := s.orderRepo.GetOrderItems(order.ID)
if err == nil {
for _, item := range items {
if item.SKUID != nil && *item.SKUID > 0 {
// 如果有SKU同时恢复SKU库存和商品库存
err := s.productRepo.RestoreStockWithSKU(item.ProductID, item.SKUID, item.Quantity)
if err != nil {
log.Printf("管理员取消订单时恢复SKU库存失败 - 商品ID: %d, SKU ID: %d, 数量: %d, 错误: %v", item.ProductID, *item.SKUID, item.Quantity, err)
}
} else {
// 如果没有SKU只恢复商品库存
s.productRepo.UpdateStock(item.ProductID, int(item.Quantity))
}
}
}
// 恢复优惠券(如果订单使用了优惠券)
if order.CouponID != nil && *order.CouponID > 0 {
if err := s.couponRepo.RestoreCoupon(*order.CouponID); err != nil {
log.Printf("管理员取消订单时恢复优惠券失败: orderID=%d, couponID=%d, error=%v", orderID, *order.CouponID, err)
// 不阻止订单取消,只记录日志
}
}
updates := map[string]interface{}{
"status": 7, // 已取消
"cancel_reason": cancelReason,
"cancel_time": time.Now(),
"updated_at": time.Now(),
}
return s.orderRepo.Update(orderID, updates)
}
// GetOrderStatisticsWithDateRange 获取订单统计(带日期范围)
func (s *OrderService) GetOrderStatisticsWithDateRange(startDate, endDate string) (map[string]interface{}, error) {
// 暂时使用基础统计方法,后续可以扩展支持日期范围
return s.orderRepo.GetOrderStatistics()
}
// GetDailyOrderStatisticsWithDateRange 获取每日订单统计(带日期范围)
func (s *OrderService) GetDailyOrderStatisticsWithDateRange(startDate, endDate string) ([]map[string]interface{}, error) {
// 解析日期范围,计算天数
start, err := time.Parse("2006-01-02", startDate)
if err != nil {
return nil, fmt.Errorf("invalid start date format: %v", err)
}
end, err := time.Parse("2006-01-02", endDate)
if err != nil {
return nil, fmt.Errorf("invalid end date format: %v", err)
}
// 计算天数差
days := int(end.Sub(start).Hours()/24) + 1
if days <= 0 {
days = 1
}
// 使用基础统计方法,但确保天数正确
return s.orderRepo.GetDailyOrderStatistics(days)
}
// isValidStatusTransition 检查状态转换是否合法
func (s *OrderService) isValidStatusTransition(currentStatus, newStatus int) bool {
// 定义合法的状态转换
validTransitions := map[int][]int{
1: {2, 7}, // 未付款 -> 已付款, 已取消
2: {3, 7, 8, 9}, // 已付款 -> 待发货, 已取消, 退货中, 已退款
3: {4, 7, 8, 9}, // 待发货 -> 已发货, 已取消, 退货中, 已退款
4: {5, 8, 9}, // 已发货 -> 待收货, 退货中, 已退款
5: {6, 8, 9}, // 待收货 -> 已完成, 退货中, 已退款
6: {8, 9}, // 已完成 -> 退货中, 已退款
7: {}, // 已取消 -> 无法转换到其他状态
8: {9}, // 退货中 -> 已退款
9: {}, // 已退款 -> 无法转换到其他状态
}
allowedStatuses, exists := validTransitions[currentStatus]
if !exists {
return false
}
for _, status := range allowedStatuses {
if status == newStatus {
return true
}
}
return false
}
// GetLogisticsInfo 获取物流信息
func (s *OrderService) GetLogisticsInfo(orderNo string) (map[string]interface{}, error) {
order, err := s.orderRepo.GetByOrderNo(orderNo)
if err != nil {
return nil, errors.New("订单不存在")
}
if order.LogisticsCompany == "" || order.LogisticsNo == "" {
return nil, errors.New("订单尚未发货")
}
// 构建物流信息
logisticsInfo := map[string]interface{}{
"order_no": order.OrderNo,
"express_company": order.LogisticsCompany,
"express_no": order.LogisticsNo,
"receiver_name": order.ReceiverName,
"receiver_phone": order.ReceiverPhone,
"receiver_address": order.ReceiverAddress,
"ship_time": order.ShippedAt,
"status": order.Status,
"status_name": s.getOrderStatusName(order.Status),
}
// 这里可以集成第三方物流API获取实时物流信息
// 暂时返回基本信息
logisticsInfo["tracks"] = []map[string]interface{}{
{
"time": order.ShippedAt,
"description": "商品已发货",
"location": "发货地",
},
}
return logisticsInfo, nil
}
// UpdateOrderStatus 更新订单状态
func (s *OrderService) UpdateOrderStatus(orderID uint, status int, adminID uint) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
// 验证状态转换的合法性
if !s.isValidStatusTransition(order.Status, status) {
return errors.New("无效的状态转换")
}
updates := map[string]interface{}{
"status": status,
"updated_at": time.Now(),
}
// 根据状态设置相应的时间字段
switch status {
case 2: // 已付款
updates["pay_time"] = time.Now()
updates["pay_status"] = 1
case 4: // 已发货
updates["shipped_at"] = time.Now()
case 6: // 已完成
updates["receive_time"] = time.Now()
case 7: // 已取消
updates["cancel_time"] = time.Now()
case 8: // 退货中
// 退货中状态不需要特殊的时间字段,由退款记录表管理
case 9: // 已退款
updates["refund_time"] = time.Now()
}
err = s.orderRepo.Update(orderID, updates)
if err != nil {
return err
}
// 处理状态变更后的业务逻辑
return s.handleOrderStatusChange(order, status, adminID)
}
// handleOrderStatusChange 处理订单状态变更后的业务逻辑
func (s *OrderService) handleOrderStatusChange(order *model.Order, newStatus int, adminID uint) error {
switch newStatus {
case 8: // 退货中
// 当订单状态变为退货中时,可以在这里添加额外的业务逻辑
// 例如:通知相关人员、记录日志等
log.Printf("订单 %s 状态变更为退货中", order.OrderNo)
case 9: // 已退款
// 当订单状态变为已退款时,处理库存恢复等业务逻辑
log.Printf("订单 %s 状态变更为已退款,开始处理库存恢复", order.OrderNo)
// 获取订单项
orderItems, err := s.orderRepo.GetOrderItems(order.ID)
if err != nil {
log.Printf("获取订单项失败: %v", err)
return err
}
// 恢复库存(如果订单已支付)
if order.Status >= 2 && order.PayStatus == 1 {
for _, item := range orderItems {
// 恢复库存
err := s.productRepo.UpdateStock(item.ProductID, item.Quantity)
if err != nil {
log.Printf("恢复库存失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
} else {
log.Printf("库存恢复成功 - 商品ID: %d, 数量: %d", item.ProductID, item.Quantity)
}
// 减少销量
err = s.productRepo.UpdateSales(item.ProductID, -item.Quantity)
if err != nil {
log.Printf("减少销量失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
} else {
log.Printf("销量减少成功 - 商品ID: %d, 数量: %d", item.ProductID, item.Quantity)
}
}
}
}
return nil
}
// BatchUpdateOrderStatus 批量更新订单状态
func (s *OrderService) BatchUpdateOrderStatus(orderIDs []uint, status int, adminID uint) error {
for _, orderID := range orderIDs {
if err := s.UpdateOrderStatus(orderID, status, adminID); err != nil {
return fmt.Errorf("更新订单 %d 状态失败: %v", orderID, err)
}
}
return nil
}
// ProcessRefund 处理退款
func (s *OrderService) ProcessRefund(orderID uint, refundAmount float64, refundReason string, adminID uint) error {
order, err := s.orderRepo.GetByID(orderID)
if err != nil {
return errors.New("订单不存在")
}
// 检查订单状态
if order.Status != 2 && order.Status != 3 && order.Status != 4 && order.Status != 5 {
return errors.New("订单状态不允许退款")
}
// 检查退款金额
if refundAmount <= 0 || refundAmount > order.PayAmount {
return errors.New("退款金额无效")
}
// 获取订单商品项
orderItems, err := s.orderRepo.GetOrderItems(order.ID)
if err != nil {
return errors.New("获取订单商品项失败")
}
// 恢复库存
for _, item := range orderItems {
if err := s.productRepo.RestoreStock(item.ProductID, item.Quantity); err != nil {
log.Printf("恢复库存失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
}
}
// 减少销量
if order.Status >= 2 && order.PayStatus == 1 {
for _, item := range orderItems {
if err := s.productRepo.UpdateSales(item.ProductID, -item.Quantity); err != nil {
log.Printf("减少销量失败 - 商品ID: %d, 数量: %d, 错误: %v", item.ProductID, item.Quantity, err)
}
}
}
// 更新订单状态
updates := map[string]interface{}{
"status": 9, // 已退款
"refund_amount": refundAmount,
"refund_time": time.Now(),
"cancel_reason": refundReason,
"updated_at": time.Now(),
}
return s.orderRepo.Update(orderID, updates)
}
// GetOrderStatistics 获取订单统计
func (s *OrderService) GetOrderStatistics() (map[string]interface{}, error) {
return s.orderRepo.GetOrderStatistics()
}
// GetDailyOrderStatistics 获取每日订单统计
func (s *OrderService) GetDailyOrderStatistics(days int) ([]map[string]interface{}, error) {
return s.orderRepo.GetDailyOrderStatistics(days)
}
// GetOrdersByDateRange 根据日期范围获取订单
func (s *OrderService) GetOrdersByDateRange(startDate, endDate string, status int, offset, limit int) ([]model.Order, int64, error) {
conditions := make(map[string]interface{})
if startDate != "" {
conditions["start_date"] = startDate
}
if endDate != "" {
conditions["end_date"] = endDate
}
if status > 0 {
conditions["status"] = status
}
return s.orderRepo.GetList(offset, limit, conditions)
}
// ExportOrdersToExcel 导出订单到Excel
func (s *OrderService) ExportOrdersToExcel(conditions map[string]interface{}) ([]map[string]interface{}, error) {
// 获取所有符合条件的订单
orders, _, err := s.orderRepo.GetList(0, 10000, conditions) // 限制最大导出数量
if err != nil {
return nil, err
}
var exportData []map[string]interface{}
for _, order := range orders {
data := map[string]interface{}{
"订单号": order.OrderNo,
"用户ID": order.UserID,
"店铺ID": order.StoreID,
"订单状态": s.getOrderStatusName(order.Status),
"订单金额": order.TotalAmount,
"实付金额": order.PayAmount,
"优惠金额": order.DiscountAmount,
"运费": order.ShippingFee,
"收货人": order.ReceiverName,
"收货电话": order.ReceiverPhone,
"收货地址": order.ReceiverAddress,
"快递公司": order.LogisticsCompany,
"快递单号": order.LogisticsNo,
"支付方式": order.PayMethod,
"支付时间": s.formatTime(order.PayTime),
"发货时间": s.formatTime(order.ShippedAt),
"收货时间": s.formatTime(order.ReceiveTime),
"取消时间": s.formatTime(order.CancelTime),
"取消原因": order.CancelReason,
"退款金额": order.RefundAmount,
"退款时间": s.formatTime(order.RefundTime),
"备注": order.Remark,
"创建时间": order.CreatedAt.Format("2006-01-02 15:04:05"),
"更新时间": order.UpdatedAt.Format("2006-01-02 15:04:05"),
}
exportData = append(exportData, data)
}
return exportData, nil
}
// GetOrderTrends 获取订单趋势
func (s *OrderService) GetOrderTrends(days int) (map[string]interface{}, error) {
dailyStats, err := s.GetDailyOrderStatistics(days)
if err != nil {
return nil, err
}
var dates []string
var orderCounts []int
var amounts []float64
for _, stat := range dailyStats {
if date, ok := stat["date"].(string); ok {
dates = append(dates, date)
}
if count, ok := stat["order_count"].(int64); ok {
orderCounts = append(orderCounts, int(count))
}
if amount, ok := stat["total_amount"].(float64); ok {
amounts = append(amounts, amount)
}
}
return map[string]interface{}{
"dates": dates,
"order_counts": orderCounts,
"amounts": amounts,
}, nil
}
// getOrderStatusName 获取订单状态名称
func (s *OrderService) getOrderStatusName(status int) string {
statusNames := map[int]string{
1: "未付款",
2: "待发货", // 统一为待发货
3: "待发货", // 统一为待发货
4: "已发货",
5: "待收货",
6: "已完成",
7: "已取消",
8: "退货中",
9: "已退款",
}
if name, exists := statusNames[status]; exists {
return name
}
return "未知状态"
}
// formatTime 格式化时间
func (s *OrderService) formatTime(t *time.Time) string {
if t == nil {
return ""
}
return t.Format("2006-01-02 15:04:05")
}