446 lines
13 KiB
Go
446 lines
13 KiB
Go
package act
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
"git.rosy.net.cn/jx-callback/business/partner"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
||
"git.rosy.net.cn/jx-callback/business/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
)
|
||
|
||
const (
|
||
DefActSkuStock = 200 // 缺省活动库存
|
||
)
|
||
|
||
type ActOrderRuleParam struct {
|
||
SalePrice int64 `orm:"" json:"salePrice"` // 满的价格
|
||
DeductPrice int64 `orm:"" json:"deductPrice"` // 减的价格
|
||
}
|
||
|
||
type ActStoreSkuParam struct {
|
||
model.ActStoreSku
|
||
}
|
||
|
||
type ActDetail struct {
|
||
model.Act2
|
||
}
|
||
|
||
type ActMapPureInfo struct {
|
||
VendorID int `orm:"column(vendor_id)" json:"vendorID"`
|
||
VendorActID string `orm:"column(vendor_act_id);size(48)" json:"vendorActID"`
|
||
SyncStatus int `orm:"default(2)" json:"syncStatus"`
|
||
}
|
||
|
||
type ActVendorInfo struct {
|
||
model.Act
|
||
VendorList []*ActMapPureInfo
|
||
}
|
||
|
||
func ActStoreSkuParam2Model(ctx *jxcontext.Context, db *dao.DaoDB, act *model.Act, vendorIDs []int, actStoreSku []*ActStoreSkuParam) (validVendorIDs []int, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap, err error) {
|
||
wholeValidVendorMap := make(map[int]int)
|
||
if len(actStoreSku) > 0 {
|
||
storeIDMap := make(map[int]int)
|
||
skuIDMap := make(map[int]int)
|
||
storeSkuParamMap := make(map[int][]*ActStoreSkuParam)
|
||
for _, v := range actStoreSku {
|
||
storeIDMap[v.StoreID] = 1
|
||
skuIDMap[v.SkuID] = 1
|
||
storeSkuParamMap[v.StoreID] = append(storeSkuParamMap[v.StoreID], v)
|
||
}
|
||
|
||
storeSkuList, err2 := dao.GetStoresSkusInfo(db, jxutils.IntMap2List(storeIDMap), jxutils.IntMap2List(skuIDMap))
|
||
if err = err2; err != nil {
|
||
return nil, nil, nil, err
|
||
}
|
||
storeSkuMap := make(map[int64]*model.StoreSkuBind)
|
||
for _, v := range storeSkuList {
|
||
storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v
|
||
}
|
||
|
||
for storeID, oneStoreSkuParam := range storeSkuParamMap {
|
||
validVendorMap := make(map[int]int)
|
||
validSkuMap := make(map[int]int)
|
||
for _, vendorID := range vendorIDs {
|
||
storeDetail, err2 := dao.GetStoreDetail(db, storeID, vendorID)
|
||
if err = err2; err == nil {
|
||
for _, v := range oneStoreSkuParam {
|
||
if storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||
validVendorMap[vendorID] = 1
|
||
validSkuMap[v.SkuID] = 1
|
||
actSkuMap := &model.ActStoreSkuMap{
|
||
ActID: act.ID,
|
||
StoreID: storeID,
|
||
SkuID: v.SkuID,
|
||
VendorID: vendorID,
|
||
|
||
SyncStatus: model.SyncFlagNewMask,
|
||
}
|
||
if v.ActPrice != 0 {
|
||
actSkuMap.ActualActPrice = v.ActPrice
|
||
} else {
|
||
percentage := act.PricePercentage
|
||
if v.PricePercentage != 0 {
|
||
percentage = v.PricePercentage
|
||
}
|
||
percentage = percentage * int(storeDetail.PricePercentage) / 100
|
||
actSkuMap.ActualActPrice = int64(jxutils.CaculateSkuVendorPrice(storeSkuInfo.Price, percentage, 0))
|
||
}
|
||
dao.WrapAddIDCULDEntity(actSkuMap, ctx.GetUserName())
|
||
actStoreSkuMapList = append(actStoreSkuMapList, actSkuMap)
|
||
}
|
||
}
|
||
wholeValidVendorMap[vendorID] = 1
|
||
} else if !dao.IsNoRowsError(err) {
|
||
return nil, nil, nil, err
|
||
} else {
|
||
err = nil
|
||
}
|
||
}
|
||
|
||
for _, v := range oneStoreSkuParam {
|
||
if validSkuMap[v.SkuID] == 1 { // todo 这里是否需要判断
|
||
if storeSkuInfo := storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]; storeSkuInfo != nil {
|
||
storeSku := &v.ActStoreSku
|
||
storeSku.ActID = act.ID
|
||
storeSku.OriginalPrice = int64(storeSkuInfo.Price)
|
||
dao.WrapAddIDCULDEntity(storeSku, ctx.GetUserName())
|
||
actStoreSkuList = append(actStoreSkuList, storeSku)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return jxutils.IntMap2List(wholeValidVendorMap), actStoreSkuList, actStoreSkuMapList, err
|
||
}
|
||
|
||
func addActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actStoreSkuList []*model.ActStoreSku, actStoreSkuMapList []*model.ActStoreSkuMap) (err error) {
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
|
||
storeSkuMap := make(map[int64]int)
|
||
for _, v := range actStoreSkuList {
|
||
if v.Stock == 0 {
|
||
v.Stock = DefActSkuStock
|
||
}
|
||
err = dao.CreateEntity(db, v)
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
return err
|
||
}
|
||
storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v.ID
|
||
}
|
||
for _, v := range actStoreSkuMapList {
|
||
v.BindID = storeSkuMap[jxutils.Combine2Int(v.StoreID, v.SkuID)]
|
||
}
|
||
|
||
if len(actStoreSkuMapList) > 0 {
|
||
err = dao.CreateMultiEntities(db, actStoreSkuMapList)
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
return err
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func AddActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSku []*ActStoreSkuParam) (err error) {
|
||
actMap, err := dao.GetActVendorInfo(db, actID, nil)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
vendorIDs := partner.GetVendorIDsFromActMap(actMap)
|
||
|
||
var act *model.Act
|
||
if len(vendorIDs) > 0 {
|
||
act = &actMap[vendorIDs[0]].Act
|
||
} else {
|
||
act = &model.Act{}
|
||
act.ID = actID
|
||
if err = dao.GetEntity(db, act); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if act.Status != model.ActStatusCreated {
|
||
return fmt.Errorf("当前活动状态:%s不能进行此操作", model.ActStatusName[act.Status])
|
||
}
|
||
|
||
_, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, db, act, vendorIDs, actStoreSku)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil || err != nil {
|
||
dao.Rollback(db)
|
||
if r != nil {
|
||
panic(r)
|
||
}
|
||
}
|
||
}()
|
||
if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil {
|
||
return err
|
||
}
|
||
for _, act := range actMap {
|
||
if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act),
|
||
map[string]interface{}{
|
||
model.FieldSyncStatus: act.SyncStatus | model.SyncFlagModifiedMask,
|
||
}, ctx.GetUserName(), nil); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func CreateAct(ctx *jxcontext.Context, act *model.Act, vendorIDs []int, actRules []*ActOrderRuleParam, actStoreSku []*ActStoreSkuParam, isAsync bool) (hint string, err error) {
|
||
db := dao.GetDB()
|
||
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if act.LimitCount == 0 {
|
||
act.LimitCount = 1 // 缺省限购一份,如果确定不限,明确给一个很大的值
|
||
}
|
||
act.Status = model.ActStatusCreated
|
||
dao.WrapAddIDCULDEntity(act, ctx.GetUserName())
|
||
err = dao.CreateEntity(db, act)
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
return "", err
|
||
}
|
||
|
||
validVendorIDs, actStoreSkuList, actStoreSkuMapList, err := ActStoreSkuParam2Model(ctx, db, act, vendorIDs, actStoreSku)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
var actMapList []*model.ActMap
|
||
for _, vendorID := range validVendorIDs {
|
||
actMap := &model.ActMap{
|
||
ActID: act.ID,
|
||
VendorID: vendorID,
|
||
|
||
SyncStatus: model.SyncFlagNewMask,
|
||
}
|
||
dao.WrapAddIDCULDEntity(actMap, ctx.GetUserName())
|
||
actMapList = append(actMapList, actMap)
|
||
}
|
||
if len(actMapList) > 0 {
|
||
err = dao.CreateMultiEntities(db, actMapList)
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
return "", err
|
||
}
|
||
}
|
||
|
||
if err = addActStoreSkuBind(ctx, db, actStoreSkuList, actStoreSkuMapList); err != nil {
|
||
dao.Rollback(db)
|
||
return "", err
|
||
}
|
||
dao.Commit(db)
|
||
|
||
hint, err = SyncAct(ctx, nil, act.ID, nil, nil, nil, isAsync)
|
||
if !isAsync {
|
||
hint = utils.Int2Str(act.ID)
|
||
}
|
||
return hint, err
|
||
}
|
||
|
||
func QueryActs(ctx *jxcontext.Context, actID int, offset, pageSize int, keyword string, statusList []int, actTypeList []int, storeID, skuID, cityCode int, beginAt, endAt, createdAtFrom, createdAtTo time.Time) (pagedInfo *dao.PagedActListInfo, err error) {
|
||
return dao.QueryActs(dao.GetDB(), actID, offset, pageSize, keyword, statusList, actTypeList, storeID, skuID, cityCode, beginAt, endAt, createdAtFrom, createdAtTo)
|
||
}
|
||
|
||
func GetActVendorInfo(ctx *jxcontext.Context, actID int) (actVendorInfo *ActVendorInfo, err error) {
|
||
db := dao.GetDB()
|
||
actMap, err := dao.GetActVendorInfo(db, actID, nil)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if len(actMap) == 0 {
|
||
return nil, fmt.Errorf("不能找到活动:%d", actID)
|
||
}
|
||
actVendorInfo = &ActVendorInfo{}
|
||
for vendorID, v := range actMap {
|
||
if actVendorInfo.ID == 0 {
|
||
actVendorInfo.Act = v.Act
|
||
}
|
||
actVendorInfo.VendorList = append(actVendorInfo.VendorList, &ActMapPureInfo{
|
||
VendorID: vendorID,
|
||
SyncStatus: v.SyncStatus,
|
||
VendorActID: v.VendorActID,
|
||
})
|
||
}
|
||
return actVendorInfo, err
|
||
}
|
||
|
||
func GetActStoreSkuInfo(ctx *jxcontext.Context, actID int, vendorIDs []int) (actStoreSkuList []*model.ActStoreSku2, err error) {
|
||
db := dao.GetDB()
|
||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, vendorIDs, nil, nil)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if len(actStoreSkuMap) == 0 {
|
||
return nil, fmt.Errorf("不能找到活动:%d", actID)
|
||
}
|
||
for _, v := range actStoreSkuMap {
|
||
actStoreSkuList = append(actStoreSkuList, v...)
|
||
}
|
||
return actStoreSkuList, err
|
||
}
|
||
|
||
func CancelAct(ctx *jxcontext.Context, actID int) (err error) {
|
||
db := dao.GetDB()
|
||
if err = DeleteActStoreSkuBind(ctx, db, actID, nil); err != nil {
|
||
return err
|
||
}
|
||
_, err = SyncAct(ctx, nil, actID, nil, nil, nil, false)
|
||
return err
|
||
}
|
||
|
||
// actStoreSkuParam为空,不会删除act_store_sku,但会删除act_store_sku_map
|
||
func DeleteActStoreSkuBind(ctx *jxcontext.Context, db *dao.DaoDB, actID int, actStoreSkuParam []*ActStoreSkuParam) (err error) {
|
||
actMap, err := dao.GetActVendorInfo(db, actID, nil)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(actMap) == 0 {
|
||
return fmt.Errorf("找不到活动:%d,或已被取消", actID)
|
||
}
|
||
|
||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, nil, nil)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
act := actMap[partner.GetVendorIDsFromActMap(actMap)[0]]
|
||
if act.Status != model.ActStatusCreated {
|
||
return fmt.Errorf("当前活动状态:%s不能进行此操作", model.ActStatusName[act.Status])
|
||
}
|
||
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil || err != nil {
|
||
dao.Rollback(db)
|
||
if r != nil {
|
||
panic(r)
|
||
}
|
||
}
|
||
}()
|
||
|
||
actStoreSkuParamMap := make(map[int64]*ActStoreSkuParam)
|
||
for _, v := range actStoreSkuParam {
|
||
actStoreSkuParamMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v
|
||
if _, err = dao.DeleteEntityLogically(db, &model.ActStoreSku{}, nil, ctx.GetUserName(),
|
||
map[string]interface{}{
|
||
model.FieldActID: actID,
|
||
model.FieldStoreID: v.StoreID,
|
||
model.FieldSkuID: v.SkuID,
|
||
}); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
isNeedCancelAct := true
|
||
for vendorID, act := range actMap {
|
||
isDeleteAll := true
|
||
isDeleteAtLeastOne := false
|
||
actStoreSkuMap := partner.SplitActStoreSku(actStoreSkuMap[vendorID])
|
||
for storeID := range actStoreSkuMap {
|
||
for _, actStoreSku := range actStoreSkuMap[storeID] {
|
||
if actStoreSkuParam == nil || actStoreSkuParamMap[jxutils.Combine2Int(actStoreSku.StoreID, actStoreSku.SkuID)] != nil {
|
||
if _, err = dao.UpdateEntityLogically(db, partner.ActStoreSku2ActStoreSkuMap(actStoreSku),
|
||
map[string]interface{}{
|
||
model.FieldSyncStatus: actStoreSku.SyncStatus | model.SyncFlagDeletedMask,
|
||
}, ctx.GetUserName(), nil); err != nil {
|
||
return err
|
||
}
|
||
isDeleteAtLeastOne = true
|
||
} else {
|
||
isNeedCancelAct = false
|
||
isDeleteAll = false
|
||
}
|
||
}
|
||
}
|
||
if isDeleteAll || isDeleteAtLeastOne {
|
||
syncStatus := model.SyncFlagModifiedMask
|
||
if isDeleteAll {
|
||
syncStatus = model.SyncFlagDeletedMask
|
||
}
|
||
syncStatus |= act.SyncStatus
|
||
if _, err = dao.UpdateEntityLogically(db, partner.Act2ActMap(act),
|
||
map[string]interface{}{
|
||
model.FieldSyncStatus: syncStatus,
|
||
}, ctx.GetUserName(), nil); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if isDeleteAll != isNeedCancelAct {
|
||
globals.SugarLogger.Warnf("deleteActStoreBind, actID:%d isDeleteAll:%t != isNeedCancelAct:%t", act.ID, isDeleteAll, isNeedCancelAct)
|
||
}
|
||
}
|
||
|
||
if isNeedCancelAct {
|
||
act := &model.Act{}
|
||
act.ID = actID
|
||
if _, err = dao.UpdateEntityLogically(db, act,
|
||
map[string]interface{}{
|
||
model.FieldStatus: model.ActStatusCanceled,
|
||
}, ctx.GetUserName(), nil); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func SyncAct(ctx *jxcontext.Context, parentTask tasksch.ITask, actID int, vendorIDs, storeIDs, skuIDs []int, isAsync bool) (hint string, err error) {
|
||
db := dao.GetDB()
|
||
actMap, err := dao.GetActVendorInfo(db, actID, vendorIDs)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
actStoreSkuMap, err := dao.GetActStoreSkuVendorInfo(db, actID, nil, storeIDs, skuIDs)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
if vendorIDs == nil {
|
||
vendorIDs = partner.GetVendorIDsFromActMap(actMap)
|
||
}
|
||
task := tasksch.NewParallelTask("SyncAct", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
vendorID := batchItemList[0].(int)
|
||
if handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IPurchasePlatformActHandler); handler != nil {
|
||
if err = handler.SyncAct(ctx, nil, actMap[vendorID], nil, actStoreSkuMap[vendorID]); err == nil {
|
||
retVal = []int{1}
|
||
}
|
||
}
|
||
return retVal, err
|
||
}, vendorIDs)
|
||
tasksch.HandleTask(task, parentTask, true).Run()
|
||
if !isAsync {
|
||
result, err2 := task.GetResult(0)
|
||
if err = err2; err == nil {
|
||
hint = utils.Int2Str(len(result))
|
||
}
|
||
} else {
|
||
hint = task.GetID()
|
||
}
|
||
return hint, err
|
||
}
|