322 lines
11 KiB
Go
322 lines
11 KiB
Go
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)
|
||
} |