package dao import ( "fmt" "time" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" ) type ActMapPureInfo struct { VendorID int `orm:"column(vendor_id)" json:"vendorID"` VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空 VendorActID string `orm:"column(vendor_act_id);size(48)" json:"vendorActID"` SyncStatus int `orm:"default(2)" json:"syncStatus"` Remark string `orm:"column(map_remark)" json:"remark"` } type ActVendorInfo struct { model.Act VendorList []*ActMapPureInfo `json:"vendorList"` } type tActAndMap struct { model.Act MapID int `orm:"column(map_id)" json:"-"` // 内部使用,不暴露 ActMapPureInfo } type PagedActListInfo struct { TotalCount int `json:"totalCount"` Data []*ActVendorInfo `json:"data"` } func GetActVendorInfo(db *DaoDB, actID int, vendorIDs []int) (actMap map[int]*model.Act2, err error) { leftOrEmpty := "" if len(vendorIDs) == 1 && vendorIDs[0] == -1 { leftOrEmpty = "LEFT" } sql := fmt.Sprintf(` SELECT t1.*, t2.id map_id, t2.vendor_id, t2.vendor_org_code, t2.vendor_act_id, t2.sync_status FROM act t1 %s JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ?`, leftOrEmpty) sqlParams := []interface{}{ utils.DefaultTimeValue, } if len(vendorIDs) > 0 { sql += " AND t2.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, vendorIDs) } sql += ` WHERE t1.deleted_at = ? AND t1.id = ?` sqlParams = append(sqlParams, utils.DefaultTimeValue, actID) var actList []*model.Act2 if err = GetRows(db, &actList, sql, sqlParams...); err == nil { actMap = make(map[int]*model.Act2) for _, v := range actList { if leftOrEmpty != "" { v.VendorID = -1 } actMap[v.VendorID] = v } } return actMap, err } func GetActStoreSkuVendorList(db *DaoDB, actID int, vendorIDs, storeIDs, skuIDs []int, keyword string, offset, pageSize int) (totalCount int, actStoreSkuList []*model.ActStoreSku2, err error) { globals.SugarLogger.Debugf("GetActStoreSkuVendorList actID:%d", actID) offset = jxutils.FormalizePageOffset(offset) pageSize = jxutils.FormalizePageSize(pageSize) leftOrEmpty := "" jdVendorIDField := "t4.jd_id" if len(vendorIDs) == 1 && (vendorIDs[0] == -1 || vendorIDs[0] == model.VendorIDJX) { leftOrEmpty = "LEFT" } if globals.IsUseThingMap { jdVendorIDField = "t4m.vendor_thing_id" } sql := fmt.Sprintf(` SELECT SQL_CALC_FOUND_ROWS t1.*, t2.id map_id, t2.vendor_id, t2.vendor_act_id, t2.sync_status, t2.actual_act_price, t2.vendor_price, t3.vendor_store_id, CASE t2.vendor_id WHEN 0 THEN %s WHEN 1 THEN t5.mtwm_id WHEN 3 THEN t5.ebai_id ELSE '' END vendor_sku_id, t4.comment, t4.spec_quality, t4.spec_unit, t6.name store_name, t7.name sku_name_name, t7.unit, t7.prefix, t7.ex_prefix, t7.ex_prefix_begin, t7.ex_prefix_end FROM act_store_sku t1 %s JOIN act_store_sku_map t2 ON t2.act_id = ? AND t2.bind_id = t1.id AND t2.deleted_at = ?`, jdVendorIDField, leftOrEmpty) sqlParams := []interface{}{ actID, utils.DefaultTimeValue, } if len(vendorIDs) > 0 { sql += " AND t2.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, vendorIDs) } sql += ` LEFT JOIN store_map t3 ON t3.store_id = t1.store_id AND t3.vendor_id = t2.vendor_id AND t3.deleted_at = ? JOIN sku t4 ON t4.id = t1.sku_id` sqlParams = append(sqlParams, utils.DefaultTimeValue) if globals.IsUseThingMap { sql += ` LEFT JOIN thing_map t4m ON t4m.thing_id = t4.id AND t4m.thing_type = ? AND t4m.vendor_id = t2.vendor_id AND t4m.vendor_org_code = t3.vendor_org_code AND t4m.deleted_at = ?` sqlParams = append(sqlParams, model.ThingTypeSku, utils.DefaultTimeValue) } sql += ` LEFT JOIN store_sku_bind t5 ON t5.sku_id = t1.sku_id AND t5.store_id = t1.store_id AND t5.deleted_at = ? LEFT JOIN store t6 ON t6.id = t1.store_id JOIN sku_name t7 ON t7.id = t4.name_id WHERE t1.act_id = ? ` sqlParams = append(sqlParams, utils.DefaultTimeValue, actID, ) if keyword != "" { keywordLike := "%" + keyword + "%" sql += " AND (t7.name LIKE ? OR t6.name LIKE ?" sqlParams = append(sqlParams, keywordLike, keywordLike) if intKeyword := int(utils.Str2Int64WithDefault(keyword, 0)); intKeyword > 0 { sql += " OR t1.sku_id = ? OR t1.store_id = ?" sqlParams = append(sqlParams, intKeyword, intKeyword) } sql += ")" } if leftOrEmpty != "" { sql += " AND t1.deleted_at = ?" sqlParams = append(sqlParams, utils.DefaultTimeValue) } if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } sql += " LIMIT ? OFFSET ?;" sqlParams = append(sqlParams, pageSize, offset) // globals.SugarLogger.Debug(sql) // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) // globals.SugarLogger.Debug(utils.Format4Output(actStoreSkuList, false)) Begin(db) defer Rollback(db) if err = GetRows(db, &actStoreSkuList, sql, sqlParams...); err == nil { totalCount = GetLastTotalRowCount(db) } return totalCount, actStoreSkuList, err } func GetActStoreSkuVendorInfo(db *DaoDB, actID int, vendorIDs, storeIDs, skuIDs []int) (actStoreSkuMap map[int][]*model.ActStoreSku2, err error) { leftOrEmpty := "" if len(vendorIDs) == 1 && vendorIDs[0] == -1 { leftOrEmpty = "LEFT" } _, actStoreSkuList, err := GetActStoreSkuVendorList(db, actID, vendorIDs, storeIDs, skuIDs, "", 0, -1) if err == nil { actStoreSkuMap = make(map[int][]*model.ActStoreSku2) for _, v := range actStoreSkuList { if leftOrEmpty != "" { v.VendorID = -1 } actStoreSkuMap[v.VendorID] = append(actStoreSkuMap[v.VendorID], v) } } return actStoreSkuMap, err } func QueryActs(db *DaoDB, actID int, offset, pageSize int, syncStatus int, keyword string, vendorID int, statusList, actTypeList, createTypeList []int, storeID int, skuIDs []int, cityCode int, beginAt, endAt, createdAtFrom, createdAtTo time.Time) (pagedInfo *PagedActListInfo, err error) { if actID == 0 && utils.IsTimeZero(createdAtFrom) && utils.IsTimeZero(beginAt) { return nil, fmt.Errorf("actID,createdAtFrom和beginAt中,至少要指定一个条件") } offset = jxutils.FormalizePageOffset(offset) pageSize = jxutils.FormalizePageSize(pageSize) isGetAll := offset == 0 && pageSize == model.UnlimitedPageSize sql := ` SELECT SQL_CALC_FOUND_ROWS DISTINCT t1.id FROM act t1` sqlParams := []interface{}{} if isGetAll { sql = ` SELECT t1.*, t2.id map_id, t2.vendor_id, t2.vendor_act_id, t2.sync_status, t2.remark map_remark FROM act t1` } sql += " LEFT JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ?" sqlParams = append(sqlParams, utils.DefaultTimeValue) if syncStatus >= 0 { sql += " AND (t2.sync_status = ? OR t2.sync_status & ? <> 0)" sqlParams = append(sqlParams, syncStatus, syncStatus) } sql += ` WHERE t1.deleted_at = ?` if syncStatus >= 0 { sql += " AND t2.id IS NOT NULL" } sqlParams = append(sqlParams, utils.DefaultTimeValue) keywordInt := int64(0) if keyword != "" { keywordLike := "%" + keyword + "%" sql += " AND ( t1.name LIKE ? OR t1.advertising LIKE ? OR t1.remark LIKE ? OR t2.vendor_act_id LIKE ?" sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike) keywordInt = utils.Str2Int64WithDefault(keyword, 0) if keywordInt > 0 { sql += ` OR t1.id = ?` sqlParams = append(sqlParams, keywordInt) } sql += ")" } if storeID > 0 || len(skuIDs) > 0 || cityCode > 0 { sql += ` AND (SELECT COUNT(*) FROM act_store_sku t2` if cityCode > 0 { sql += " JOIN store t3 ON t3.id = t2.store_id AND t3.city_code = ?" sqlParams = append(sqlParams, cityCode) } sql += ` WHERE t2.act_id = t1.id AND t2.deleted_at = ?` sqlParams = append(sqlParams, utils.DefaultTimeValue) if storeID > 0 { sql += " AND t2.store_id = ?" sqlParams = append(sqlParams, storeID) } if len(skuIDs) > 0 { sql += " AND t2.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } sql += ") > 0" } if actID > 0 { sql += " AND t1.id = ?" sqlParams = append(sqlParams, actID) } if vendorID >= 0 { sql += " AND t1.vendor_mask & ? <> 0" sqlParams = append(sqlParams, model.GetVendorMask(vendorID)) } if len(statusList) > 0 { sql += " AND t1.status IN (" + GenQuestionMarks(len(statusList)) + ")" sqlParams = append(sqlParams, statusList) } if len(actTypeList) > 0 { sql += " AND t1.type IN (" + GenQuestionMarks(len(actTypeList)) + ")" sqlParams = append(sqlParams, actTypeList) } if len(createTypeList) > 0 { sql += " AND t1.create_type IN (" + GenQuestionMarks(len(createTypeList)) + ")" sqlParams = append(sqlParams, createTypeList) } if !utils.IsTimeZero(beginAt) { sql += " AND t1.begin_at <= ?" sqlParams = append(sqlParams, beginAt) } if !utils.IsTimeZero(endAt) { sql += " AND t1.end_at >= ?" sqlParams = append(sqlParams, endAt) } if !utils.IsTimeZero(createdAtFrom) { sql += " AND t1.created_at >= ?" sqlParams = append(sqlParams, createdAtFrom) } if !utils.IsTimeZero(createdAtTo) { sql += " AND t1.created_at <= ?" sqlParams = append(sqlParams, createdAtTo) } pagedInfo = &PagedActListInfo{} if isGetAll { sql += ` ORDER BY t1.id DESC, t2.vendor_id` } else { sql += ` ORDER BY 1 DESC LIMIT ? OFFSET ? ` sqlParams = append(sqlParams, pageSize, offset) var idList []int Begin(db) defer func() { if r := recover(); r != nil { Rollback(db) panic(r) } }() // globals.SugarLogger.Debug(sql) if err = GetRows(db, &idList, sql, sqlParams...); err != nil || len(idList) == 0 { Rollback(db) return pagedInfo, err } pagedInfo.TotalCount = GetLastTotalRowCount(db) Commit(db) sql = ` SELECT t1.*, t2.id map_id, t2.vendor_id, t2.vendor_org_code, t2.vendor_act_id, t2.sync_status, t2.remark map_remark FROM act t1 LEFT JOIN act_map t2 ON t2.act_id = t1.id AND t2.deleted_at = ? WHERE t1.id IN (` + GenQuestionMarks(len(idList)) + `)` if syncStatus >= 0 { sql += " AND t2.id IS NOT NULL" } sql += ` ORDER BY t1.id DESC, t2.vendor_id` sqlParams = []interface{}{ utils.DefaultTimeValue, idList, } } var actList []*tActAndMap // globals.SugarLogger.Debug(sql) if err = GetRows(db, &actList, sql, sqlParams...); err != nil { return nil, err } actMap := make(map[int]*ActVendorInfo) for _, v := range actList { tmpAct := actMap[v.ID] if tmpAct == nil { tmpAct = &ActVendorInfo{ Act: v.Act, } actMap[v.ID] = tmpAct pagedInfo.Data = append(pagedInfo.Data, tmpAct) } if v.MapID > 0 { tmpAct.VendorList = append(tmpAct.VendorList, &v.ActMapPureInfo) } } if isGetAll { pagedInfo.TotalCount = len(pagedInfo.Data) } return pagedInfo, err } func GetExistVendorActIDs(db *DaoDB, vendorID int) (vendorActIDs []string, err error) { // todo 不应该是全表扫描 sql := ` SELECT DISTINCT t1.vendor_act_id FROM act_store_sku_map t1 WHERE t1.deleted_at = ? AND t1.vendor_id = ?` sqlParams := []interface{}{ utils.DefaultTimeValue, vendorID, } err = GetRows(db, &vendorActIDs, sql, sqlParams...) return vendorActIDs, err } func GetEffectiveActStoreSkuInfo(db *DaoDB, actID int, vendorIDs []int, actType int, storeIDs, skuIDs []int, beginAt, endAt time.Time) (actStoreSkuList []*model.ActStoreSku2, err error) { if utils.IsTimeZero(beginAt) { return nil, fmt.Errorf("GeActStoreSkuInfo必须指定活动开始时间") } if utils.IsTimeZero(endAt) { endAt = beginAt } sql := ` SELECT t1.type, t2.*, t3.actual_act_price, t3.sync_status, t3.vendor_price, t3.vendor_id FROM act t1 JOIN act_store_sku t2 ON t2.act_id = t1.id AND t2.deleted_at = ? JOIN act_store_sku_map t3 ON t3.bind_id = t2.id AND t3.act_id = t1.id AND (t3.sync_status & ? = 0 OR t1.type = ?) JOIN act_map t4 ON t4.act_id = t1.id AND t4.vendor_id = t3.vendor_id AND t4.deleted_at = ? AND (t4.sync_status & ? = 0 OR t1.type = ?) WHERE t1.deleted_at = ? AND t1.status = ? AND NOT (t1.begin_at > ? OR t1.end_at < ?)` sqlParams := []interface{}{ utils.DefaultTimeValue, model.SyncFlagNewMask, model.ActSkuFake, utils.DefaultTimeValue, model.SyncFlagNewMask, model.ActSkuFake, utils.DefaultTimeValue, model.ActStatusCreated, endAt, beginAt, } if len(vendorIDs) > 0 { sql += " AND (t1.vendor_mask & ?) <> 0 AND t3.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, model.GetVendorMask(vendorIDs...), vendorIDs) } if actID > 0 { sql += " AND t1.id = ?" sqlParams = append(sqlParams, actID) } if actType != model.ActTypeAll { sql += " AND t1.type = ?" sqlParams = append(sqlParams, actType) } if len(storeIDs) > 0 { sql += " AND t2.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(skuIDs) > 0 { sql += " AND t2.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } // globals.SugarLogger.Debug(sql) // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) err = GetRows(db, &actStoreSkuList, sql, sqlParams...) return actStoreSkuList, err } func UpdateActStatusByTime(db *DaoDB, refTime time.Time) (num int64, err error) { sql := ` UPDATE act t1 SET t1.status = ? WHERE t1.deleted_at = ? AND t1.status < ? AND t1.end_at < ?;` sqlParams := []interface{}{ model.ActStatusEnded, utils.DefaultTimeValue, model.ActStatusCanceled, utils.Time2Date(refTime), } num, err = ExecuteSQL(db, sql, sqlParams...) return num, err } // func ActStoreSkuMap2StoreSkuAct(actStoreSkuMap *model.ActStoreSkuMap, isCanceled bool) (storeSkuAct *model.StoreSkuAct) { // storeSkuAct = &model.StoreSkuAct{ // StoreID: actStoreSkuMap.StoreID, // SkuID: actStoreSkuMap.SkuID, // VendorID: actStoreSkuMap.VendorID, // } // storeSkuAct.CreatedAt = actStoreSkuMap.CreatedAt // storeSkuAct.UpdatedAt = actStoreSkuMap.UpdatedAt // storeSkuAct.LastOperator = actStoreSkuMap.LastOperator // if actStoreSkuMap.ActualActPrice > 0 { // if isCanceled || !utils.IsTimeZero(actStoreSkuMap.DeletedAt) { // storeSkuAct.ActID = 0 // } else { // storeSkuAct.ActID = actStoreSkuMap.ActID // storeSkuAct.VendorActID = actStoreSkuMap.VendorActID // storeSkuAct.SyncStatus = actStoreSkuMap.SyncStatus // storeSkuAct.VendorPrice = actStoreSkuMap.VendorPrice // storeSkuAct.ActualActPrice = actStoreSkuMap.ActualActPrice // } // } // if actStoreSkuMap.EarningPrice > 0 { // if isCanceled || !utils.IsTimeZero(actStoreSkuMap.DeletedAt) { // storeSkuAct.EarningActID = 0 // } else { // storeSkuAct.EarningActID = actStoreSkuMap.ActID // storeSkuAct.EarningPrice = actStoreSkuMap.EarningPrice // } // } // return storeSkuAct // } func BatchUpdateActEntity(db *DaoDB, isCanceled bool, items []*KVUpdateItem) (num int64, err error) { return BatchUpdateEntityByKV(db, items) // if globals.IsStoreSkuAct { // Begin(db) // defer func() { // if r := recover(); r != nil || err != nil { // Rollback(db) // if r != nil { // panic(r) // } // } // }() // for _, v := range items { // if actStoreSku, ok := v.Item.(*model.ActStoreSkuMap); ok { // for k1, v1 := range v.KVs { // refutil.SetObjFieldByName(actStoreSku, k1, v1) // } // if err = CreateOrUpdateActStoreSku(db, ActStoreSkuMap2StoreSkuAct(actStoreSku, isCanceled)); err != nil { // return 0, err // } // } // } // } // if _, err = BatchUpdateEntityByKV(db, items); err != nil { // return 0, err // } // if globals.IsStoreSkuAct { // Commit(db) // } // return num, err } func CreateOrUpdateActStoreSku(db *DaoDB, storeSkuAct *model.StoreSkuAct) (err error) { storeSkuActCopy := *storeSkuAct if err2 := GetEntity(db, &storeSkuActCopy, model.FieldStoreID, model.FieldSkuID, model.FieldVendorID); err2 == nil { storeSkuAct.ID = storeSkuActCopy.ID _, err = UpdateEntity(db, storeSkuAct) } else if IsNoRowsError(err2) { err = CreateEntity(db, storeSkuAct) } else { err = err2 } return err } func GetStoresSkusAct(db *DaoDB, storeIDs, skuIDs, vendorIDs []int, minActPercentage, maxActPercentage int) (storeSkuActList []*model.StoreSkuAct, err error) { sql := ` SELECT * FROM store_sku_act t1 WHERE 1 = 1 ` sqlParams := []interface{}{} if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } if len(vendorIDs) > 0 { sql += " AND t1.vendor_id IN (" + GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, vendorIDs) } if minActPercentage > 0 { sql += " AND t1.act_percentage >= ?" sqlParams = append(sqlParams, minActPercentage) } if maxActPercentage > 0 { sql += " AND t1.act_percentage <= ?" sqlParams = append(sqlParams, maxActPercentage) } err = GetRows(db, &storeSkuActList, sql, sqlParams...) return storeSkuActList, err } func GetStoresSkusAndActInfo(db *DaoDB, storeIDs, skuIDs, vendorIDs []int, minActPercentage, maxActPercentage int) (storeSkuAndActList []*StoreSkuAndAct, err error) { storeSkuList, err := GetStoresSkusInfo(db, storeIDs, skuIDs) if err == nil && len(storeSkuList) > 0 { storeSkuActList, err2 := GetStoresSkusAct(db, storeIDs, skuIDs, vendorIDs, minActPercentage, maxActPercentage) if err = err2; err == nil { actMap := make(map[int64][]*model.StoreSkuAct) for _, v := range storeSkuActList { actMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = append(actMap[jxutils.Combine2Int(v.StoreID, v.SkuID)], v) } for _, v := range storeSkuList { storeSkuAct := &StoreSkuAndAct{ StoreSkuBind: v, ActMap: make(map[int]*model.StoreSkuAct), } for _, vv := range actMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] { storeSkuAct.ActMap[vv.VendorID] = vv } storeSkuAndActList = append(storeSkuAndActList, storeSkuAct) } } } return storeSkuAndActList, err } // func GetConflictStoreSkuActInfo(db *DaoDB, vendorIDs []int, inStoreSkuActList []*model.StoreSkuAct) (outStoreSkuActList []*model.StoreSkuAct, err error) { // storeIDMap := make(map[int]int) // skuIDMap := make(map[int]int) // inStoreSkuActMap := make(map[int64]*model.StoreSkuAct) // for _, v := range inStoreSkuActList { // storeIDMap[v.StoreID] = 1 // skuIDMap[v.SkuID] = 1 // inStoreSkuActMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] = v // } // storeIDs := jxutils.IntMap2List(storeIDMap) // skuIDs := jxutils.IntMap2List(skuIDMap) // sql := ` // SELECT * // FROM store_sku_act t1 // WHERE // t1.store_id IN (` + GenQuestionMarks(len(storeIDs)) + `) // AND t1.sku_id IN (` + GenQuestionMarks(len(skuIDs)) + `) // ` // sqlParams := []interface{}{ // storeIDs, // skuIDs, // } // if len(vendorIDs) > 0 { // sql += ` AND t1.vendor_Id IN (` + GenQuestionMarks(len(storeIDs)) + `)` // sqlParams = append(sqlParams, vendorIDs) // } // var tmpStoreSkuActList []*model.StoreSkuAct // if err = GetRows(db, &tmpStoreSkuActList, sql, sqlParams...); err == nil { // for _, v := range tmpStoreSkuActList { // tmpStoreSkuAct := inStoreSkuActMap[jxutils.Combine2Int(v.StoreID, v.SkuID)] // if tmpStoreSkuAct != nil && (tmpStoreSkuAct.ActualActPrice > 0 && v.ActID != 0 && v.SyncStatus == 0 || tmpStoreSkuAct.EarningPrice > 0 && v.EarningActID != 0) { // outStoreSkuActList = append(outStoreSkuActList, v) // } // } // } // return outStoreSkuActList, err // }