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

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