You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
9.9 KiB
323 lines
9.9 KiB
package order_preview
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/shopspring/decimal"
|
|
"math"
|
|
"recook/internal/back"
|
|
"recook/internal/dbc"
|
|
"recook/internal/model/freight"
|
|
"recook/internal/model/goods"
|
|
"recook/internal/model/order_preview"
|
|
"recook/internal/model/user"
|
|
"recook/tools"
|
|
)
|
|
|
|
type updateOrderAddrParam struct {
|
|
UserID uint `json:"userId" validate:"numeric"`
|
|
OrderID uint `json:"orderId" validate:"numeric"`
|
|
AddressID uint `json:"addressId" validate:"numeric"`
|
|
}
|
|
|
|
func UpdateOrderAddr(c *gin.Context) {
|
|
var p updateOrderAddrParam
|
|
err := tools.ParseParams(&p, c)
|
|
if err != nil {
|
|
back.Fail(c, "参数错误:"+err.Error())
|
|
return
|
|
}
|
|
|
|
var previewOrderInfo order_preview.Information
|
|
err = dbc.DB.First(&previewOrderInfo, p.OrderID).Error
|
|
if err != nil {
|
|
back.Err(c, "订单不存在:"+err.Error())
|
|
return
|
|
}
|
|
|
|
var addr user.Addr
|
|
err = dbc.DB.First(&addr, "id = ?", p.AddressID).Error
|
|
if err != nil {
|
|
back.Err(c, "地址不存在:"+err.Error())
|
|
return
|
|
}
|
|
|
|
var previewOrderAddr order_preview.Addr
|
|
err = dbc.DB.First(&previewOrderAddr, "order_id = ?", p.OrderID).Error
|
|
if err != nil {
|
|
back.Err(c, "pre地址不存在"+err.Error())
|
|
return
|
|
}
|
|
|
|
if previewOrderInfo.ShippingMethod == 1 { // 自提货订单不需要计算运费
|
|
|
|
} else { // 不是自提时
|
|
isDeliveryArea := 1
|
|
// 先检测是否有不发货地区
|
|
var goodsList []order_preview.GoodsDetail
|
|
dbc.DB.Find(&goodsList, "order_id = ?", p.OrderID)
|
|
for _, v := range goodsList {
|
|
if v.VendorID == 1800 || v.VendorID == 2000 || v.VendorID == 3000 {
|
|
continue
|
|
}
|
|
if checkIsDelivery(addr.Province, addr.City, v.FreightID) == false {
|
|
isDeliveryArea = 0
|
|
break
|
|
}
|
|
}
|
|
|
|
if isDeliveryArea == 0 { // 表示不发货
|
|
err = dbc.DB.Model(&previewOrderAddr).Updates(map[string]interface{}{
|
|
"address_id": addr.ID,
|
|
"province": addr.Province,
|
|
"city": addr.City,
|
|
"district": addr.District,
|
|
"address": addr.Address,
|
|
"receiver_name": addr.Name,
|
|
"mobile": addr.Mobile,
|
|
"is_delivery_area": isDeliveryArea,
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, "更新失败:"+err.Error())
|
|
return
|
|
}
|
|
} else {
|
|
err = dbc.DB.Model(&previewOrderAddr).Updates(map[string]interface{}{
|
|
"address_id": addr.ID,
|
|
"province": addr.Province,
|
|
"city": addr.City,
|
|
"district": addr.District,
|
|
"address": addr.Address,
|
|
"receiver_name": addr.Name,
|
|
"mobile": addr.Mobile,
|
|
"is_delivery_area": isDeliveryArea,
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, "更新失败:"+err.Error())
|
|
return
|
|
}
|
|
|
|
tx := dbc.DB.Begin()
|
|
{
|
|
expressTotalFee := decimal.NewFromFloat(0.0)
|
|
jg := make(map[*goods.Sku]uint)
|
|
ojg := make(map[*goods.Sku]uint)
|
|
sjg := make(map[*goods.Sku]uint)
|
|
for _, v := range goodsList {
|
|
if v.VendorID == 1800 || v.VendorID == 2000 || v.VendorID == 3000 {
|
|
var sku goods.Sku
|
|
{
|
|
if err = dbc.DB.First(&sku, "id = ?", v.SkuID).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
switch v.VendorID {
|
|
case 1800:
|
|
jg[&sku] = v.Quantity
|
|
case 2000:
|
|
ojg[&sku] = v.Quantity
|
|
case 3000:
|
|
sjg[&sku] = v.Quantity
|
|
}
|
|
continue
|
|
}
|
|
_, ef, _ := computeExpressFeeWithPreviewGoods(v.Quantity, &v, addr.Province, addr.City)
|
|
err = tx.Model(&v).Updates(map[string]interface{}{
|
|
"express_fee": ef,
|
|
"actual_amount": v.ActualAmount.Sub(v.ExpressFee).Add(ef).Round(2),
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
expressTotalFee = expressTotalFee.Add(ef)
|
|
}
|
|
if len(jg) > 0 {
|
|
unitMap, err := JdExpressFee(jg, addr.GetAddress())
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
for _, v := range goodsList {
|
|
if value, ok := unitMap[v.SkuID]; ok {
|
|
v.ExpressFee = value
|
|
expressTotalFee = expressTotalFee.Add(value)
|
|
if err = tx.Model(&v).Updates(map[string]interface{}{
|
|
"express_fee": value,
|
|
"actual_amount": v.ActualAmount.Sub(v.ExpressFee).Add(value).Round(2),
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
if len(ojg) > 0 {
|
|
unitMap, err := JdExpressFee(ojg, addr.GetAddress())
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
for _, v := range goodsList {
|
|
if value, ok := unitMap[v.SkuID]; ok {
|
|
v.ExpressFee = value
|
|
expressTotalFee = expressTotalFee.Add(value)
|
|
if err = tx.Model(&v).Updates(map[string]interface{}{
|
|
"express_fee": value,
|
|
"actual_amount": v.ActualAmount.Sub(v.ExpressFee).Add(value).Round(2),
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
if len(sjg) > 0 {
|
|
unitMap, err := ShaMaExpressFee(sjg, addr.GetAddress())
|
|
if err != nil {
|
|
back.Fail(c, err.Error())
|
|
return
|
|
}
|
|
for _, v := range goodsList {
|
|
if value, ok := unitMap[v.SkuID]; ok {
|
|
v.ExpressFee = value
|
|
expressTotalFee = expressTotalFee.Add(value)
|
|
if err = tx.Model(&v).Updates(map[string]interface{}{
|
|
"express_fee": value,
|
|
"actual_amount": v.ActualAmount.Sub(v.ExpressFee).Add(value).Round(2),
|
|
}).Error; err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
err = tx.Model(&previewOrderInfo).Updates(map[string]interface{}{
|
|
"express_total_fee": expressTotalFee,
|
|
"actual_total_amount": previewOrderInfo.ActualTotalAmount.Sub(previewOrderInfo.ExpressTotalFee).Add(expressTotalFee),
|
|
}).Error
|
|
if err != nil {
|
|
back.Err(c, err.Error())
|
|
tx.Rollback()
|
|
return
|
|
}
|
|
}
|
|
tx.Commit()
|
|
}
|
|
}
|
|
|
|
back.Suc(c, "更改成功", queryPreviewOrderGroup(previewOrderInfo.ID))
|
|
}
|
|
|
|
func computeExpressFeeWithPreviewGoods(quantity uint, goodsInfo *order_preview.GoodsDetail, province, city string) (bool, decimal.Decimal, error) {
|
|
if len(province) == 0 {
|
|
return true, decimal.NewFromFloat(0.0), nil
|
|
}
|
|
var freightTemplateInfo freight.Information
|
|
// 只有用户有默认地址才去计算运费价格
|
|
err := dbc.DB.First(&freightTemplateInfo, "id = ?", goodsInfo.FreightID).Error
|
|
if err != nil {
|
|
return false, decimal.Zero, err
|
|
}
|
|
// 检测是否属于不发货地区
|
|
var nonDeliveryProvince freight.NoProvince
|
|
err = dbc.DB.First(&nonDeliveryProvince, "freight_id = ? AND province_name = ?", goodsInfo.FreightID, province).Error
|
|
if err != nil && gorm.IsRecordNotFoundError(err) == false {
|
|
return false, decimal.Zero, err
|
|
}
|
|
if nonDeliveryProvince.ID > 0 {
|
|
return false, decimal.NewFromFloat(0.0), nil
|
|
}
|
|
// 不发货的市
|
|
var noCitys freight.NoCitys
|
|
err = dbc.DB.First(&noCitys, "freight_id = ? AND province_name = ? and city_name = ?", goodsInfo.FreightID, province, city).Error
|
|
if err != nil && gorm.IsRecordNotFoundError(err) == false {
|
|
return false, decimal.Zero, err
|
|
}
|
|
if noCitys.ID > 0 {
|
|
return false, decimal.NewFromFloat(0.0), nil
|
|
}
|
|
|
|
// 进入该分支代表该地址可以发货 需要查询运费信息
|
|
// 先判断是不是所有地方包邮
|
|
var freightInfo freight.Information
|
|
err = dbc.DB.First(&freightInfo, "id = ?", goodsInfo.FreightID).Error
|
|
if err != nil {
|
|
return false, decimal.Zero, err
|
|
}
|
|
if freightInfo.AllFree == 1 {
|
|
return true, decimal.NewFromFloat(0.0), nil
|
|
}
|
|
|
|
// 先找到该收货省市的信息 然后找到对应的价格表
|
|
|
|
var priceDetailID uint
|
|
// 市价格表
|
|
var deliveryCity freight.Citys
|
|
err = dbc.DB.First(&deliveryCity, "freight_id = ? AND province_name = ? and city_name = ?", goodsInfo.FreightID, province, city).Error
|
|
if deliveryCity.ID == 0 {
|
|
// 省价格表
|
|
var deliveryProvince freight.Province
|
|
err = dbc.DB.First(&deliveryProvince, "freight_id = ? AND province_name = ?", goodsInfo.FreightID, province).Error
|
|
if err != nil {
|
|
return true, decimal.Zero, nil
|
|
}
|
|
priceDetailID = deliveryProvince.PriceDetailID
|
|
} else {
|
|
priceDetailID = deliveryCity.PriceDetailID
|
|
}
|
|
var freightPrice freight.Price
|
|
dbc.DB.First(&freightPrice, "id = ?", priceDetailID)
|
|
|
|
expressFee := decimal.NewFromFloat(0.0)
|
|
if freightPrice.Type == 0 { // 按照件数计算
|
|
if quantity <= freightPrice.FirstNumber {
|
|
expressFee = freightPrice.FirstNumberFee
|
|
} else {
|
|
baseNumber := math.Ceil(float64((quantity - freightPrice.FirstNumber) / freightPrice.AdditionalNumber)) // 向上取整 意思是不满一斤算一斤
|
|
expressFee = freightPrice.FirstNumberFee.Add(decimal.NewFromFloat(baseNumber).Mul(freightPrice.AdditionalNumberFee))
|
|
}
|
|
} else if freightPrice.Type == 3 {
|
|
return true, freightPrice.Amount, nil
|
|
} else { // 按照重量计算
|
|
if goodsInfo.Weight.LessThanOrEqual(freightPrice.FirstWeight) { // 小于首重
|
|
expressFee = freightPrice.FirstWeightFee
|
|
} else {
|
|
baseWeight := (goodsInfo.Weight.Sub(freightPrice.FirstWeight)).Div(freightPrice.AdditionalWeight).Ceil() // 向上取整 意思是不满一斤算一斤
|
|
expressFee = freightPrice.FirstWeightFee.Add(baseWeight.Mul(freightPrice.AdditionalWeightFee))
|
|
}
|
|
}
|
|
//判断是否有满几件的免费
|
|
if quantity >= freightPrice.FreeNumberThreshold {
|
|
expressFee = decimal.NewFromFloat(0.0)
|
|
}
|
|
|
|
return true, expressFee, nil
|
|
}
|
|
|
|
func checkIsDelivery(province, city string, freightId uint) bool {
|
|
// 检索省份
|
|
var nonDeliveryProvince freight.NoProvince
|
|
err := dbc.DB.Select("id").First(&nonDeliveryProvince, "freight_id = ? AND province_name = ?", freightId, province).Error
|
|
if gorm.IsRecordNotFoundError(err) {
|
|
// 检索市区
|
|
var nonDeliveryCitys freight.NoCitys
|
|
err := dbc.DB.Select("id").First(&nonDeliveryCitys, "freight_id = ? AND province_name = ? and city_name = ?", freightId, province, city).Error
|
|
if gorm.IsRecordNotFoundError(err) {
|
|
return true
|
|
}
|
|
return false
|
|
} else {
|
|
return false
|
|
}
|
|
}
|