feat: change order id

master
howell 4 years ago
parent db235ddd74
commit 0e43b14436

@ -2,28 +2,23 @@ package order
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"github.com/shopspring/decimal"
"log"
order_preview2 "recook/internal/api/mobile/order_preview"
"recook/internal/back"
"recook/internal/dbc"
"recook/internal/model/coupon"
"recook/internal/libs/snow"
"recook/internal/model/goods"
"recook/internal/model/order"
"recook/internal/model/order_preview"
"recook/internal/model/promotion"
"recook/internal/model/shopping_trolley"
"recook/internal/model/user"
"recook/internal/v2/controller/task"
"recook/internal/v2/lib/jcook"
goods3 "recook/internal/v2/model/recook/goods"
"recook/tools"
"strconv"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
)
/*创建普通订单的参数*/
@ -32,20 +27,8 @@ type submitOrderParam struct {
PreviewOrderID uint `json:"previewOrderId"`
}
var submitOrderSentinel sync.Mutex
//var submitOrderSentinel sync.Mutex
/*
10
/
使
*/
func SubmitOrder(c *gin.Context) {
var p submitOrderParam
err := tools.ParseParams(&p, c)
@ -54,12 +37,6 @@ func SubmitOrder(c *gin.Context) {
return
}
submitOrderSentinel.Lock()
defer submitOrderSentinel.Unlock()
// 验证库存 验证优惠券是否失效 验证活动 验证金额是否匹配
now := time.Now().Unix()
var previewOrderInfo order_preview.Information
if err = dbc.DB.First(&previewOrderInfo, "id = ?", p.PreviewOrderID).Error; err != nil {
back.Err(c, err.Error())
@ -83,47 +60,6 @@ func SubmitOrder(c *gin.Context) {
}
}
// 钱包的瑞币是否足够支付
var wallet user.Wallet
{
if err = dbc.DB.First(&wallet, "user_id = ?", p.UserID).Error; err != nil {
back.Err(c, err.Error())
return
}
if wallet.Coin.LessThan(previewOrderInfo.CoinTotalAmount) {
back.Fail(c, "瑞币不足,请重新购买")
return
}
}
// 优惠券是否可用
var preOrderCouponList []order_preview.CouponDetail
if err = dbc.DB.Find(&preOrderCouponList, "order_id = ?", p.PreviewOrderID).Error; err != nil && false == gorm.IsRecordNotFoundError(err) {
back.Err(c, err.Error())
return
}
personalCouponMidList := make([]*coupon.ReceiverMid, 0, 0)
for _, v := range preOrderCouponList {
var couponMid coupon.ReceiverMid
if err = dbc.DB.First(&couponMid, "id = ?", v.PersonalCouponID).Error; err != nil {
back.Err(c, err.Error())
return
}
if couponMid.Status == 1 {
back.Fail(c, "优惠券已在其他订单使用,请重新下单")
return
}
if couponMid.EndTime.Time.Unix() < now {
back.Fail(c, "优惠券已过期,请重新下单")
return
}
personalCouponMidList = append(personalCouponMidList, &couponMid)
}
var preOrderGoodsList []order_preview.GoodsDetail
if err = dbc.DB.Find(&preOrderGoodsList, "order_id = ?", p.PreviewOrderID).Error; err != nil {
back.Err(c, err.Error())
@ -149,17 +85,6 @@ func SubmitOrder(c *gin.Context) {
back.Err(c, err.Error())
return
}
if goodsInfo.ThirdPartyType == goods3.RecookGoodsInfoThirdPartyTypeJingtong {
jingtong := &task.Jingtong{}
if err := jingtong.Update(goodsInfo.ThirdPartyId); err != nil {
back.Err(c, err.Error())
return
}
if err = dbc.DB.Select("hash, publish_status,third_party_id,third_party_type").First(&goodsInfo, "id = ?", v.GoodsID).Error; err != nil {
back.Err(c, err.Error())
return
}
}
if goodsInfo.Hash != v.Hash {
back.Fail(c, "商品信息已经发生变化,请重新下单")
@ -217,31 +142,30 @@ func SubmitOrder(c *gin.Context) {
data := make(map[uint][]order_preview.GoodsDetail)
fData := make(map[uint]decimal.Decimal)
var lastId uint
virtualID := GetVirtualID()
tx := dbc.DB.Begin()
{
sql := `select max(id)+floor(1+rand()*50) from recook_order_info`
if err = tx.Raw(sql).Count(&lastId).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
for _, value := range preOrderGoodsList {
data[value.VendorID] = append(data[value.VendorID], value)
fData[value.VendorID] = fData[value.VendorID].Add(value.ExpressFee)
}
work := snow.GetOrderWorker()
orderID, err := work.NextID()
if err != nil {
back.Err(c, err.Error())
return
}
condition := len(data) == 1
orderInfo.ID = lastId
var count uint = 0
orderInfo.ID = uint(orderID)
for vendor, value := range data {
//if vendor == 1800 || vendor== 2000 {
// continue
//}
id1, err := work.NextID()
if err != nil {
back.Err(c, err.Error())
return
}
orderCopy := order.Information{
ID: lastId + count,
ID: uint(id1),
AncestorID: orderInfo.AncestorID,
ParentID: orderInfo.ParentID,
SharerID: orderInfo.SharerID,
@ -276,7 +200,7 @@ func SubmitOrder(c *gin.Context) {
}
kind := 0
if vendor == 1800 || vendor == 2000 {
channelOrderID := strconv.Itoa(int(lastId + count))
channelOrderID := strconv.Itoa(int(orderCopy.ID))
resp, err := JdOrderSubmit(tx, c.ClientIP(), data, vendor, previewOrderAddr, fData, channelOrderID)
if err != nil {
log.Println("订单生成失败:", err.Error())
@ -296,7 +220,6 @@ func SubmitOrder(c *gin.Context) {
if condition {
orderCopy.VirtualID = orderCopy.ID
}
count += 1
for _, v := range value {
orderCopy.BrandCouponTotalAmount = orderCopy.BrandCouponTotalAmount.Add(v.BrandCouponAmount)
orderCopy.UniverseCouponTotalAmount = orderCopy.UniverseCouponTotalAmount.Add(v.UniverseCouponAmount)
@ -319,39 +242,9 @@ func SubmitOrder(c *gin.Context) {
tx.Rollback()
return
}
//判断是否为秒杀商品
smp := make(map[uint]uint)
now1 := previewOrderInfo.CreatedAt.Time
for _, v := range preOrderGoodsList {
res, _ := order_preview2.IfSecKill(now1, v.SkuID)
if res.Id > 0 {
//秒杀中
num := res.RealStock.Sub(decimal.NewFromInt(int64(v.Quantity)))
if num.LessThan(decimal.Zero) {
back.Err(c, "库存不足")
tx.Rollback()
return
} else {
//库存更新
err = tx.Table(res.TableName()).Where("id=?", res.Id).Update("real_stock", num).Error
if err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
}
smp[v.SkuID] = res.SecKillActivityId
} else {
continue
}
}
for _, v := range value {
goodsDetail := (&order.GoodsDetail{}).Reflect(&v, &orderCopy)
if _, ok := smp[v.SkuID]; ok {
goodsDetail.ActivityStatus = 1
goodsDetail.ActivityId = smp[v.SkuID]
}
if err = tx.Create(goodsDetail).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
@ -371,45 +264,6 @@ func SubmitOrder(c *gin.Context) {
}
}
if orderCopy.CoinTotalAmount.GreaterThan(decimal.NewFromFloat(0.0)) {
// 标记瑞币, 即扣除了总额
if err = tx.Model(&wallet).Updates(map[string]interface{}{
"coin": wallet.Coin.Sub(orderCopy.CoinTotalAmount),
}).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
// 加入流水记录, 直接加在coinHistory中
var uCoinHis user.CoinHistory
uCoinHis.UserID = p.UserID
uCoinHis.CoinNum = orderCopy.CoinTotalAmount.Neg()
uCoinHis.CoinType = user.PurchasedTypeForCoinHistory
uCoinHis.OrderId = orderCopy.ID
uCoinHis.CreatedAt = orderCopy.CreatedAt
uCoinHis.Remark = "订单扣除"
if err := dbc.DB.Create(&uCoinHis).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
walletCoinDetail := user.WalletCoinList{
UserID: wallet.UserID,
Number: int64(orderCopy.CoinTotalAmount.IntPart()),
Title: orderCopy.Title,
Comment: "订单支付抵扣",
OrderID: orderCopy.ID,
}
if err = tx.Create(&walletCoinDetail).Error; err != nil {
back.Err(c, err.Error())
tx.Rollback()
return
}
}
}
// 如果是购物车下单 则要清除一下购物车
@ -468,14 +322,7 @@ func JdOrderSubmit(tx *gorm.DB, ip string, data map[uint][]order_preview.GoodsDe
return resp, nil
}
const initCount int64 = 20210624681
func GetVirtualID() uint {
result := dbc.Rds.Incr("order_count")
if r, err := result.Result(); err != nil {
log.Println(err.Error())
return uint(time.Now().Unix()) * 10
} else {
return uint(r + initCount)
}
id, _ := snow.GetOrderWorker().NextID()
return uint(id)
}

@ -0,0 +1,89 @@
package snow
import (
"errors"
"sync"
"time"
)
var OrderWorker *Worker
var once sync.Once
func GetOrderWorker() *Worker {
once.Do(func() {
OrderWorker = NewWorker(1, 1)
})
return OrderWorker
}
const (
workerIDBits = uint64(4)
businessIDBits = uint64(4)
sequenceBits = uint64(14)
maxWorkerID = int64(-1) ^ (int64(-1) << workerIDBits)
maxBusinessID = int64(-1) ^ (int64(-1) << businessIDBits)
maxSequence = int64(-1) ^ (int64(-1) << sequenceBits)
timeLeft = uint8(22) // 6 + 4 + 12
workLeft = uint8(18) // 4 + 12
businessLeft = uint(14) // 12
initialisierung = int64(1638935759)
)
type Worker struct {
mu sync.Mutex
LastStamp int64
WorkerID int64
BusinessID int64
Sequence int64 // 当前毫秒已经生成的ID序列号(从0 开始累加) 1毫秒内最多生成4096个ID
}
func NewWorker(workerID, businessID int64) *Worker {
return &Worker{
WorkerID: workerID,
LastStamp: 0,
Sequence: 0,
BusinessID: businessID,
}
}
func (w *Worker) getMilliSeconds() int64 {
return time.Now().Unix()
}
func (w *Worker) NextID() (uint64, error) {
w.mu.Lock()
defer w.mu.Unlock()
return w.nextID()
}
func (w *Worker) nextID() (uint64, error) {
timeStamp := w.getMilliSeconds()
if timeStamp < w.LastStamp {
return 0, errors.New("time is moving backwards,waiting until")
}
if w.LastStamp == timeStamp {
w.Sequence = (w.Sequence + 1) & maxSequence
if w.Sequence == 0 {
for timeStamp <= w.LastStamp {
timeStamp = w.getMilliSeconds()
}
}
} else {
w.Sequence = 0
}
w.LastStamp = timeStamp
id := ((timeStamp - initialisierung) << timeLeft) |
(w.WorkerID << workLeft) |
(w.BusinessID << businessLeft) |
w.Sequence
return uint64(id), nil
}
Loading…
Cancel
Save