Files
jx-callback/business/jxstore/act/act.go
2019-07-04 15:25:28 +08:00

446 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}