Files
ai_dianshang/server/internal/handler/order_settle.go

322 lines
11 KiB
Go
Raw Permalink Normal View History

2025-11-17 14:11:46 +08:00
package handler
import (
"dianshang/internal/service"
"dianshang/pkg/response"
"dianshang/pkg/utils"
"fmt"
"github.com/gin-gonic/gin"
)
// OrderSettleHandler 订单结算处理器
type OrderSettleHandler struct {
orderService *service.OrderService
productService *service.ProductService
userService *service.UserService
}
// NewOrderSettleHandler 创建订单结算处理器
func NewOrderSettleHandler(orderService *service.OrderService, productService *service.ProductService, userService *service.UserService) *OrderSettleHandler {
return &OrderSettleHandler{
orderService: orderService,
productService: productService,
userService: userService,
}
}
// SettleOrderRequest 订单结算请求
type SettleOrderRequest struct {
UserAddressReq *UserAddressRequest `json:"userAddressReq"`
CouponList []CouponRequest `json:"couponList"`
GoodsRequestList []GoodsRequest `json:"goodsRequestList"`
StoreInfoList []StoreInfo `json:"storeInfoList"` // 添加门店信息列表
}
// UserAddressRequest 用户地址请求
type UserAddressRequest struct {
AddressID uint `json:"addressId"`
Name string `json:"name"`
Phone string `json:"phone"`
Address string `json:"address"`
DetailAddress string `json:"detailAddress"` // 添加详细地址字段支持前端address-card组件
ProvinceCode string `json:"provinceCode"`
CityCode string `json:"cityCode"`
DistrictCode string `json:"districtCode"`
}
// CouponRequest 优惠券请求
type CouponRequest struct {
CouponID uint `json:"couponId"` // 优惠券模板ID
UserCouponID uint `json:"userCouponId"` // 用户优惠券ID (ai_user_coupons表的id)
Type int `json:"type"`
Value int `json:"value"`
Status string `json:"status"`
}
// StoreInfo 门店信息
type StoreInfo struct {
StoreID string `json:"storeId"`
StoreName string `json:"storeName"`
}
// GoodsRequest 商品请求
type GoodsRequest struct {
StoreID string `json:"storeId"`
SpuID string `json:"spuId"`
SkuID interface{} `json:"skuId"` // 改为interface{}以支持数字和字符串
Title string `json:"title"`
GoodsName string `json:"goodsName"` // 添加商品名称字段
PrimaryImage string `json:"primaryImage"`
Thumb string `json:"thumb"` // 添加缩略图字段
Quantity int `json:"quantity"`
Price int `json:"price"`
OriginPrice int `json:"originPrice"`
Available int `json:"available"` // 添加可用性字段
SpecInfo []SpecInfo `json:"specInfo"`
RoomID interface{} `json:"roomId"`
}
// SpecInfo 规格信息
type SpecInfo struct {
SpecID string `json:"specId"`
SpecTitle string `json:"specTitle"`
SpecValue string `json:"specValue"`
}
// SettleOrder 订单结算
func (h *OrderSettleHandler) SettleOrder(c *gin.Context) {
_, exists := c.Get("user_id")
if !exists {
response.Unauthorized(c)
return
}
var req SettleOrderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "参数错误: "+err.Error())
return
}
// 验证商品信息并计算价格
var totalAmount float64
var totalGoodsCount int
var skuDetailVos []map[string]interface{}
for _, goods := range req.GoodsRequestList {
// 转换SkuID为字符串
var skuIDStr string
switch v := goods.SkuID.(type) {
case string:
skuIDStr = v
case float64:
skuIDStr = fmt.Sprintf("%.0f", v)
case int:
skuIDStr = fmt.Sprintf("%d", v)
default:
skuIDStr = fmt.Sprintf("%v", v)
}
spuID := utils.StringToUint(goods.SpuID)
if spuID == 0 {
response.BadRequest(c, "无效的商品ID: "+goods.SpuID)
return
}
// 获取商品信息
product, err := h.productService.GetProductDetail(spuID)
if err != nil {
response.BadRequest(c, "商品不存在: "+goods.SpuID)
return
}
// 检查库存
if product.Stock < goods.Quantity {
response.BadRequest(c, "商品库存不足: "+product.Name)
return
}
// 获取实际价格优先使用SKU价格如果没有SKU则使用SPU价格
var actualPrice float64
skuID := utils.StringToUint(skuIDStr)
if skuID > 0 {
// 根据SKU ID获取SKU详情和价格
sku, err := h.productService.GetSKUByID(skuID)
if err != nil {
// 如果SKU不存在使用SPU价格
actualPrice = product.Price
} else {
// 使用SKU价格
actualPrice = sku.Price
}
} else {
// 没有SKU ID使用SPU价格
actualPrice = product.Price
}
// 计算商品总价(数据库中价格以分为单位存储,直接计算)
itemTotal := actualPrice * float64(goods.Quantity)
totalAmount += itemTotal
totalGoodsCount += goods.Quantity
// 构建商品详情
skuDetail := map[string]interface{}{
"storeId": goods.StoreID,
"spuId": goods.SpuID,
"skuId": skuIDStr,
"goodsName": product.Name,
"image": product.MainImage,
"reminderStock": product.Stock,
"quantity": goods.Quantity,
"payPrice": actualPrice,
"totalSkuPrice": itemTotal,
"discountSettlePrice": actualPrice,
"realSettlePrice": actualPrice,
"settlePrice": actualPrice,
"oriPrice": actualPrice,
"tagPrice": nil,
"tagText": nil,
"skuSpecLst": goods.SpecInfo,
"promotionIds": nil,
"weight": 0.0,
"unit": "KG",
"volume": nil,
"masterGoodsType": 0,
"viceGoodsType": 0,
"roomId": goods.RoomID,
"egoodsName": nil,
}
skuDetailVos = append(skuDetailVos, skuDetail)
}
// 计算优惠券折扣
var totalCouponAmount float64
for _, coupon := range req.CouponList {
if coupon.Status == "default" {
if coupon.Type == 1 {
// 固定金额优惠券数据库中value以分为单位存储直接累加
totalCouponAmount += float64(coupon.Value)
} else if coupon.Type == 2 {
// 折扣优惠券 - 修复:计算折扣金额而不是最终价格
// 例如8折券(value=80)9900分商品的折扣金额 = 9900 * (100-80) / 100 = 1980分
totalCouponAmount += totalAmount * (100 - float64(coupon.Value)) / 100
}
}
}
// 计算最终支付金额
totalPromotionAmount := 0.0 // 暂时没有促销活动
totalDeliveryFee := 0.0 // 免运费
totalPayAmount := totalAmount - totalCouponAmount - totalPromotionAmount + totalDeliveryFee
// 获取用户地址信息
var userAddress interface{}
settleType := 0
if req.UserAddressReq != nil {
settleType = 1
// 如果有地址ID从数据库获取完整的地址信息
if req.UserAddressReq.AddressID > 0 {
userID, exists := c.Get("user_id")
if exists {
// 获取完整的地址信息
fullAddress, err := h.userService.GetAddressByID(userID.(uint), req.UserAddressReq.AddressID)
if err == nil && fullAddress != nil {
// 构建包含完整信息的地址对象
userAddress = map[string]interface{}{
"addressId": fullAddress.ID,
"name": fullAddress.Name,
"phone": fullAddress.Phone,
"address": fmt.Sprintf("%s%s%s%s", fullAddress.ProvinceName, fullAddress.CityName, fullAddress.DistrictName, fullAddress.DetailAddress),
"detailAddress": fullAddress.DetailAddress,
"provinceName": fullAddress.ProvinceName,
"cityName": fullAddress.CityName,
"districtName": fullAddress.DistrictName,
"provinceCode": req.UserAddressReq.ProvinceCode,
"cityCode": req.UserAddressReq.CityCode,
"districtCode": req.UserAddressReq.DistrictCode,
"isDefault": fullAddress.IsDefault,
}
} else {
// 如果获取失败,使用原始请求数据
userAddress = req.UserAddressReq
}
} else {
// 如果没有用户ID使用原始请求数据
userAddress = req.UserAddressReq
}
} else {
// 如果没有地址ID使用原始请求数据
userAddress = req.UserAddressReq
}
}
// 获取店铺信息
storeID := uint(1000) // 默认店铺ID实际应该从商品信息中获取
if len(req.GoodsRequestList) > 0 {
// 从第一个商品获取店铺ID
if storeIDFromGoods := utils.StringToUint(req.GoodsRequestList[0].StoreID); storeIDFromGoods > 0 {
storeID = storeIDFromGoods
}
}
// 动态获取店铺名称
storeName := "默认店铺" // 默认店铺名
store, err := h.productService.GetStoreByID(storeID)
if err == nil && store != nil {
storeName = store.Name
}
// 构建返回数据(前端期望接收以分为单位的金额字符串)
result := map[string]interface{}{
"settleType": settleType,
"userAddress": userAddress,
"totalGoodsCount": totalGoodsCount,
"packageCount": 1,
"totalAmount": utils.FloatToString(totalAmount), // 已经是分为单位
"totalPayAmount": utils.FloatToString(totalPayAmount), // 已经是分为单位
"totalDiscountAmount": "0",
"totalPromotionAmount": utils.FloatToString(totalPromotionAmount), // 已经是分为单位
"totalCouponAmount": utils.FloatToString(totalCouponAmount), // 已经是分为单位
"totalSalePrice": utils.FloatToString(totalAmount), // 已经是分为单位
"totalGoodsAmount": utils.FloatToString(totalAmount), // 已经是分为单位
"totalDeliveryFee": utils.FloatToString(totalDeliveryFee), // 已经是分为单位
"invoiceRequest": nil,
"skuImages": nil,
"deliveryFeeList": nil,
"storeGoodsList": []map[string]interface{}{
{
"storeId": fmt.Sprintf("%d", storeID),
"storeName": storeName,
"remark": nil,
"goodsCount": totalGoodsCount,
"deliveryFee": utils.FloatToString(totalDeliveryFee), // 已经是分为单位
"deliveryWords": nil,
"storeTotalAmount": utils.FloatToString(totalAmount), // 已经是分为单位
"storeTotalPayAmount": utils.FloatToString(totalPayAmount), // 已经是分为单位
"storeTotalDiscountAmount": "0",
"storeTotalCouponAmount": utils.FloatToString(totalCouponAmount), // 已经是分为单位
"skuDetailVos": skuDetailVos,
"couponList": func() []map[string]interface{} {
var couponList []map[string]interface{}
for _, coupon := range req.CouponList {
if coupon.Status == "default" {
couponList = append(couponList, map[string]interface{}{
"couponId": coupon.UserCouponID, // 使用用户优惠券ID
"storeId": fmt.Sprintf("%d", storeID),
})
}
}
return couponList
}(),
},
},
"inValidGoodsList": nil,
"outOfStockGoodsList": nil,
"limitGoodsList": nil,
"abnormalDeliveryGoodsList": nil,
"invoiceSupport": 1,
}
response.Success(c, result)
}