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) }