1783 lines
63 KiB
Go
1783 lines
63 KiB
Go
package localjx
|
||
|
||
import (
|
||
"crypto/md5"
|
||
"fmt"
|
||
"math"
|
||
"regexp"
|
||
"sort"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/jdeclpapi"
|
||
"git.rosy.net.cn/baseapi/platformapi/wxpayapi"
|
||
|
||
"git.rosy.net.cn/jx-callback/globals/api"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/netprinter"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/baseapi/utils/errlist"
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||
"git.rosy.net.cn/jx-callback/business/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
"git.rosy.net.cn/jx-callback/business/partner"
|
||
"git.rosy.net.cn/jx-callback/business/partner/delivery"
|
||
)
|
||
|
||
const (
|
||
OrderCreateTypePre = 0 // 预创建
|
||
OrderCreateTypeNormal = 1 // 正常创建
|
||
|
||
PayWaitingTime = 10 * time.Minute // 等待支付的最长时间
|
||
DingShiDaMinTime = 1 * time.Hour
|
||
|
||
specialStoreID = 100274
|
||
specialFreightPrice = 1500
|
||
|
||
wxAppID = "wx4b5930c13f8b1170"
|
||
|
||
autoCancelOrderReason = "支付超时,系统自动取消!"
|
||
cancelMatterOrderReason = "失败重发!"
|
||
|
||
splitMatterOrderMinWeight = 4500 //物料订单分包最少要4.5kg
|
||
jxwxfMatterEclpID = "EMG4418113943423" //京西五香粉物料编码
|
||
)
|
||
|
||
type JxSkuInfo struct {
|
||
SkuID int `json:"skuID"`
|
||
Count int `json:"count"`
|
||
|
||
Price int64 `json:"price,omitempty"` // 原价
|
||
SalePrice int64 `json:"salePrice,omitempty"` // 售卖价
|
||
|
||
Name string `json:"name"`
|
||
Weight int `json:"weight"`
|
||
GroupSign bool `json:"groupSign"`
|
||
}
|
||
|
||
type JxSkuInfo2 struct {
|
||
SkuID int `json:"skuID"`
|
||
Count int `json:"count"`
|
||
|
||
Price int64 `json:"price,omitempty"` // 原价
|
||
SalePrice int64 `json:"salePrice,omitempty"` // 售卖价
|
||
|
||
Name string `json:"name"`
|
||
Weight int `json:"weight"`
|
||
GroupSign bool `json:"groupSign"`
|
||
}
|
||
|
||
type JxSkuInfoList []*JxSkuInfo
|
||
|
||
func (l JxSkuInfoList) Len() int {
|
||
return len(l)
|
||
}
|
||
|
||
func (l JxSkuInfoList) Less(i, j int) bool {
|
||
if l[i].SkuID == l[j].SkuID {
|
||
return l[i].SalePrice < l[j].SalePrice
|
||
}
|
||
return l[i].SkuID < l[j].SkuID
|
||
}
|
||
|
||
func (l JxSkuInfoList) Swap(i, j int) {
|
||
l[i], l[j] = l[j], l[i]
|
||
}
|
||
|
||
type JxOrderInfo struct {
|
||
BuyerComment string `json:"buyerComment"`
|
||
StoreID int `json:"storeID"`
|
||
Skus []*JxSkuInfo `json:"skus"`
|
||
|
||
ExpectedDeliveredTimestamp int64 `json:"expectedDeliveredTimestamp"` // 预期送达时间
|
||
|
||
TotalPrice int64 `json:"totalPrice"` // 单位为分 订单总价
|
||
FreightPrice int64 `json:"freightPrice"` // 单位为分 订单配送费
|
||
OrderPrice int64 `json:"orderPrice"` // 单位为分 订单商品价格
|
||
ActualPayPrice int64 `json:"actualPayPrice"` // 单位为分 顾客实际支付
|
||
|
||
OrderID int64 `json:"orderID"`
|
||
StoreName string `json:"storeName"`
|
||
Weight int `json:"weight"`
|
||
FromStoreID int `json:"fromStoreID"`
|
||
}
|
||
|
||
type DeliveryTimeItem struct {
|
||
ViewTime string `json:"viewTime"`
|
||
UnixTime int64 `json:"unixTime"`
|
||
ViewShippingFee string `json:"viewShippingFee"`
|
||
}
|
||
|
||
type DeliveryDayTimeInfo struct {
|
||
Date string `json:"date"`
|
||
TimeList []*DeliveryTimeItem `json:"timeList"`
|
||
}
|
||
|
||
type MatterOrderStatus struct {
|
||
Time time.Time `json:"time"`
|
||
Status string `json:"status"`
|
||
Name string `json:"name"`
|
||
Sign int `sign`
|
||
}
|
||
|
||
var (
|
||
orderNoBeginTimestamp int64
|
||
|
||
weekdayMap = map[int]string{
|
||
1: "一",
|
||
2: "二",
|
||
3: "三",
|
||
4: "四",
|
||
5: "五",
|
||
6: "六",
|
||
0: "日",
|
||
}
|
||
dayList = []string{"今天", "明天", "后天"}
|
||
|
||
bagMap = map[int]int{
|
||
6039382: 100,
|
||
6039383: 200,
|
||
6039384: 200,
|
||
6039387: 200,
|
||
6039390: 200,
|
||
}
|
||
|
||
regexpCnameAndCmobile = regexp.MustCompile(`配送员,(.*),手机号,(.*)`)
|
||
regexpCnameAndCmobile2 = regexp.MustCompile(`(快递员:(.*),联系电话:(.*))`)
|
||
|
||
bagSkuMap = map[int]int{ //京西物料袋子skuid
|
||
6039382: 6039382,
|
||
6039383: 6039383,
|
||
6039384: 6039384,
|
||
6039387: 6039387,
|
||
6039390: 6039390,
|
||
}
|
||
)
|
||
|
||
func init() {
|
||
orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix()
|
||
}
|
||
|
||
func GetMyOrders(ctx *jxcontext.Context, fromDateStr, toDateStr string, params map[string]interface{}, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||
db := dao.GetDB()
|
||
params["vendorIDs"] = string(utils.MustMarshal([]int{model.VendorIDJX}))
|
||
tmpOrderList, totalCount, err := dao.GetOrders(db, nil, false, false, fromDateStr, toDateStr, false, nil, false, ctx.GetUserID(), params, offset, pageSize)
|
||
if err == nil {
|
||
pagedInfo = &model.PagedInfo{
|
||
TotalCount: totalCount,
|
||
}
|
||
if totalCount > 0 {
|
||
var ids []int64
|
||
for _, v := range tmpOrderList {
|
||
ids = append(ids, v.ID)
|
||
}
|
||
orderSkuList, _, err2 := dao.GetOrders(db, ids, true, false, "", "", false, nil, false, "", nil, 0, model.UnlimitedPageSize)
|
||
if err = err2; err == nil {
|
||
orderMap := make(map[string]*model.GoodsOrderExt)
|
||
var orderList []*model.GoodsOrderExt
|
||
for _, v := range orderSkuList {
|
||
universalOrderID := jxutils.ComposeUniversalOrderID(v.VendorOrderID, v.VendorID)
|
||
if orderMap[universalOrderID] == nil {
|
||
orderMap[universalOrderID] = v
|
||
orderList = append(orderList, v)
|
||
}
|
||
orderMap[universalOrderID].SkuList = append(orderMap[universalOrderID].SkuList, &v.ShortSkuInfo)
|
||
}
|
||
pagedInfo.Data = orderList
|
||
} else {
|
||
pagedInfo = nil
|
||
}
|
||
}
|
||
}
|
||
return pagedInfo, err
|
||
}
|
||
|
||
func GetMyAfsOrders(ctx *jxcontext.Context, fromDateStr, toDateStr string, params map[string]interface{}, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
||
|
||
return pagedInfo, err
|
||
}
|
||
|
||
func GetMyOrderCountInfo(ctx *jxcontext.Context, fromDate, toDate time.Time, statuss []int) (countInfo []*model.GoodsOrderCountInfo, err error) {
|
||
countInfo, err = dao.GetMyOrderCountInfo(dao.GetDB(), ctx.GetUserID(), fromDate, toDate, statuss)
|
||
return countInfo, err
|
||
}
|
||
|
||
//fromStoreID 为0 表示非物料订单(京西商城订单等)
|
||
//fromStoreID 为 门店ID ,表示是物料订单,fromStoreID表示是哪个门店申请的物料
|
||
//fromStoreID 为-1 表示也是物料订单,但是不是门店申请,是个人申请的
|
||
//fromStoreID 在后面 generateOrder中有用
|
||
func CreateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, createType int, fromStoreID int, IsDeliverySelf bool) (outJxOrder *JxOrderInfo, err error) {
|
||
outJxOrder, deliveryAddress, err := generateOrder(ctx, jxOrder, addressID, fromStoreID, "", IsDeliverySelf)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if fromStoreID != 0 {
|
||
checkMatterDeliveryAddress(deliveryAddress)
|
||
}
|
||
if createType != OrderCreateTypePre {
|
||
if outJxOrder.TotalPrice != jxOrder.TotalPrice {
|
||
return nil, fmt.Errorf("商品或配送信息发生改变,请重新下单")
|
||
}
|
||
outJxOrder.OrderID = GenOrderNo(ctx)
|
||
order, err2 := jxOrder2GoodsOrder(ctx, outJxOrder, deliveryAddress, "", IsDeliverySelf)
|
||
if err = err2; err == nil {
|
||
order.AddressID = addressID
|
||
order.Status = model.OrderStatusWait4Pay
|
||
callNewOrder(order)
|
||
}
|
||
}
|
||
return outJxOrder, err
|
||
}
|
||
|
||
// 买家取消(或申请取消)订单
|
||
func BuyerCancelOrder(ctx *jxcontext.Context, orderID int64, reason string) (canceled bool, err error) {
|
||
order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX)
|
||
if err == nil {
|
||
if order.Status < model.OrderStatusNew {
|
||
order.Status = model.OrderStatusCanceled
|
||
order.VendorStatus = utils.Int2Str(model.OrderStatusCanceled)
|
||
if err = partner.CurOrderManager.UpdateOrderFields(order, []string{model.FieldStatus, "VendorStatus"}); err == nil {
|
||
canceled = true
|
||
}
|
||
} else {
|
||
err = fmt.Errorf("暂不支持自行取消订单,请联系商家取消")
|
||
// err = changeOrderStatus(utils.Int64ToStr(orderID), model.OrderStatusApplyCancel, fmt.Sprintf("用户%s主动取消", ctx.GetUserName()))
|
||
}
|
||
}
|
||
return canceled, err
|
||
}
|
||
|
||
func Pay4Order(ctx *jxcontext.Context, orderID int64, payType int, vendorPayType string) (orderPay *model.OrderPay, err error) {
|
||
order, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDJX)
|
||
if err == nil {
|
||
switch payType {
|
||
case model.PayTypeWX:
|
||
if orderPay, err = pay4OrderByWX(ctx, order, vendorPayType); err == nil {
|
||
dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
|
||
err = dao.CreateEntity(dao.GetDB(), orderPay)
|
||
}
|
||
case model.PayTypeTL:
|
||
if orderPay, err = pay4OrderByTL(ctx, order, vendorPayType); err == nil && orderPay != nil {
|
||
dao.WrapAddIDCULDEntity(orderPay, ctx.GetUserName())
|
||
err = dao.CreateEntity(dao.GetDB(), orderPay)
|
||
}
|
||
default:
|
||
err = fmt.Errorf("支付方式:%d当前不支持", payType)
|
||
}
|
||
}
|
||
return orderPay, err
|
||
}
|
||
|
||
func time2ShortTimeStr(t time.Time) string {
|
||
return t.Format("15:04")
|
||
}
|
||
|
||
func GetAvailableDeliverTime(ctx *jxcontext.Context, storeID int) (deliverTimerList []*DeliveryDayTimeInfo, err error) {
|
||
db := dao.GetDB()
|
||
storeDetail, err := dao.GetStoreDetail(db, storeID, model.VendorIDJX)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if storeDetail.Status != model.StoreStatusOpened {
|
||
return nil, fmt.Errorf("门店:%s不是营业状态,状态是:%s", storeDetail.Name, model.StoreStatusName[storeDetail.Status])
|
||
}
|
||
// now := utils.Str2Time(timeStr)
|
||
now := time.Now()
|
||
// beginDate := utils.Time2Date(utils.Str2Time(timeStr))
|
||
beginDate := utils.Time2Date(now)
|
||
minDingShiDaTime := now.Add(DingShiDaMinTime)
|
||
viewShippingFee := "约6.6元配送费"
|
||
if storeID == specialStoreID {
|
||
viewShippingFee = "免费配送"
|
||
}
|
||
var isOrder = false
|
||
if storeDetail.IsOrder == model.YES {
|
||
isOrder = true
|
||
beginDate = beginDate.AddDate(0, 0, 1)
|
||
}
|
||
for i, dayStr := range dayList {
|
||
if isOrder {
|
||
isOrder = false
|
||
continue
|
||
}
|
||
openTime1 := jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime1, beginDate)
|
||
closeTime1 := jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime1, beginDate)
|
||
openTime2 := jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime2, beginDate)
|
||
closeTime2 := jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime2, beginDate)
|
||
timeInfo := &DeliveryDayTimeInfo{
|
||
Date: fmt.Sprintf("%s(周%s)", dayStr, weekdayMap[int(beginDate.Weekday())]),
|
||
}
|
||
if i == 0 {
|
||
if isTimeInOpTime(storeDetail.OpenTime1, storeDetail.CloseTime1, storeDetail.OpenTime2, storeDetail.CloseTime2, now) {
|
||
timeInfo.TimeList = append(timeInfo.TimeList, &DeliveryTimeItem{
|
||
ViewTime: "立即送出",
|
||
UnixTime: 0,
|
||
ViewShippingFee: viewShippingFee,
|
||
})
|
||
}
|
||
}
|
||
for j := 0; j < 24*3; j++ {
|
||
deliveryTime := beginDate.Add(time.Duration(j) * 20 * time.Minute)
|
||
if deliveryTime.Sub(minDingShiDaTime) >= 0 {
|
||
if (deliveryTime.Sub(openTime1) >= 0 && deliveryTime.Sub(closeTime1) <= 0) ||
|
||
(storeDetail.OpenTime2 > 0 && deliveryTime.Sub(openTime2) >= 0 && deliveryTime.Sub(closeTime2) <= 0) {
|
||
timeInfo.TimeList = append(timeInfo.TimeList, &DeliveryTimeItem{
|
||
ViewTime: time2ShortTimeStr(deliveryTime),
|
||
UnixTime: deliveryTime.Unix(),
|
||
ViewShippingFee: viewShippingFee,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
if len(timeInfo.TimeList) > 0 {
|
||
deliverTimerList = append(deliverTimerList, timeInfo)
|
||
}
|
||
beginDate = beginDate.Add(24 * time.Hour)
|
||
}
|
||
if len(deliverTimerList) > 0 {
|
||
if deliverTimerList[0].TimeList[0].UnixTime != 0 {
|
||
deliverTimerList[0].TimeList[0].ViewTime = "营业即送"
|
||
}
|
||
}
|
||
return deliverTimerList, err
|
||
}
|
||
|
||
func OnPayFinished(orderPay *model.OrderPay) (err error) {
|
||
order, err := partner.CurOrderManager.LoadOrder(orderPay.VendorOrderID, orderPay.VendorID)
|
||
if err == nil {
|
||
db := dao.GetDB()
|
||
dao.UpdateEntity(db, orderPay)
|
||
if count, err2 := dao.GetJxOrderCount(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, order.OrderCreatedAt); err2 == nil {
|
||
order.OrderSeq = count + 1
|
||
partner.CurOrderManager.UpdateOrderFields(order, []string{"OrderSeq"})
|
||
}
|
||
order.Status = model.OrderStatusNew
|
||
order.VendorStatus = utils.Int2Str(model.OrderStatusNew)
|
||
order.StatusTime = *orderPay.PayFinishedAt
|
||
err = callNewOrder(order)
|
||
//如果是物料的订单,直接到拣货完成,配送中的状态
|
||
if order.FromStoreID != 0 {
|
||
netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order)
|
||
PickupGoods(order, false, "jxadmin")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func GenOrderNo(ctx *jxcontext.Context) (orderNo int64) {
|
||
const prefix = 88
|
||
const randPartNum = 1000
|
||
orderNo = time.Now().Unix() - orderNoBeginTimestamp
|
||
// fmt.Println(orderNo)
|
||
orderNo = orderNo * randPartNum
|
||
md5Bytes := md5.Sum([]byte(utils.GetUUID()))
|
||
randPart := 0
|
||
for k, v := range md5Bytes {
|
||
randPart += int(v) << ((k % 3) * 8)
|
||
}
|
||
orderNo += int64(randPart % randPartNum)
|
||
orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix
|
||
return orderNo
|
||
}
|
||
|
||
func GenAfsOrderNo(ctx *jxcontext.Context) (orderNo int64) {
|
||
const prefix = 80
|
||
const randPartNum = 100
|
||
orderNo = time.Now().Unix() - orderNoBeginTimestamp
|
||
orderNo = orderNo * randPartNum
|
||
md5Bytes := md5.Sum([]byte(utils.GetUUID()))
|
||
randPart := 0
|
||
for k, v := range md5Bytes {
|
||
randPart += int(v) << ((k % 3) * 8)
|
||
}
|
||
orderNo += int64(randPart % randPartNum)
|
||
orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix
|
||
return orderNo
|
||
}
|
||
|
||
func GenPayOrderID(order *model.GoodsOrder) (payOrderID int64) {
|
||
return utils.Str2Int64(order.VendorOrderID)
|
||
}
|
||
|
||
func GenRefundID(order *model.GoodsOrder) (refundID int64) {
|
||
const suffix = 100000
|
||
refundID = utils.Str2Int64(order.VendorOrderID) * suffix
|
||
refundID += int64(time.Now().Sub(order.OrderFinishedAt) / time.Minute)
|
||
return refundID
|
||
}
|
||
|
||
func formalizeSkus(skus []*JxSkuInfo) (outSkus []*JxSkuInfo) {
|
||
skuMap := make(map[int]int)
|
||
for _, v := range skus {
|
||
skuMap[v.SkuID] += v.Count
|
||
}
|
||
for skuID, skuCount := range skuMap {
|
||
outSkus = append(outSkus, &JxSkuInfo{
|
||
SkuID: skuID,
|
||
Count: skuCount,
|
||
})
|
||
}
|
||
return outSkus
|
||
}
|
||
|
||
func isTimeInOpTime(openTime1, closeTime1, openTime2, closeTime2 int16, time2Check time.Time) bool {
|
||
timeStrList := []string{
|
||
jxutils.OperationTime2StrWithSecond(openTime1),
|
||
jxutils.OperationTime2StrWithSecond(closeTime1),
|
||
}
|
||
if openTime1 > 0 {
|
||
timeStrList = append(timeStrList,
|
||
jxutils.OperationTime2StrWithSecond(openTime2),
|
||
jxutils.OperationTime2StrWithSecond(closeTime2),
|
||
)
|
||
}
|
||
checkTimeStr := utils.Time2TimeStr(time2Check)
|
||
for i := 0; i < len(timeStrList); i += 2 {
|
||
if checkTimeStr >= timeStrList[i] && checkTimeStr <= timeStrList[i+1] {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func generateOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, addressID int64, fromStoreID int, userID string, IsDeliverySelf bool) (outJxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, err error) {
|
||
db := dao.GetDB()
|
||
if jxOrder.StoreID == 0 {
|
||
return nil, nil, fmt.Errorf("没有指定门店信息")
|
||
}
|
||
// 配送范围检查
|
||
storeDetail, err := dao.GetStoreDetail(db, jxOrder.StoreID, model.VendorIDJX)
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
var addressList []*dao.UserDeliveryAddressEx
|
||
if userID == "" {
|
||
addressList, _, err = dao.QueryUserDeliveryAddress(db, addressID, nil, 0, 0)
|
||
} else {
|
||
addressList, _, err = dao.QueryUserDeliveryAddress(db, addressID, []string{userID}, 0, 0)
|
||
}
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
if len(addressList) == 0 {
|
||
return nil, nil, fmt.Errorf("地址ID不正确")
|
||
}
|
||
deliveryAddress = addressList[0]
|
||
if distance := jxutils.Point2StoreDistance(deliveryAddress.Lng, deliveryAddress.Lat, storeDetail.Lng, storeDetail.Lat, storeDetail.DeliveryRangeType, storeDetail.DeliveryRange); distance == 0 {
|
||
return nil, nil, fmt.Errorf("当前送货地址不在门店%s的配送范围", storeDetail.Name)
|
||
}
|
||
|
||
// 营业状态及时间检查
|
||
if storeDetail.Status != model.StoreStatusOpened { // model.StoreStatusDisabled {
|
||
return nil, nil, fmt.Errorf("门店:%s状态是:%s", storeDetail.Name, model.StoreStatusName[storeDetail.Status])
|
||
}
|
||
checkTime := time.Now()
|
||
if jxOrder.ExpectedDeliveredTimestamp == 0 {
|
||
if storeDetail.Status != model.StoreStatusOpened {
|
||
return nil, nil, fmt.Errorf("门店:%s不是营业状态,状态是:%s", storeDetail.Name, model.StoreStatusName[storeDetail.Status])
|
||
}
|
||
} else {
|
||
checkTime = utils.Timestamp2Time(jxOrder.ExpectedDeliveredTimestamp)
|
||
if checkTime.Sub(time.Now()) < DingShiDaMinTime {
|
||
return nil, nil, fmt.Errorf("预订单只能在1小时后")
|
||
}
|
||
if utils.Time2Date(time.Now()).Sub(utils.Time2Date(checkTime)) > 24*time.Hour {
|
||
return nil, nil, fmt.Errorf("预订单只能预定当天或第二天")
|
||
}
|
||
}
|
||
// if !isTimeInOpTime(storeDetail.OpenTime1, storeDetail.CloseTime1, storeDetail.OpenTime2, storeDetail.CloseTime2, checkTime) {
|
||
// return nil, nil, fmt.Errorf("门店:%s不在营业时间范围", storeDetail.Name)
|
||
// }
|
||
|
||
outJxOrder2 := *jxOrder
|
||
outJxOrder2.Skus = nil
|
||
outJxOrder2.OrderPrice = 0
|
||
outJxOrder2.Weight = 0
|
||
outJxOrder = &outJxOrder2
|
||
outJxOrder.StoreName = storeDetail.Name
|
||
|
||
skus := formalizeSkus(jxOrder.Skus)
|
||
// 允许空商品列表(一般用于测试配送地址,门店信息是否合适)
|
||
if len(skus) > 0 {
|
||
var skuIDs []int
|
||
for _, v := range skus {
|
||
skuIDs = append(skuIDs, v.SkuID)
|
||
}
|
||
storeSkuInfo, err := cms.GetStoreSkus(ctx, jxOrder.StoreID, skuIDs, true, "", true, false, map[string]interface{}{
|
||
"actVendorID": model.VendorIDJX,
|
||
}, 0, model.UnlimitedPageSize)
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
storeSkuMap := make(map[int]*dao.StoreSkuExt)
|
||
for _, v1 := range storeSkuInfo.SkuNames {
|
||
for _, v2 := range v1.Skus {
|
||
if v2.StoreSkuStatus != model.SkuStatusNormal {
|
||
return nil, nil, fmt.Errorf("此商品已下架,请联系管理员!skuID:[%v]", v2.SkuID)
|
||
}
|
||
storeSkuMap[v2.SkuID] = v2
|
||
}
|
||
}
|
||
|
||
skuList, err := dao.GetSkus(db, skuIDs, nil, nil, nil, nil)
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
skuMap := make(map[int]*model.SkuAndName)
|
||
for _, v := range skuList {
|
||
if fromStoreID != 0 {
|
||
if v.EclpID == "" {
|
||
return nil, nil, fmt.Errorf("此商品物料编码为空,请联系管理员!skuID:[%v]", v.ID)
|
||
}
|
||
}
|
||
skuMap[v.ID] = v
|
||
}
|
||
var (
|
||
result *orderman.OrderCount
|
||
sum int //申请物料的店的最近销量,以下会根据销量计算具体袋子的价格
|
||
flag = false //新店袋子拆分当个参数
|
||
)
|
||
if fromStoreID != 0 && fromStoreID != -1 {
|
||
result, _ = orderman.GetMatterStoreOrderCount(nil, fromStoreID)
|
||
sum = result.Count
|
||
}
|
||
if jxOrder.Weight == 0 {
|
||
for _, v := range jxOrder.Skus {
|
||
v.Weight = storeSkuMap[v.SkuID].Weight
|
||
jxOrder.Weight += v.Weight * v.Count
|
||
}
|
||
}
|
||
for _, v := range skus {
|
||
if storeSkuBind := storeSkuMap[v.SkuID]; storeSkuBind != nil {
|
||
if fromStoreID != 0 {
|
||
result2, _ := api.JdEclpAPI.QueryStock(storeSkuBind.EclpID)
|
||
if len(result2) > 0 {
|
||
if result2[0].UsableNum < v.Count {
|
||
return nil, nil, fmt.Errorf("此商品库存不足无法购买,请联系管理员!skuID:[%v]", v.SkuID)
|
||
}
|
||
}
|
||
}
|
||
if sku := skuMap[v.SkuID]; sku != nil {
|
||
jxSku := &JxSkuInfo{
|
||
SkuID: v.SkuID,
|
||
Price: int64(storeSkuBind.JxPrice),
|
||
Count: v.Count,
|
||
SalePrice: int64(storeSkuBind.JxPrice), // todo 考虑活动价
|
||
Weight: sku.Weight,
|
||
Name: jxutils.ComposeSkuName(sku.Prefix, sku.Name, sku.Comment, sku.Unit, sku.SpecQuality, sku.SpecUnit, 0, sku.ExPrefix, sku.ExPrefixBegin, sku.ExPrefixEnd),
|
||
}
|
||
if fromStoreID != -1 {
|
||
//活动商品要拆分,一分钱的单独列一个(count为1),正常价格的列在一起(count叠加)
|
||
if storeSkuBind.ActPrice != 0 && storeSkuBind.ActPrice < storeSkuBind.JxPrice {
|
||
jxSku.SalePrice = int64(storeSkuBind.ActPrice)
|
||
jxSku.Count = 1
|
||
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
outJxOrder.Weight += jxSku.Count * jxSku.Weight
|
||
if v.Count-1 > 0 {
|
||
jxSku2 := *jxSku
|
||
jxSku2.SalePrice = jxSku.Price
|
||
jxSku2.Count = v.Count - 1
|
||
|
||
jxSku = &jxSku2
|
||
} else {
|
||
jxSku = nil
|
||
}
|
||
}
|
||
}
|
||
if jxSku != nil {
|
||
if fromStoreID == 0 || fromStoreID == -1 {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
} else { //以下else为物料订单袋子金额和数量处理
|
||
if !result.Flag { //只要flag是false就按原价申请,是true再按订单量
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
} else {
|
||
if result.Count == 0 { //这个条件被认为是新店,袋子限量
|
||
if bagMap[jxSku.SkuID] != 0 { //如果他买了袋子,第一个袋子算1分钱,其余按原价(包括所有袋子)
|
||
if !flag {
|
||
salePirce := jxSku.SalePrice
|
||
count := jxSku.Count
|
||
jxSku.SalePrice = 1
|
||
jxSku.Count = 1
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
if count > 1 {
|
||
jxSku2 := *jxSku
|
||
jxSku2.SalePrice = salePirce
|
||
jxSku2.Count = count - 1
|
||
outJxOrder.Skus = append(outJxOrder.Skus, &jxSku2)
|
||
outJxOrder.OrderPrice += int64(jxSku2.Count) * jxSku2.SalePrice
|
||
outJxOrder.Weight += jxSku2.Count * jxSku2.Weight
|
||
}
|
||
flag = true
|
||
} else {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
}
|
||
} else {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
}
|
||
} else {
|
||
//袋子总数小于等于销量就是1分钱,只要大于销量其他就按原价
|
||
//这个袋子规格是一份100个
|
||
if jxSku.SkuID == 6039382 {
|
||
if bagMap[jxSku.SkuID] != 0 {
|
||
if sum > 0 {
|
||
if bagMap[jxSku.SkuID]*jxSku.Count <= sum+100 {
|
||
jxSku.SalePrice = 1
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(1 * jxSku.Count)
|
||
} else {
|
||
jxSku2 := *jxSku
|
||
jxSku2.SalePrice = jxSku.SalePrice
|
||
jxSku2.Count = int(int64(jxSku.Count) - utils.Float64TwoInt64(math.Ceil(utils.Int2Float64(sum)/100)))
|
||
outJxOrder.Weight += jxSku2.Count * jxSku2.Weight
|
||
jxSku.SalePrice = 1
|
||
jxSku.Count = int(utils.Float64TwoInt64(math.Ceil(utils.Int2Float64(sum) / 100)))
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.Skus = append(outJxOrder.Skus, &jxSku2)
|
||
outJxOrder.OrderPrice += jxSku.SalePrice * int64(jxSku.Count)
|
||
outJxOrder.OrderPrice += jxSku2.SalePrice * int64(jxSku2.Count)
|
||
}
|
||
} else {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
}
|
||
sum = sum - bagMap[jxSku.SkuID]*jxSku.Count
|
||
}
|
||
} else if jxSku.SkuID == 6039383 || jxSku.SkuID == 6039384 || jxSku.SkuID == 6039387 || jxSku.SkuID == 6039390 { //这些袋子是一份200个
|
||
if bagMap[jxSku.SkuID] != 0 {
|
||
if sum > 0 {
|
||
if bagMap[jxSku.SkuID]*jxSku.Count <= sum+200 {
|
||
jxSku.SalePrice = 1
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(1 * jxSku.Count)
|
||
} else {
|
||
jxSku2 := *jxSku
|
||
jxSku2.SalePrice = jxSku.SalePrice
|
||
jxSku2.Count = int(int64(jxSku.Count) - utils.Float64TwoInt64(math.Ceil(utils.Int2Float64(sum)/200)))
|
||
outJxOrder.Weight += jxSku2.Count * jxSku2.Weight
|
||
jxSku.SalePrice = 1
|
||
jxSku.Count = int(utils.Float64TwoInt64(math.Ceil(utils.Int2Float64(sum) / 200)))
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.Skus = append(outJxOrder.Skus, &jxSku2)
|
||
outJxOrder.OrderPrice += jxSku.SalePrice * int64(jxSku.Count)
|
||
outJxOrder.OrderPrice += jxSku2.SalePrice * int64(jxSku2.Count)
|
||
}
|
||
} else {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
}
|
||
sum = sum - bagMap[jxSku.SkuID]*jxSku.Count
|
||
}
|
||
} else {
|
||
outJxOrder.Skus = append(outJxOrder.Skus, jxSku)
|
||
outJxOrder.OrderPrice += int64(jxSku.Count) * jxSku.SalePrice
|
||
}
|
||
}
|
||
}
|
||
}
|
||
outJxOrder.Weight += jxSku.Count * jxSku.Weight
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//物料订单的配送费另算,所以排除了免得多算一次
|
||
if fromStoreID == 0 {
|
||
sort.Sort(JxSkuInfoList(outJxOrder.Skus))
|
||
outJxOrder.FreightPrice, _, err = delivery.CalculateDeliveryFee(dao.GetDB(), jxOrder.StoreID, "",
|
||
jxutils.StandardCoordinate2Int(deliveryAddress.Lng), jxutils.StandardCoordinate2Int(deliveryAddress.Lat),
|
||
model.CoordinateTypeMars, outJxOrder.Weight, checkTime)
|
||
}
|
||
// if jxOrder.StoreID == specialStoreID {
|
||
// outJxOrder.FreightPrice = 0
|
||
// }
|
||
} else {
|
||
outJxOrder.FreightPrice = 0
|
||
}
|
||
//表示此订单为物料配送订单
|
||
if fromStoreID != 0 {
|
||
storeDetail2, err2 := dao.GetStoreDetail(db, fromStoreID, model.VendorIDJX)
|
||
if err = err2; err != nil {
|
||
return nil, nil, fmt.Errorf("fromStoreID有误,[%v]", fromStoreID)
|
||
}
|
||
//要求配送人姓名填门店名
|
||
if fromStoreID != -1 {
|
||
deliveryAddress.ConsigneeName = storeDetail2.Name
|
||
}
|
||
outJxOrder.FromStoreID = fromStoreID
|
||
//TODO 修改配送费规则,2020-04-28
|
||
//3kg 5元,每多1kg加2元
|
||
//配送费要按分包规则计算
|
||
if outJxOrder.Weight <= 3000 {
|
||
outJxOrder.FreightPrice = 500
|
||
} else if outJxOrder.Weight > 3000 && outJxOrder.Weight <= splitMatterOrderMinWeight {
|
||
outJxOrder.FreightPrice = utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(outJxOrder.Weight)-3000)/1000)*200)
|
||
} else {
|
||
_, freightPrice, _ := tryToSplitMatterOrder(jxOrder)
|
||
outJxOrder.FreightPrice = freightPrice
|
||
}
|
||
///规则为: 配送费用规则。起价5元(含2kg),之后每kg+2元,不足1kg按1kg计算。
|
||
// if outJxOrder.Weight <= 2000 {
|
||
// outJxOrder.FreightPrice = 500
|
||
// } else {
|
||
// outJxOrder.FreightPrice = utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(outJxOrder.Weight)-2000)/1000)*200)
|
||
// }
|
||
} else {
|
||
if outJxOrder.FreightPrice > specialFreightPrice {
|
||
outJxOrder.FreightPrice = specialFreightPrice
|
||
}
|
||
if outJxOrder.OrderPrice >= int64(storeDetail.DeliveryFeeDeductionSill) {
|
||
outJxOrder.FreightPrice -= int64(storeDetail.DeliveryFeeDeductionFee)
|
||
if outJxOrder.FreightPrice < 0 || IsDeliverySelf {
|
||
outJxOrder.FreightPrice = 0
|
||
}
|
||
}
|
||
}
|
||
if err == nil {
|
||
outJxOrder.TotalPrice = outJxOrder.OrderPrice + outJxOrder.FreightPrice
|
||
outJxOrder.ActualPayPrice = outJxOrder.TotalPrice
|
||
} else {
|
||
outJxOrder = nil
|
||
deliveryAddress = nil
|
||
}
|
||
return outJxOrder, deliveryAddress, err
|
||
}
|
||
|
||
//根据销量限制门店申请袋子数,现暂不使用该判断,万一以后要用就先没删
|
||
func matterSkusLimited(skus []*JxSkuInfo, storeID int) (err error) {
|
||
result, err := orderman.GetMatterStoreOrderCount(nil, storeID)
|
||
sum := 0
|
||
if result.Count != 0 {
|
||
for _, sku := range skus {
|
||
if sku.SkuID == 6039382 {
|
||
sum1 := 0
|
||
if bagMap[sku.SkuID] != 0 {
|
||
sum1 += bagMap[sku.SkuID] * sku.Count
|
||
sum += sum1
|
||
}
|
||
if utils.Int2Float64(sum1/100) >= math.Ceil(utils.Int2Float64(result.Count)/100) {
|
||
return fmt.Errorf("订单100个一份背心袋订购数量过多,请按照实际销量购买!,大概销量:[%v],购买数量:[%v]", result.Count, sum1)
|
||
}
|
||
}
|
||
if sku.SkuID == 6039383 || sku.SkuID == 6039384 || sku.SkuID == 6039387 || sku.SkuID == 6039390 {
|
||
sum2 := 0
|
||
if bagMap[sku.SkuID] != 0 {
|
||
sum2 += bagMap[sku.SkuID] * sku.Count
|
||
sum += sum2
|
||
}
|
||
if utils.Int2Float64(sum2/200) >= math.Ceil(utils.Int2Float64(result.Count)/200) {
|
||
return fmt.Errorf("订单200个一份背心袋订购数量过多,请按照实际销量购买!,大概销量:[%v],购买数量:[%v]", result.Count, sum2)
|
||
}
|
||
}
|
||
}
|
||
if sum-result.Count > 100 {
|
||
return fmt.Errorf("订单背心袋订购数量过多,请按照实际销量购买!,大概销量:[%v],购买数量:[%v]", result.Count, sum)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func jxOrder2GoodsOrder(ctx *jxcontext.Context, jxOrder *JxOrderInfo, deliveryAddress *dao.UserDeliveryAddressEx, userID string, IsDeliverySelf bool) (order *model.GoodsOrder, err error) {
|
||
order = &model.GoodsOrder{
|
||
VendorOrderID: utils.Int64ToStr(jxOrder.OrderID),
|
||
VendorID: model.VendorIDJX,
|
||
VendorStoreID: utils.Int2Str(jxOrder.StoreID),
|
||
StoreID: jxOrder.StoreID,
|
||
StoreName: jxOrder.StoreName,
|
||
// UserID: ctx.GetUserID(),
|
||
|
||
ConsigneeName: deliveryAddress.ConsigneeName,
|
||
ConsigneeMobile: deliveryAddress.ConsigneeMobile,
|
||
ConsigneeMobile2: deliveryAddress.ConsigneeMobile,
|
||
ConsigneeAddress: fmt.Sprintf("%s%s", deliveryAddress.Address, deliveryAddress.DetailAddress),
|
||
CoordinateType: model.CoordinateTypeMars,
|
||
ConsigneeLng: jxutils.StandardCoordinate2Int(deliveryAddress.Lng),
|
||
ConsigneeLat: jxutils.StandardCoordinate2Int(deliveryAddress.Lat),
|
||
|
||
Status: model.OrderStatusUnknown,
|
||
VendorStatus: "realnew",
|
||
OrderSeq: 0,
|
||
BuyerComment: jxOrder.BuyerComment,
|
||
|
||
DeliveryType: model.OrderDeliveryTypeStoreSelf,
|
||
StatusTime: time.Now(),
|
||
}
|
||
if userID == "" {
|
||
order.UserID = ctx.GetUserID()
|
||
} else {
|
||
order.UserID = userID
|
||
}
|
||
order.OrderCreatedAt = order.StatusTime
|
||
order.VendorUserID = order.UserID
|
||
if jxOrder.ExpectedDeliveredTimestamp != 0 {
|
||
order.ExpectedDeliveredTime = utils.Timestamp2Time(jxOrder.ExpectedDeliveredTimestamp)
|
||
order.BusinessType = model.BusinessTypeDingshida
|
||
} else {
|
||
order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
|
||
order.BusinessType = model.BusinessTypeImmediate
|
||
}
|
||
for _, sku := range jxOrder.Skus {
|
||
order.Skus = append(order.Skus, &model.OrderSku{
|
||
Count: sku.Count,
|
||
VendorSkuID: utils.Int2Str(sku.SkuID),
|
||
SkuID: sku.SkuID,
|
||
SkuName: sku.Name,
|
||
VendorPrice: sku.Price,
|
||
SalePrice: sku.SalePrice,
|
||
})
|
||
order.TotalShopMoney += int64(sku.Count) * sku.SalePrice
|
||
}
|
||
order.TotalShopMoney += jxOrder.FreightPrice
|
||
order.ActualPayPrice = order.TotalShopMoney
|
||
if jxOrder.FromStoreID != 0 {
|
||
order.FromStoreID = jxOrder.FromStoreID
|
||
order.WaybillVendorID = model.VendorIDJDWL
|
||
order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled
|
||
order.ConsigneeAddress = deliveryAddress.Address
|
||
order.Flag = 1
|
||
}
|
||
//如果是自提单就设置
|
||
if IsDeliverySelf {
|
||
order.DeliveryType = model.OrderDeliveryTypeSelfTake
|
||
}
|
||
return order, err
|
||
}
|
||
|
||
func AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptIt bool, userName string) (err error) {
|
||
var status int
|
||
if isAcceptIt {
|
||
status = model.OrderStatusAccepted
|
||
} else {
|
||
status = model.OrderStatusCanceled
|
||
}
|
||
return changeOrderStatus(order.VendorOrderID, status, "")
|
||
}
|
||
|
||
func AdjustOrder(ctx *jxcontext.Context, order *model.GoodsOrder, removedSkuList []*model.OrderSku, reason string) (err error) {
|
||
return err
|
||
}
|
||
|
||
func PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||
err = changeOrderStatus(order.VendorOrderID, model.OrderStatusFinishedPickup, "")
|
||
//如果是物料订单则直接进行京东物流的发单,并且状态直接变为配送中
|
||
err = orderSolutionForWuLiao(order)
|
||
return err
|
||
}
|
||
|
||
func orderSolutionForWuLiao(order *model.GoodsOrder) (err error) {
|
||
if order.FromStoreID != 0 {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
err = changeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "")
|
||
goods, err := dao.QueryOrders(db, order.VendorOrderID, -1, []int{model.VendorIDJX}, -1, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if err != nil || len(goods) == 0 {
|
||
return err
|
||
}
|
||
order.WaybillVendorID = model.VendorIDJDWL
|
||
dao.UpdateEntity(db, order, "WaybillVendorID")
|
||
orderSkus := goods[0].Skus
|
||
if order.Weight <= splitMatterOrderMinWeight { //2020-04-26, 从5kg 改为小于4.5kg
|
||
var (
|
||
goodsNos []string
|
||
prices []string
|
||
quantities []string
|
||
countSum int
|
||
)
|
||
for _, v := range orderSkus {
|
||
skus, err := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil)
|
||
if err != nil || len(skus) == 0 {
|
||
continue
|
||
}
|
||
goodsNos = append(goodsNos, skus[0].EclpID)
|
||
prices = append(prices, "0")
|
||
quantities = append(quantities, utils.Int2Str(v.Count))
|
||
countSum += v.Count
|
||
}
|
||
//总订单不足3kg && 商品数量不足3个 && 五香粉有库存,要送五香粉,补足3个
|
||
stockResult, err := api.JdEclpAPI.QueryStock(jxwxfMatterEclpID)
|
||
if err == nil && len(stockResult) > 0 && stockResult[0].UsableNum > 0 {
|
||
if order.Weight < 3000 && countSum < 3 {
|
||
//要判断他本身买没买五香粉EMG4418113943423
|
||
var index = 9999
|
||
for k, v := range goodsNos {
|
||
if v == jxwxfMatterEclpID {
|
||
index = k
|
||
}
|
||
}
|
||
//说明他买了五香粉
|
||
if index != 9999 {
|
||
quantities[index] = utils.Int2Str(utils.Str2Int(quantities[index]) + 3 - countSum)
|
||
} else {
|
||
goodsNos = append(goodsNos, jxwxfMatterEclpID)
|
||
prices = append(prices, "0")
|
||
quantities = append(quantities, utils.Int2Str(3-countSum))
|
||
}
|
||
}
|
||
}
|
||
result, err := api.JdEclpAPI.AddOrder(&jdeclpapi.AddOrderParam{
|
||
IsvUUID: order.VendorOrderID,
|
||
IsvSource: jdeclpapi.IsvSource,
|
||
ShopNo: jdeclpapi.ShopNo,
|
||
DepartmentNo: jdeclpapi.DepartmentNo,
|
||
WarehouseNo: jdeclpapi.WarehouseNo,
|
||
SalesPlatformOrderNo: order.VendorOrderID,
|
||
SalePlatformSource: jdeclpapi.SalePlatformSource,
|
||
ConsigneeName: order.ConsigneeName,
|
||
ConsigneeMobile: order.ConsigneeMobile,
|
||
ConsigneeAddress: order.ConsigneeAddress,
|
||
OrderMark: jdeclpapi.OrderMark,
|
||
GoodsNo: strings.Join(goodsNos, ","),
|
||
Price: strings.Join(prices, ","),
|
||
Quantity: strings.Join(quantities, ","),
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
order.EclpOutID = result
|
||
dao.UpdateEntity(db, order, "EclpOutID")
|
||
waybill := &model.Waybill{
|
||
VendorOrderID: order.VendorOrderID,
|
||
OrderVendorID: model.VendorIDJX,
|
||
VendorWaybillID: order.EclpOutID,
|
||
WaybillVendorID: model.VendorIDJDWL,
|
||
Status: model.WaybillStatusDelivering,
|
||
WaybillCreatedAt: time.Now(),
|
||
StatusTime: time.Now(),
|
||
WaybillFinishedAt: utils.DefaultTimeValue,
|
||
DeliveryFlag: model.OrderDeliveryFlagMaskScheduleDisabled,
|
||
}
|
||
dao.CreateEntity(db, waybill)
|
||
} else { //如果重量超过5kg则需要进行拆单分包,商品分包规则。最后一个包不超过5kg,其他包不超过3kg
|
||
outOrders, _, _ := tryToSplitMatterOrder(buildJxOrderInfo(order, orderSkus))
|
||
//以下为仿照CreateOrder,改了一些参数
|
||
for k, v := range outOrders {
|
||
outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, v, order.AddressID, order.FromStoreID, order.UserID, false)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
//分包后的子订单ID默认是后面加两位(目前的规则),要改的话要注意取消订单那的判断
|
||
outJxOrder.OrderID = utils.Str2Int64(order.VendorOrderID)*100 + int64(k+1)
|
||
checkMatterDeliveryAddress(deliveryAddress)
|
||
order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false)
|
||
if err = err2; err == nil {
|
||
order2.AddressID = order.AddressID
|
||
order2.Status = model.OrderStatusDelivering
|
||
err = partner.CurOrderManager.OnOrderNew(order2, model.Order2Status(order2))
|
||
orderSolutionForWuLiao(order2)
|
||
}
|
||
}
|
||
//刷新一下库存
|
||
for _, v := range goods[0].Skus {
|
||
cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID)
|
||
}
|
||
}
|
||
for _, v := range order.Skus {
|
||
if bagSkuMap[v.SkuID] != 0 {
|
||
stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, "")
|
||
if len(stores) > 0 {
|
||
store := stores[0]
|
||
store.IsBoughtMatter = model.YES
|
||
dao.UpdateEntity(db, store, "IsBoughtMatter")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func SelfDeliverDelivering(order *model.GoodsOrder, userName string) (err error) {
|
||
return changeOrderStatus(order.VendorOrderID, model.OrderStatusDelivering, "")
|
||
}
|
||
|
||
func SelfDeliverDelivered(order *model.GoodsOrder, userName string) (err error) {
|
||
return changeOrderStatus(order.VendorOrderID, model.OrderStatusFinished, "")
|
||
}
|
||
|
||
func CancelOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
|
||
if true { //order.Status < model.OrderStatusDelivering {
|
||
errList := errlist.New()
|
||
db := dao.GetDB()
|
||
payList, err2 := dao.GetOrderPayList(db, order.VendorOrderID, jxutils.GetPossibleVendorIDFromVendorOrderID(order.VendorOrderID))
|
||
if err = err2; err == nil {
|
||
for _, orderPay := range payList {
|
||
if orderPay.Status == model.PayStatusYes {
|
||
// refundID := utils.Int64ToStr(GenRefundID(order))
|
||
refundID := order.VendorOrderID
|
||
var orderPayRefund *model.OrderPayRefund
|
||
if orderPay.PayType == model.PayTypeWX {
|
||
orderPayRefund, err = refundOrderByWX(ctx, orderPay, refundID, orderPay.TotalFee, reason)
|
||
if err == nil {
|
||
dao.WrapAddIDCULDEntity(orderPayRefund, ctx.GetUserName())
|
||
errList.AddErr(dao.CreateEntity(dao.GetDB(), orderPayRefund))
|
||
} else {
|
||
errList.AddErr(err)
|
||
}
|
||
} else if orderPay.PayType == model.PayTypeTL {
|
||
orderPayRefund, err = RefundOrderByTL(ctx, orderPay, refundID, orderPay.TotalFee, reason)
|
||
if err != nil {
|
||
errList.AddErr(err)
|
||
}
|
||
}
|
||
if err == nil {
|
||
MarkArrears(db, order, orderPay)
|
||
err2 := CancelMatterOrder(db, order, reason)
|
||
errList.AddErr(err2)
|
||
}
|
||
} else {
|
||
orderPay.Status = model.PayStatusCanceled
|
||
_, err2 := dao.UpdateEntity(db, orderPay)
|
||
errList.AddErr(err2)
|
||
}
|
||
}
|
||
} else if dao.IsNoRowsError(err) {
|
||
err = nil
|
||
} else {
|
||
errList.AddErr(err)
|
||
}
|
||
if errList.GetErrListAsOne() == nil {
|
||
errList.AddErr(changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, reason))
|
||
}
|
||
err = errList.GetErrListAsOne()
|
||
if len(payList) == 0 {
|
||
err = CancelMatterOrder(db, order, "")
|
||
}
|
||
} else {
|
||
err = fmt.Errorf("当前订单状态:%s不允许取消", model.OrderStatusName[order.Status])
|
||
}
|
||
return err
|
||
}
|
||
|
||
func CancelMatterOrder(db *dao.DaoDB, order *model.GoodsOrder, reason string) (err error) {
|
||
if order.FromStoreID != 0 {
|
||
if order.EclpOutID != "" {
|
||
//表示是京西的物料订单的子订单(拆分后的订单)
|
||
if len(order.VendorOrderID) == 16 && order.VendorID == model.VendorIDJX {
|
||
return fmt.Errorf("不允许取消该子订单,请取消主订单进行退货退款!主订单ID :[%v]", order.VendorOrderID[:len(order.VendorOrderID)-2])
|
||
}
|
||
_, err = api.JdEclpAPI.CancelOrder(order.EclpOutID)
|
||
} else {
|
||
goodsList, err := dao.GetMatterChildOrders(db, order.VendorOrderID)
|
||
if err == nil && len(goodsList) > 0 {
|
||
for _, v := range goodsList {
|
||
_, err = api.JdEclpAPI.CancelOrder(v.EclpOutID)
|
||
changeOrderStatus(v.VendorOrderID, model.OrderStatusCanceled, reason)
|
||
}
|
||
}
|
||
}
|
||
stores, _ := dao.GetStoreList(db, []int{order.FromStoreID}, nil, nil, nil, "")
|
||
if len(stores) > 0 {
|
||
//如果这周还买过其他物料,则不刷新是否购买标志
|
||
var (
|
||
orderPays []*model.OrderPay
|
||
day int
|
||
)
|
||
sql := `
|
||
SELECT b.*
|
||
FROM goods_order a
|
||
JOIN order_pay b ON a.vendor_order_id = b.vendor_order_id
|
||
WHERE IF(a.store_id = 0, a.jx_store_id, a.store_id) = 666666
|
||
AND a.from_store_id = ?
|
||
AND a.status >= ? AND a.status <> ?
|
||
AND b.status = ?
|
||
AND b.pay_finished_at <= NOW() AND b.pay_finished_at >= ?
|
||
`
|
||
weekInt := int(time.Now().Weekday())
|
||
if weekInt == 0 {
|
||
day = 7
|
||
} else {
|
||
day = weekInt
|
||
}
|
||
lastTime := utils.Str2Time(time.Now().AddDate(0, 0, -(day-1)).Format("2006-01-02") + " 01:00:00")
|
||
sqlParams := []interface{}{order.FromStoreID, model.OrderStatusDelivering, model.OrderStatusCanceled, model.PayStatusYes, lastTime}
|
||
err = dao.GetRows(db, &orderPays, sql, sqlParams)
|
||
if len(orderPays) == 0 {
|
||
store := stores[0]
|
||
store.IsBoughtMatter = model.NO
|
||
dao.UpdateEntity(db, store, "IsBoughtMatter")
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func MarkArrears(db *dao.DaoDB, order *model.GoodsOrder, orderPay *model.OrderPay) {
|
||
//退款后,若此订单下单用户有推广人,则需要将分给推广人的金额记录到该推广人的欠款中
|
||
orders, _ := dao.QueryOrders(db, order.VendorOrderID, 0, []int{model.VendorIDJX}, 0, utils.DefaultTimeValue, utils.DefaultTimeValue)
|
||
if len(orders) > 0 {
|
||
user, _ := dao.GetUserByID(db, "user_id", orders[0].UserID)
|
||
if user.ParentMobile != "" {
|
||
user2, _ := dao.GetUserByID(db, "mobile", user.ParentMobile)
|
||
user2.Arrears = user2.Arrears + (orderPay.TotalFee * user2.DividePercentage / 100)
|
||
dao.UpdateEntity(db, user2, "Arrears")
|
||
if user2.ParentMobile != "" {
|
||
user3, _ := dao.GetUserByID(db, "mobile", user2.ParentMobile)
|
||
user3.Arrears = user3.Arrears + ((orderPay.TotalFee - user2.Arrears) * user3.DividePercentage / 100)
|
||
dao.UpdateEntity(db, user3, "Arrears")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func AgreeOrRefuseCancel(ctx *jxcontext.Context, order *model.GoodsOrder, isAgree bool, reason string) (err error) {
|
||
if isAgree {
|
||
err = CancelOrder(ctx, order, reason)
|
||
} else {
|
||
err = changeOrderStatus(order.VendorOrderID, model.OrderStatusVendorRejectCancel, reason)
|
||
}
|
||
return err
|
||
}
|
||
|
||
// todo 消息用异步可能导致丢失,单同步又有重入相关的问题
|
||
func callNewOrder(order *model.GoodsOrder) (err error) {
|
||
jxutils.CallMsgHandlerAsync(func() {
|
||
err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order))
|
||
}, jxutils.ComposeUniversalOrderID(order.VendorOrderID, model.VendorIDJX))
|
||
return err
|
||
}
|
||
|
||
func changeOrderStatus(vendorOrderID string, status int, remark string) (err error) {
|
||
orderStatus := &model.OrderStatus{
|
||
VendorOrderID: vendorOrderID,
|
||
VendorID: model.VendorIDJX,
|
||
OrderType: model.OrderTypeOrder,
|
||
RefVendorOrderID: vendorOrderID,
|
||
RefVendorID: model.VendorIDJX,
|
||
VendorStatus: utils.Int2Str(status),
|
||
Status: status,
|
||
StatusTime: time.Now(),
|
||
Remark: remark,
|
||
}
|
||
jxutils.CallMsgHandlerAsync(func() {
|
||
err = partner.CurOrderManager.OnOrderStatusChanged("", orderStatus)
|
||
}, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJX))
|
||
return err
|
||
}
|
||
|
||
func GetOrderPay(ctx *jxcontext.Context, vendorOrderID string) (payList []*model.OrderPay, err error) {
|
||
db := dao.GetDB()
|
||
payList, err = dao.GetOrderPayList(db, vendorOrderID, jxutils.GetPossibleVendorIDFromVendorOrderID(vendorOrderID))
|
||
return payList, err
|
||
}
|
||
|
||
func PayForPopluarMan(ctx *jxcontext.Context, vendorOrderID, userID string, price int) (err error) {
|
||
db := dao.GetDB()
|
||
user, err := dao.GetUserByID(db, "user_id", userID)
|
||
if user == nil {
|
||
return fmt.Errorf("未找到此用户!用户ID:[%v]\n", userID)
|
||
}
|
||
auth, err := dao.GetUserBindAuthInfo(db, userID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170")
|
||
if len(auth) == 0 {
|
||
return fmt.Errorf("未找到此用户的微信验证方式!用户ID:[%v]\n", userID)
|
||
}
|
||
goods, err := dao.QueryOrders(db, vendorOrderID, 0, []int{model.VendorIDJX}, 0, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if len(goods) == 0 {
|
||
return fmt.Errorf("未找到此订单!订单ID:[%v]\n", vendorOrderID)
|
||
}
|
||
param := &wxpayapi.TransfersParam{
|
||
CheckName: wxpayapi.CheckName,
|
||
PartnerTradeNo: vendorOrderID,
|
||
Desc: "每日推广人订单分成分到个人",
|
||
SpbillCreateIP: ctx.GetRealRemoteIP(),
|
||
OpenID: auth[0].AuthID,
|
||
Amount: price,
|
||
}
|
||
_, err = api.WxpayAPI.Transfers(param)
|
||
return err
|
||
}
|
||
|
||
//自动打款给市场推广人
|
||
func AutoPayForPopluarMan(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
errMsg string
|
||
errCode string
|
||
db = dao.GetDB()
|
||
fromDateStr = time.Now().AddDate(0, 0, -1).Format("2006-1-2") + " 00:00:00"
|
||
toDateStr = time.Now().AddDate(0, 0, -1).Format("2006-1-2") + " 23:59:59"
|
||
mapResult = make(map[string]interface{})
|
||
)
|
||
result, err := dao.GetOrdersForJxPay(db, utils.Str2Time(fromDateStr), utils.Str2Time(toDateStr))
|
||
for _, goods := range result {
|
||
var (
|
||
param = &wxpayapi.TransfersParam{
|
||
CheckName: wxpayapi.CheckName,
|
||
Desc: "每日推广人订单分成分到个人",
|
||
SpbillCreateIP: ctx.GetRealRemoteIP(),
|
||
}
|
||
payPrice1 int
|
||
payPrice2 int
|
||
)
|
||
user, err := dao.GetUserByID(db, "user_id", goods.UserID)
|
||
if user.ParentMobile == "" {
|
||
return err
|
||
}
|
||
user2, err := dao.GetUserByID(db, "mobile", user.ParentMobile)
|
||
auths, err := dao.GetUserBindAuthInfo(db, user2.UserID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(auths) == 0 {
|
||
errMsg += fmt.Sprintf("打款失败!未找到此用户的微信验证方式!订单号:[%v],用户ID:[%v]\n", goods.VendorOrderID, user2.UserID)
|
||
} else {
|
||
var openID string
|
||
for _, auth := range auths {
|
||
if auth.TypeID == wxAppID {
|
||
openID = auth.AuthID
|
||
}
|
||
}
|
||
payPrice1 = int(goods.ActualPayPrice) * user2.DividePercentage / 100
|
||
//表示这个人之前有欠款,意思是取消订单退款时,这个推广人的分成收不回来,算作欠款,打钱的时候要扣除
|
||
//表示这个人之前有小于3毛钱的款没有打(微信付款api付款最低3毛),记录下来加到以后的款项中
|
||
rPrice := payPrice1 - user2.Arrears + user2.Profit
|
||
err = updateUserAndTransfers(db, param, user2, openID, rPrice)
|
||
if err != nil {
|
||
errMsg += err.Error()
|
||
}
|
||
mapResult["打款人1"] = user2.Name
|
||
mapResult["打款人金额1"] = rPrice
|
||
mapResult["打款人电话1"] = user2.Mobile
|
||
mapResult["打款人1userID"] = user2.UserID
|
||
}
|
||
if user2.ParentMobile != "" {
|
||
user3, err := dao.GetUserByID(db, "mobile", user2.ParentMobile)
|
||
auths, err := dao.GetUserBindAuthInfo(db, user3.UserID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(auths) == 0 {
|
||
errMsg += fmt.Sprintf("打款失败!未找到此用户的微信验证方式!订单号:[%v],用户ID:[%v]\n", goods.VendorOrderID, user3.UserID)
|
||
} else {
|
||
var openID string
|
||
for _, auth := range auths {
|
||
if auth.TypeID == wxAppID {
|
||
openID = auth.AuthID
|
||
}
|
||
}
|
||
payPrice2 = (int(goods.ActualPayPrice) - payPrice1) * user3.DividePercentage / 100
|
||
rPrice := payPrice2 - user3.Arrears + user3.Profit
|
||
err = updateUserAndTransfers(db, param, user3, openID, rPrice)
|
||
if err != nil {
|
||
errMsg += err.Error()
|
||
}
|
||
mapResult["打款人2"] = user3.Name
|
||
mapResult["打款人金额2"] = rPrice
|
||
mapResult["打款人电话2"] = user3.Mobile
|
||
mapResult["打款人2userID"] = user3.UserID
|
||
}
|
||
}
|
||
}
|
||
user, _ := dao.GetUserByID(dao.GetDB(), "mobile", "18160030913")
|
||
if user != nil && errMsg != "" {
|
||
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "每日打款错误", errMsg)
|
||
}
|
||
if err != nil || errMsg != "" {
|
||
errMsg += err.Error()
|
||
errCode = model.ErrCodeGeneralFailed
|
||
} else {
|
||
errCode = model.ErrCodeSuccess
|
||
}
|
||
err = event.AddOperateEvent(ctx, ctx.GetTrackInfo(), cms.BuildDiffData(mapResult), errCode, errMsg, 0, "AutoPayForPopluarMan")
|
||
globals.SugarLogger.Debugf("每日订单打款:[%v]", cms.BuildDiffData(mapResult))
|
||
return err
|
||
}
|
||
|
||
func updateUserAndTransfers(db *dao.DaoDB, param *wxpayapi.TransfersParam, user *model.User, authID string, rPrice int) (err error) {
|
||
if rPrice >= 30 {
|
||
param.OpenID = authID
|
||
param.Amount = rPrice
|
||
param.PartnerTradeNo = utils.GetUUID()
|
||
_, err = api.WxpayAPI.Transfers(param)
|
||
user.ProfitSum = user.ProfitSum + rPrice
|
||
user.Profit = 0
|
||
user.Arrears = 0
|
||
} else if rPrice >= 0 && rPrice < 30 {
|
||
user.Profit = rPrice
|
||
user.Arrears = 0
|
||
} else {
|
||
user.Profit = 0
|
||
user.Arrears = int(utils.Float64TwoInt64(math.Abs(utils.Int2Float64(rPrice))))
|
||
}
|
||
_, err = dao.UpdateEntity(db, user, "ProfitSum", "Profit", "Arrears")
|
||
return err
|
||
}
|
||
|
||
func CancelPayTimeOutOrder(ctx *jxcontext.Context) (err error) {
|
||
db := dao.GetDB()
|
||
var orders []*model.GoodsOrder
|
||
sql := `
|
||
SELECT *
|
||
FROM goods_order
|
||
WHERE order_created_at >= ? AND order_created_at <= NOW()
|
||
AND status = ?
|
||
AND vendor_id = ?
|
||
`
|
||
sqlParams := []interface{}{
|
||
time.Now().Add(-time.Minute * 30),
|
||
model.OrderStatusWait4Pay,
|
||
model.VendorIDJX,
|
||
}
|
||
err = dao.GetRows(db, &orders, sql, sqlParams)
|
||
for _, v := range orders {
|
||
if v.OrderCreatedAt.Add(PayWaitingTime).Before(time.Now()) {
|
||
err2 := changeOrderStatus(v.VendorOrderID, model.OrderStatusCanceled, autoCancelOrderReason)
|
||
err = err2
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func GetHalfHoursList() (strs []string) {
|
||
for k := 0; k < 3; k++ {
|
||
for i := 0; i < 10; i++ {
|
||
for j := 0; j < 4; j += 3 {
|
||
if k == 2 && i > 3 {
|
||
break
|
||
}
|
||
strs = append(strs, utils.Int2Str(k)+utils.Int2Str(i)+":"+utils.Int2Str(j)+"0"+":00")
|
||
}
|
||
}
|
||
}
|
||
return strs
|
||
}
|
||
|
||
func RefreshAllMatterOrderStatus(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
goodsList []*model.GoodsOrder
|
||
realTime time.Time
|
||
)
|
||
realTime = time.Now().AddDate(0, 0, -7)
|
||
//有分包的主订单
|
||
sql := `
|
||
SELECT * FROM goods_order WHERE store_id = 666666 AND order_created_at >= ? AND status < ? AND vendor_id = ? AND LENGTH(vendor_order_id) = 14
|
||
`
|
||
sqlParams := []interface{}{realTime, model.OrderStatusEndBegin, model.VendorIDJX}
|
||
err = dao.GetRows(db, &goodsList, sql, sqlParams)
|
||
for _, v := range goodsList {
|
||
if v.EclpOutID == "" {
|
||
var (
|
||
goodsList2 []*model.GoodsOrder
|
||
cancelCount int
|
||
deliveringCount int
|
||
)
|
||
sql2 := "SELECT * FROM goods_order WHERE vendor_order_id LIKE ? OR vendor_order_id LIKE ? AND vendor_id = ? AND eclp_out_id <> '' AND LENGTH(vendor_order_id) = 16"
|
||
sqlParams2 := []interface{}{v.VendorOrderID + "0%", v.VendorOrderID + "1%", model.VendorIDJX}
|
||
err = dao.GetRows(db, &goodsList2, sql2, sqlParams2)
|
||
for _, vv := range goodsList2 {
|
||
if vv.Status < model.OrderStatusFinished {
|
||
queryOrderStatus, _ := api.JdEclpAPI.QueryOrderStatus(vv.EclpOutID)
|
||
if len(queryOrderStatus.OrderStatusList) > 0 {
|
||
if queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode == jdeclpapi.SoStatusCode10034 {
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
vv.Status = model.OrderStatusFinished
|
||
dao.UpdateEntity(db, vv, "Status")
|
||
waybills, err := dao.GetWaybills(db, vv.VendorOrderID)
|
||
if err == nil && len(waybills) > 0 {
|
||
waybills[0].Status = model.WaybillStatusDelivered
|
||
dao.UpdateEntity(db, waybills[0], "Status")
|
||
}
|
||
dao.Commit(db)
|
||
changeOrderStatus(vv.VendorOrderID, model.OrderStatusFinished, "")
|
||
getTrackMessagePlusByOrderResult, _ := api.JdEclpAPI.GetTrackMessagePlusByOrder(vv.VendorOrderID)
|
||
updateJdWayBillInfo(db, vv, getTrackMessagePlusByOrderResult)
|
||
} else {
|
||
deliveringCount++
|
||
}
|
||
}
|
||
} else if vv.Status == model.OrderStatusCanceled {
|
||
cancelCount++
|
||
}
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if deliveringCount == 0 {
|
||
v.Status = model.OrderStatusFinished
|
||
} else {
|
||
if cancelCount == len(goodsList2) {
|
||
v.Status = model.OrderStatusCanceled
|
||
}
|
||
}
|
||
if v.Status < model.OrderStatusDelivering {
|
||
v.Status = model.OrderStatusCanceled
|
||
}
|
||
dao.UpdateEntity(db, v, "Status")
|
||
dao.Commit(db)
|
||
changeOrderStatus(v.VendorOrderID, v.Status, "")
|
||
} else {
|
||
queryOrderStatus, _ := api.JdEclpAPI.QueryOrderStatus(v.EclpOutID)
|
||
getTrackMessagePlusByOrderResult, _ := api.JdEclpAPI.GetTrackMessagePlusByOrder(v.VendorOrderID)
|
||
updateMatterOrderStatus(db, v, queryOrderStatus)
|
||
updateJdWayBillInfo(db, v, getTrackMessagePlusByOrderResult)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func GetMatterOrderStatus(ctx *jxcontext.Context, vendorOrderID string) (result []*MatterOrderStatus, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
order, err := dao.GetSimpleOrder(db, vendorOrderID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if order.EclpOutID == "" {
|
||
return nil, err
|
||
}
|
||
queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(order.EclpOutID)
|
||
getTrackMessagePlusByOrderResult, err := api.JdEclpAPI.GetTrackMessagePlusByOrder(vendorOrderID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for _, v := range queryOrderStatus.OrderStatusList {
|
||
matter := &MatterOrderStatus{}
|
||
matter.Time = utils.Str2Time(v.OperateTime)
|
||
matter.Status = v.SoStatusName
|
||
matter.Name = v.SoStatusName
|
||
matter.Sign = 1
|
||
result = append(result, matter)
|
||
}
|
||
if len(getTrackMessagePlusByOrderResult.ResultData) > 0 {
|
||
for _, vv := range getTrackMessagePlusByOrderResult.ResultData {
|
||
matter := &MatterOrderStatus{}
|
||
matter.Time = utils.Str2Time(strings.ReplaceAll(vv.OpeTime, "/", "-"))
|
||
matter.Status = vv.OpeTitle
|
||
matter.Name = vv.OpeRemark
|
||
matter.Sign = 2
|
||
result = append(result, matter)
|
||
}
|
||
}
|
||
for i := 0; i < len(result)-1; i++ {
|
||
for j := 0; j < len(result)-i-1; j++ {
|
||
if result[j].Time.Unix() > result[j+1].Time.Unix() || (result[j].Time.Unix() == result[j+1].Time.Unix() && result[j].Sign > result[j+1].Sign) {
|
||
tmp := result[j]
|
||
result[j] = result[j+1]
|
||
result[j+1] = tmp
|
||
}
|
||
}
|
||
}
|
||
if len(queryOrderStatus.OrderStatusList) > 0 {
|
||
updateMatterOrderStatus(db, order, queryOrderStatus)
|
||
}
|
||
if len(getTrackMessagePlusByOrderResult.ResultData) > 0 {
|
||
updateJdWayBillInfo(db, order, getTrackMessagePlusByOrderResult)
|
||
}
|
||
return result, err
|
||
}
|
||
|
||
func updateMatterOrderStatus(db *dao.DaoDB, order *model.GoodsOrder, queryOrderStatus *jdeclpapi.QueryOrderStatusResult) {
|
||
code := queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode
|
||
if code == jdeclpapi.SoStatusCode10034 || code == jdeclpapi.SoStatusCode10038 {
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
order.Status = model.OrderStatusFinished
|
||
dao.UpdateEntity(db, order, "Status")
|
||
waybills, err := dao.GetWaybills(db, order.VendorOrderID)
|
||
if err == nil && len(waybills) > 0 {
|
||
waybills[0].Status = model.WaybillStatusDelivered
|
||
dao.UpdateEntity(db, waybills[0], "Status")
|
||
}
|
||
dao.Commit(db)
|
||
changeOrderStatus(order.VendorOrderID, model.OrderStatusFinished, "")
|
||
}
|
||
}
|
||
|
||
func updateJdWayBillInfo(db *dao.DaoDB, order *model.GoodsOrder, getTrackMessagePlusByOrderResult *jdeclpapi.GetTrackMessagePlusByOrderResult) (err error) {
|
||
var (
|
||
waybillCode string
|
||
cName string
|
||
cMobile string
|
||
waybills []*model.Waybill
|
||
)
|
||
if len(getTrackMessagePlusByOrderResult.ResultData) > 0 {
|
||
waybillCode = getTrackMessagePlusByOrderResult.ResultData[0].WaybillCode
|
||
} else {
|
||
return err
|
||
}
|
||
for _, vv := range getTrackMessagePlusByOrderResult.ResultData {
|
||
if vv.OpeTitle == "配送员收货" {
|
||
result := regexpCnameAndCmobile.FindAllStringSubmatch(vv.OpeRemark, -1)
|
||
if len(result) > 0 {
|
||
cName = result[0][1]
|
||
cMobile = result[0][2]
|
||
} else {
|
||
result2 := regexpCnameAndCmobile2.FindAllStringSubmatch(vv.OpeRemark, -1)
|
||
if len(result2) > 0 {
|
||
cName = result2[0][1]
|
||
cMobile = result2[0][2]
|
||
}
|
||
}
|
||
break
|
||
}
|
||
}
|
||
waybills, err = dao.GetWaybills(db, order.VendorOrderID)
|
||
if len(waybills) > 0 {
|
||
waybills[0].VendorWaybillID = waybillCode
|
||
waybills[0].CourierName = cName
|
||
waybills[0].CourierMobile = cMobile
|
||
order.VendorWaybillID = waybillCode
|
||
order.WaybillVendorID = model.VendorIDJDWL
|
||
dao.UpdateEntity(db, order, "VendorWaybillID", "WaybillVendorID")
|
||
dao.UpdateEntity(db, waybills[0], "VendorWaybillID", "CourierName", "CourierMobile")
|
||
}
|
||
return err
|
||
}
|
||
|
||
func tryToSplitMatterOrder(jxOrder *JxOrderInfo) (outOrders []*JxOrderInfo, freightPrice int64, err error) {
|
||
var (
|
||
skus = jxOrder.Skus
|
||
weightList []*JxSkuInfo2
|
||
)
|
||
//我的思路为把所有商品依次按重量销量从大到小排列,然后第一个包尽量分出3kg,后面分出4.5kg
|
||
//但是我把JxSkuInfo放进list的时候,想根据一个参数GroupSign判断是否这个商品已经分出去了
|
||
//但是在list中同一个商品通过以下方式放进去的地址是一样的,我改了一个商品的GroupSign,所有的都变了,所以只有分出一个JxSkuInfo2去弄。。
|
||
//要做优化的话更好
|
||
for _, v := range skus {
|
||
for i := 0; i < v.Count; i++ {
|
||
var sku2 = &JxSkuInfo2{}
|
||
sku2.Count = v.Count
|
||
sku2.Name = v.Name
|
||
sku2.Price = v.Price
|
||
sku2.SalePrice = v.SalePrice
|
||
sku2.Weight = v.Weight
|
||
sku2.SkuID = v.SkuID
|
||
weightList = append(weightList, sku2)
|
||
}
|
||
}
|
||
for i := 0; i < len(weightList)-1; i++ {
|
||
for j := 0; j < len(weightList)-i-1; j++ {
|
||
if weightList[j].Weight < weightList[j+1].Weight {
|
||
tmp := weightList[j]
|
||
weightList[j] = weightList[j+1]
|
||
weightList[j+1] = tmp
|
||
}
|
||
}
|
||
}
|
||
weight := jxOrder.Weight
|
||
for {
|
||
//每拿出一组就删掉list里的值
|
||
outOrders = append(outOrders, loop2(weightList, jxOrder.StoreID, &weight))
|
||
for i := 0; i < len(weightList); {
|
||
if weightList[i].GroupSign {
|
||
var weightList3 []*JxSkuInfo2
|
||
weightList3 = append(weightList[:i], weightList[i+1:]...)
|
||
weightList = weightList3
|
||
} else {
|
||
i++
|
||
}
|
||
}
|
||
if len(weightList) == 0 {
|
||
break
|
||
}
|
||
}
|
||
for _, v := range outOrders {
|
||
if v.Weight <= 3000 {
|
||
freightPrice += 500
|
||
} else if v.Weight > 3000 && v.Weight <= splitMatterOrderMinWeight {
|
||
freightPrice += utils.Float64TwoInt64(500 + math.Ceil((utils.Int2Float64(v.Weight)-3000)/1000)*200)
|
||
}
|
||
}
|
||
return outOrders, freightPrice, err
|
||
}
|
||
|
||
func jxOrderChange(sku2 *JxSkuInfo2) *JxSkuInfo {
|
||
sku := &JxSkuInfo{}
|
||
sku.Count = 1
|
||
sku.Name = sku2.Name
|
||
sku.Price = sku2.Price
|
||
sku.SalePrice = sku2.SalePrice
|
||
sku.SkuID = sku2.SkuID
|
||
sku.Weight = sku2.Weight
|
||
return sku
|
||
}
|
||
|
||
//TODO 修改为4.5kg 2020-04-2?
|
||
//商品分包规则2。最后一个包不超过5kg,其他包不超过3kg
|
||
// 举例1:5.1kg,分为 2.5kg,2.6kg,确保每个包不超过3kg,最后一个包不超过5kg
|
||
// 举例2:4kg,分为4kg
|
||
// 举例3:10kg,分为 3kg,3kg,4kg
|
||
// 举例4:8.1kg,分为 3kg,3kg,2.1kg ; 不能分为3kg,5.1kg
|
||
//sum3表示3kg的计算
|
||
func loop2(weightList []*JxSkuInfo2, storeID int, weight *int) (outOrder *JxOrderInfo) {
|
||
outOrder = &JxOrderInfo{}
|
||
outOrder.StoreID = storeID
|
||
sum3 := 0
|
||
if *weight <= splitMatterOrderMinWeight {
|
||
for i := 0; i < len(weightList); i++ {
|
||
buildOutOrderSkus(weightList[i], outOrder)
|
||
}
|
||
} else {
|
||
for i := 0; i < len(weightList); i++ {
|
||
if weightList[i].Weight+sum3 <= 3000 {
|
||
sum3 += weightList[i].Weight
|
||
*weight -= weightList[i].Weight
|
||
buildOutOrderSkus(weightList[i], outOrder)
|
||
} else {
|
||
if sum3 >= 3000 {
|
||
break
|
||
}
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
return outOrder
|
||
}
|
||
|
||
func buildOutOrderSkus(weightp *JxSkuInfo2, outOrder *JxOrderInfo) {
|
||
weightp.GroupSign = true
|
||
outOrder.Weight += weightp.Weight
|
||
if len(outOrder.Skus) > 0 {
|
||
var flag = false
|
||
for _, v := range outOrder.Skus {
|
||
if v.SkuID == weightp.SkuID {
|
||
v.Count++
|
||
flag = true
|
||
}
|
||
}
|
||
if !flag {
|
||
outOrder.Skus = append(outOrder.Skus, jxOrderChange(weightp))
|
||
}
|
||
} else {
|
||
outOrder.Skus = append(outOrder.Skus, jxOrderChange(weightp))
|
||
}
|
||
}
|
||
|
||
func checkMatterDeliveryAddress(deliveryAddress *dao.UserDeliveryAddressEx) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
if !strings.Contains(deliveryAddress.Address, "区") {
|
||
deliveryAddress.Address = deliveryAddress.DistrictName + deliveryAddress.Address
|
||
}
|
||
if !strings.Contains(deliveryAddress.Address, "市") {
|
||
deliveryAddress.Address = deliveryAddress.CityName + deliveryAddress.Address
|
||
}
|
||
if !strings.Contains(deliveryAddress.Address, "省") {
|
||
if place1, err := dao.GetPlaceByCode(db, deliveryAddress.CityCode); err == nil {
|
||
if place2, err2 := dao.GetPlaceByCode(db, place1.ParentCode); err2 == nil {
|
||
deliveryAddress.Address = place2.Name + deliveryAddress.Address
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func SendFailedMatterOrder(ctx *jxcontext.Context, vendorOrderID string) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJX)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if order == nil || order.StoreID != model.MatterStoreID || order.FromStoreID == 0 {
|
||
return fmt.Errorf("只允许物料店重发物料订单调用此接口!")
|
||
}
|
||
queryOrderStatus, err := api.JdEclpAPI.QueryOrderStatus(order.EclpOutID)
|
||
if len(queryOrderStatus.OrderStatusList) > 0 {
|
||
code := queryOrderStatus.OrderStatusList[len(queryOrderStatus.OrderStatusList)-1].SoStatusCode
|
||
if code == jdeclpapi.SoStatusCode10022 || code == jdeclpapi.SoStatusCode10038 { //表示该订单在京东物流为暂停或已经逆向发货完成
|
||
if len(order.VendorOrderID) == 14 && order.EclpOutID != "" { //这是不分包的订单
|
||
_, err = createMatterOrder(buildJxOrderInfo(order, order.Skus), order, int64(00))
|
||
err = CancelMatterOrder(db, order, cancelMatterOrderReason)
|
||
changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason)
|
||
for _, v := range order.Skus {
|
||
cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID)
|
||
}
|
||
} else if len(order.VendorOrderID) == 14 && order.EclpOutID == "" { //这是分包的主订单
|
||
goodsList, err := dao.GetMatterChildOrders(db, order.VendorOrderID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(goodsList) > 0 {
|
||
for _, v := range goodsList {
|
||
cOrder, err := partner.CurOrderManager.LoadOrder(v.VendorOrderID, model.VendorIDJX)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
suffix := utils.Str2Int64(cOrder.VendorOrderID[len(cOrder.VendorOrderID)-2:]) + int64(len(goodsList))
|
||
_, err = createMatterOrder(buildJxOrderInfo(cOrder, cOrder.Skus), cOrder, suffix)
|
||
for _, v := range cOrder.Skus {
|
||
cms.RefreshMatterStock(jxcontext.AdminCtx, v.SkuID)
|
||
}
|
||
}
|
||
}
|
||
err = CancelMatterOrder(db, order, cancelMatterOrderReason)
|
||
changeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, cancelMatterOrderReason)
|
||
} else if len(order.VendorOrderID) == 16 && order.EclpOutID != "" { // 这是分包的子订单
|
||
return fmt.Errorf("请重发主订单!主订单号:[%v]", order.VendorOrderID[len(order.VendorOrderID)-2:])
|
||
}
|
||
} else {
|
||
return fmt.Errorf("只允许物流订单为暂停或逆向完成才能调用此接口!")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func createMatterOrder(jxOrder *JxOrderInfo, order *model.GoodsOrder, newOrderIDSuffix int64) (order2 *model.GoodsOrder, err error) {
|
||
outJxOrder, deliveryAddress, err := generateOrder(jxcontext.AdminCtx, jxOrder, order.AddressID, order.FromStoreID, order.UserID, false)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
outJxOrder.OrderID = utils.Str2Int64(order.VendorOrderID)*100 + newOrderIDSuffix
|
||
checkMatterDeliveryAddress(deliveryAddress)
|
||
order2, err2 := jxOrder2GoodsOrder(jxcontext.AdminCtx, outJxOrder, deliveryAddress, order.UserID, false)
|
||
if err = err2; err == nil {
|
||
order2.AddressID = order.AddressID
|
||
order2.Status = model.OrderStatusDelivering
|
||
err = partner.CurOrderManager.OnOrderNew(order2, model.Order2Status(order2))
|
||
err = orderSolutionForWuLiao(order2)
|
||
}
|
||
return order2, err
|
||
}
|
||
|
||
func buildJxOrderInfo(order *model.GoodsOrder, orderSkus []*model.OrderSku) (jxOrder *JxOrderInfo) {
|
||
jxOrder = &JxOrderInfo{}
|
||
jxOrder.StoreID = order.StoreID
|
||
weight := 0
|
||
var skus []*JxSkuInfo
|
||
for _, v := range orderSkus {
|
||
weight += v.Weight * v.Count
|
||
sku := &JxSkuInfo{}
|
||
sku.SkuID = v.SkuID
|
||
sku.SalePrice = v.SalePrice
|
||
sku.Name = v.SkuName
|
||
sku.Weight = v.Weight
|
||
sku.Count = v.Count
|
||
skus = append(skus, sku)
|
||
}
|
||
jxOrder.Skus = skus
|
||
jxOrder.Weight = weight
|
||
return jxOrder
|
||
}
|