Files
jx-callback/business/jxstore/cms/sku.go
2020-04-08 09:49:17 +08:00

1743 lines
52 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 cms
import (
"errors"
"fmt"
"io"
"mime/multipart"
"strconv"
"strings"
"time"
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
"git.rosy.net.cn/baseapi/platformapi/ebaiapi"
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/baseapi/platformapi/jdapi"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/baseapi/utils/errlist"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/datares"
"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/globals"
)
type SkuNamesInfo struct {
TotalCount int `json:"totalCount"`
SkuNames []*model.SkuNameExt `json:"skuNames"`
}
var (
ErrInputCatsDoesntMatch = errors.New("输入的类别列表不合法需要输入一个父ID下的所有子类别")
)
var (
ebaiUploadRTFShopID string // 饿百找一个店用于调用SkuUploadRTF
)
var (
sendNoCatSkusMobile = []string{
"18048531223",
"18982250714",
}
)
// func getAndSetEbaiUploadRTFShopID() (shopID string) {
// if ebaiUploadRTFShopID == "" {
// if storeDetail, err := dao.GetStoreDetail(dao.GetDB(), 0, model.VendorIDEBAI); err == nil {
// ebaiUploadRTFShopID = utils.Int2Str(storeDetail.Store.ID)
// }
// }
// return ebaiUploadRTFShopID
// }
// parentID 为-1表示所有
func GetVendorCategories(ctx *jxcontext.Context, vendorID int, parentID string) (vendorCats []*model.SkuVendorCategory, err error) {
cond := map[string]interface{}{
model.FieldVendorID: vendorID,
}
if parentID != "-1" {
cond[model.FieldParentID] = parentID
}
return vendorCats, dao.GetEntitiesByKV(nil, &vendorCats, cond, false)
}
// parentID 为-1表示所有
func GetCategories(ctx *jxcontext.Context, parentID int, isExd bool) (catList []*dao.SkuCategoryWithVendor, err error) {
db := dao.GetDB()
cats, err := dao.GetCategories(db, parentID, 0, nil, isExd)
if err == nil {
var ids []int
for _, v := range cats {
ids = append(ids, v.ID)
}
thingMapMap, err2 := dao.GetThingMapMap(db, model.ThingTypeCategory, nil, ids)
// globals.SugarLogger.Debug(utils.Format4Output(thingMapMap, false))
if err = err2; err == nil {
for _, v := range cats {
catList = append(catList, &dao.SkuCategoryWithVendor{
SkuCategory: v,
MapList: thingMapMap[int64(v.ID)],
})
}
}
}
return catList, err
}
func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string) (outCat *model.SkuCategory, err error) {
db := dao.GetDB()
if cat.Level < 0 || cat.Level > 2 {
return nil, errors.New("Level必须为1或2")
} else if cat.Level == 1 && cat.ParentID != 0 {
return nil, errors.New("Level1的分类其父分类必须为0")
} else if cat.Level == 2 {
if cat.ParentID == 0 {
return nil, errors.New("Level2的分类其父分类必须不为0")
}
parentCat := &model.SkuCategory{}
parentCat.ID = cat.ParentID
if err = dao.GetEntity(db, parentCat); err != nil {
return nil, err
}
if parentCat.Level != 1 {
return nil, errors.New("Level2的分类其父分类必须为Level1分类")
}
}
dao.WrapAddIDCULDEntity(cat, userName)
// cat.JdSyncStatus = model.SyncFlagNewMask
// cat.JdID = 0
cat.Status = model.CategoryStatusEnable
cat.Name = strings.Trim(cat.Name, " ")
if cat.Img != "" {
_, err2 := datares.TryRegisterDataResource(ctx, cat.Name, cat.Img, model.ImgTypeLocal, false)
if err = err2; err != nil {
return nil, err
}
}
if cat.Seq <= 0 {
var maxSeq struct {
MaxSeq int
}
if err = dao.GetRow(db, &maxSeq, "SELECT MAX(seq) max_seq FROM sku_category t1 WHERE level = ?", cat.Level); err != nil {
return nil, err
}
cat.Seq = maxSeq.MaxSeq + 1
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if err = dao.CreateEntity(db, cat); err != nil {
dao.Rollback(db)
return nil, err
}
if cat.IsExdSpec == model.NO {
if err = OnCreateThing(ctx, db, nil, int64(cat.ID), model.ThingTypeCategory); err != nil {
dao.Rollback(db)
return nil, err
}
}
dao.Commit(db)
outCat = cat
_, err = CurVendorSync.SyncCategory(ctx, nil, cat.ID, false, userName)
return outCat, err
}
func UpdateCategory(ctx *jxcontext.Context, categoryID int, payload map[string]interface{}, userName string) (num int64, err error) {
cat := &model.SkuCategory{}
cat.ID = categoryID
db := dao.GetDB()
if err = dao.GetEntity(db, cat); err != nil {
return 0, err
}
for k, v := range payload {
if v == nil {
delete(payload, k)
}
}
valid := dao.StrictMakeMapByStructObject(payload, cat, userName)
if len(valid) > 0 {
// syncStatus := 0
// if valid["name"] != nil {
// valid["name"] = strings.Trim(valid["name"].(string), " ")
// syncStatus = model.SyncFlagModifiedMask
// valid[model.FieldJdSyncStatus] = int8(syncStatus) | cat.JdSyncStatus
// }
if valid["status"] != nil {
if utils.Interface2Int64WithDefault(valid["status"], -1) == model.CategoryStatusDisabled {
if skuList, err2 := dao.GetSkuByCats(db, []int{categoryID}); err2 == nil && len(skuList) > 0 {
return 0, fmt.Errorf("暂不允许禁用分类下有商品的分类!")
}
}
}
if valid["img"] != nil {
if imgStr := utils.Interface2String(valid["img"]); imgStr != "" {
_, err2 := datares.TryRegisterDataResource(ctx, cat.Name, utils.Interface2String(valid["img"]), model.ImgTypeLocal, false)
if err = err2; err != nil {
return 0, err
}
}
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if num, err = dao.UpdateEntityLogically(db, cat, valid, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
if cat.IsExdSpec == model.NO {
if err = OnUpdateThing(ctx, db, nil, int64(categoryID), model.ThingTypeCategory); err != nil {
dao.Rollback(db)
return 0, err
}
}
dao.Commit(db)
SetStoreCategorySyncStatus2(db, nil, []int{categoryID}, model.SyncFlagModifiedMask)
var skuIDs []int
if valid["jdCategoryID"] != nil || valid["ebaiCategoryID"] != nil || valid["mtwmCategoryID"] != nil ||
valid["jdPricePercentage"] != nil || valid["ebaiPricePercentage"] != nil || valid["mtwmPricePercentage"] != nil {
if skuList, err2 := dao.GetSkuByCats(db, []int{categoryID}); err2 == nil && len(skuList) > 0 {
for _, sku := range skuList {
skuIDs = append(skuIDs, sku.ID)
}
if valid["jdCategoryID"] != nil {
dao.SetSkuSyncStatus(db, model.VendorIDJD, skuIDs, model.SyncFlagModifiedMask)
}
// todo 如下逻辑在不同平台同时改pricePercentage与平台分类映射时会不必要的打上多余的标记
var vendorIDs []int
syncStatus := model.SyncFlagModifiedMask
if valid["jdPricePercentage"] != nil {
vendorIDs = append(vendorIDs, model.VendorIDJD)
syncStatus |= model.SyncFlagPriceMask
}
if valid["ebaiPricePercentage"] != nil {
vendorIDs = append(vendorIDs, model.VendorIDEBAI)
syncStatus |= model.SyncFlagPriceMask
} else if valid["ebaiCategoryID"] != nil {
vendorIDs = append(vendorIDs, model.VendorIDEBAI)
}
if valid["mtwmPricePercentage"] != nil {
vendorIDs = append(vendorIDs, model.VendorIDMTWM)
syncStatus |= model.SyncFlagPriceMask
} else if valid["mtwmCategoryID"] != nil {
vendorIDs = append(vendorIDs, model.VendorIDMTWM)
}
if len(vendorIDs) > 0 {
SetStoreSkuSyncStatus2(db, nil, vendorIDs, skuIDs, syncStatus)
}
}
}
_, err = CurVendorSync.SyncCategory(ctx, db, categoryID, false, userName)
if len(skuIDs) > 0 {
CurVendorSync.SyncSkus(ctx, db, nil, skuIDs, true, true, userName)
}
}
return num, err
}
func SetStoreCategorySyncStatus2(db *dao.DaoDB, storeIDs []int, catIDs []int, syncStatus int) (num int64, err error) {
for _, vendorID := range partner.GetSingleStoreVendorIDs() {
num2, err2 := dao.SetStoreCategorySyncStatus(db, vendorID, storeIDs, catIDs, syncStatus)
if err = err2; err != nil {
return 0, err
}
num += num2
}
return num, nil
}
func ReorderCategories(ctx *jxcontext.Context, parentID int, categoryIDs []int, userName string, isExd bool) (err error) {
var cats []*model.SkuCategory
db := dao.GetDB()
if err = dao.GetEntitiesByKV(db, &cats, utils.Params2Map(model.FieldParentID, parentID), false); err == nil {
catsLen := len(cats)
if !isExd {
for _, v := range cats {
if v.IsExdSpec == 1 {
catsLen--
}
}
}
if catsLen != len(categoryIDs) {
return ErrInputCatsDoesntMatch
}
catsMap := make(map[int]*model.SkuCategory, catsLen)
for _, cat := range cats {
catsMap[cat.ID] = cat
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
for k, v := range categoryIDs {
if catsMap[v] == nil {
dao.Rollback(db)
return fmt.Errorf("分类:%d不在%d分类下", v, parentID)
}
if isExd {
catsMap[v].ExdSeq = k
} else {
catsMap[v].Seq = k
}
catsMap[v].LastOperator = ctx.GetUserName()
if _, err = dao.UpdateEntity(db, catsMap[v]); err != nil {
dao.Rollback(db)
return err
}
if catsMap[v].IsExdSpec == model.NO {
if err = OnUpdateThing(ctx, db, nil, int64(catsMap[v].ID), model.ThingTypeCategory); err != nil {
dao.Rollback(db)
return err
}
}
}
dao.Commit(db)
SetStoreCategorySyncStatus2(db, nil, categoryIDs, model.SyncFlagModifiedMask)
if err == nil {
_, err = CurVendorSync.SyncReorderCategories(ctx, db, parentID, false, userName)
CurVendorSync.SyncStoresCategory(ctx, db, nil, nil, false, true, true)
}
}
return err
}
func DeleteCategory(ctx *jxcontext.Context, categoryID int, userName string) (num int64, err error) {
cat := &model.SkuCategory{}
cat.ID = categoryID
var countInfos []*struct{ Ct int }
db := dao.GetDB()
if err = dao.GetRows(db, &countInfos, `
SELECT COUNT(*) ct
FROM sku t1
WHERE t1.category_id = ? AND t1.deleted_at = ?
UNION ALL
SELECT COUNT(*) ct
FROM sku_name t1
WHERE t1.category_id = ? AND t1.deleted_at = ?
UNION ALL
SELECT COUNT(*) ct
FROM sku_category t1
WHERE t1.parent_id = ? AND t1.deleted_at = ?
`, categoryID, utils.DefaultTimeValue, categoryID, utils.DefaultTimeValue, categoryID, utils.DefaultTimeValue, &countInfos); err == nil {
if countInfos[0].Ct != 0 {
return 0, errors.New("还有商品使用此类别,不能删除")
} else if countInfos[1].Ct != 0 {
return 0, errors.New("还有商品名使用此类别,不能删除")
} else if countInfos[2].Ct != 0 {
return 0, errors.New("还有商品类别使用此类别,不能删除")
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if _, err = DeleteCategoryMap(ctx, db, categoryID); err != nil {
dao.Rollback(db)
return 0, err
}
if err = OnDeleteThing(ctx, db, nil, int64(categoryID), model.ThingTypeCategory); err != nil {
dao.Rollback(db)
return 0, err
}
if num, err = dao.DeleteEntityLogically(db, cat, map[string]interface{}{
// model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
model.FieldStatus: 0,
}, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
dao.Commit(db)
_, err = CurVendorSync.SyncCategory(ctx, db, cat.ID, false, userName)
}
return num, err
}
func DeleteCategoryMap(ctx *jxcontext.Context, db *dao.DaoDB, categoryID int) (num int64, err error) {
if db == nil {
db = dao.GetDB()
}
catMap := &model.StoreSkuCategoryMap{}
return dao.DeleteEntityLogically(db, catMap, map[string]interface{}{
model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask,
model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask,
}, ctx.GetUserName(), map[string]interface{}{
model.FieldCategoryID: categoryID,
model.FieldDeletedAt: utils.DefaultTimeValue,
})
}
func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params map[string]interface{}, offset, pageSize int) (skuNamesInfo *SkuNamesInfo, err error) {
db := dao.GetDB()
sql := `
FROM sku_name t1
LEFT JOIN sku t2 ON t1.id = t2.name_id AND t2.deleted_at = ?
LEFT JOIN sku_name_place_bind t3 ON t1.id = t3.name_id
LEFT JOIN price_refer_snapshot t4 ON t4.city_code = ? AND t4.snapshot_at = ? AND t4.sku_id = t2.id
WHERE t1.deleted_at = ?`
sqlParams := []interface{}{
utils.DefaultTimeValue,
0, utils.Time2Date(time.Now().AddDate(0, 0, -1)),
utils.DefaultTimeValue,
}
if keyword != "" {
keywordLike := "%" + keyword + "%"
sql += `
AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t2.comment LIKE ? OR t1.upc LIKE ?
OR (SELECT COUNT(*) FROM thing_map tm WHERE tm.vendor_thing_id LIKE ? AND tm.thing_type = ? AND tm.thing_id = t2.id AND tm.deleted_at = ?) > 0`
sqlParams = append(sqlParams,
keywordLike, keywordLike, keywordLike, keywordLike,
keywordLike, model.ThingTypeSku, utils.DefaultTimeValue)
if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil {
sql += " OR t1.id = ? OR t2.id = ? OR t1.category_id = ?"
sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64)
}
sql += ")"
}
if params["isSpu"] != nil {
sql += " AND t1.is_spu = ?"
sqlParams = append(sqlParams, utils.Bool2Int(params["isSpu"].(bool)))
}
if params["nameID"] != nil {
sql += " AND t1.id = ?"
sqlParams = append(sqlParams, params["nameID"].(int))
}
if params["nameIDs"] != nil {
var nameIDs []int
if ids, ok := params["nameIDs"].([]int); ok {
nameIDs = ids
} else {
if err = utils.UnmarshalUseNumber([]byte(params["nameIDs"].(string)), &nameIDs); err != nil {
return nil, err
}
}
if len(nameIDs) > 0 {
sql += " AND t1.id IN (" + dao.GenQuestionMarks(len(nameIDs)) + ")"
sqlParams = append(sqlParams, nameIDs)
}
}
if params["isExd"] != nil {
var idExd = params["isExd"].(bool)
if idExd {
sql += " AND t2.exd_sku_id <> ''"
} else {
sql += " AND t2.exd_sku_id = ''"
}
} else {
sql += " AND t2.exd_sku_id = ''"
}
if params["categoryID"] != nil {
cat := &model.SkuCategory{}
cat.ID = params["categoryID"].(int)
if err = dao.GetEntity(db, cat); err != nil {
return nil, err
}
sql += " AND (t1.category_id = ?"
sqlParams = append(sqlParams, cat.ID)
if cat.Level == 1 {
sql += " OR t1.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)"
sqlParams = append(sqlParams, cat.ID)
}
sql += ")"
}
if params["skuCategoryID"] != nil {
cat := &model.SkuCategory{}
cat.ID = params["skuCategoryID"].(int)
if err = dao.GetEntity(db, cat); err != nil {
return nil, err
}
sql += " AND (t2.category_id = ?"
sqlParams = append(sqlParams, cat.ID)
if cat.Level == 1 {
sql += " OR t2.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)"
sqlParams = append(sqlParams, cat.ID)
}
sql += ")"
}
if params["vendorSkuIDs"] != nil {
var vendorSkuIDs []int
if err = utils.UnmarshalUseNumber([]byte(params["vendorSkuIDs"].(string)), &vendorSkuIDs); err != nil {
return nil, err
}
if len(vendorSkuIDs) > 0 {
sql += " AND (SELECT COUNT(*) FROM thing_map tm WHERE tm.thing_type = ? AND tm.thing_id = t2.id AND tm.deleted_at = ? AND tm.vendor_thing_id IN (" + dao.GenQuestionMarks(len(vendorSkuIDs)) + ")) > 0"
sqlParams = append(sqlParams, utils.DefaultTimeValue, vendorSkuIDs)
}
}
if params["name"] != nil {
sql += " AND t1.name LIKE ?"
sqlParams = append(sqlParams, "%"+params["name"].(string)+"%")
}
if params["prefix"] != nil {
sql += " AND t1.prefix LIKE ?"
sqlParams = append(sqlParams, "%"+params["prefix"].(string)+"%")
}
if params["unit"] != nil {
sql += " AND t1.unit = ?"
sqlParams = append(sqlParams, params["unit"].(string))
}
if placeCond := strings.ToUpper(utils.Interface2String(params["placeCond"])); placeCond == "AND" || placeCond == "OR" {
sqlPlaceCond := ""
if placeCond == "AND" {
sqlPlaceCond += " AND ( 1 = 1"
} else {
sqlPlaceCond += " AND ( 1 = 0"
}
if params["placeCode"] != nil {
sqlPlaceCond += " " + placeCond + " t3.place_code = ?"
sqlParams = append(sqlParams, params["placeCode"].(int))
}
if params["isGlobal"] != nil {
if params["isGlobal"].(bool) {
sqlPlaceCond += " " + placeCond + " t1.is_global = 1"
} else {
sqlPlaceCond += " " + placeCond + " t1.is_global = 0"
}
}
if sqlPlaceCond != " AND ( 1 = 0" {
sql += sqlPlaceCond + ")"
}
}
if params["skuID"] != nil {
sql += " AND t2.id = ?"
sqlParams = append(sqlParams, params["skuID"].(int))
}
if params["skuIDs"] != nil {
var skuIDs []int
if err = utils.UnmarshalUseNumber([]byte(params["skuIDs"].(string)), &skuIDs); err != nil {
return nil, err
}
if len(skuIDs) > 0 {
sql += " AND t2.id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")"
sqlParams = append(sqlParams, skuIDs)
}
}
if params["fromStatus"] != nil {
fromStatus := params["fromStatus"].(int)
toStatus := fromStatus
if params["toStatus"] != nil {
toStatus = params["toStatus"].(int)
}
sql += " AND t2.status >= ? AND t2.status <= ?"
sqlParams = append(sqlParams, fromStatus, toStatus)
}
sql += `
GROUP BY
t1.id,
t1.created_at,
t1.updated_at,
t1.last_operator,
t1.deleted_at,
t1.prefix,
t1.name,
t1.brand_id,
t1.category_id,
t1.jd_category_id,
t1.is_global,
t1.unit,
t1.price,
t1.img,
t1.img2,
t1.status,
t1.is_spu,
t1.desc_img,
t1.upc,
t1.ex_prefix,
t1.ex_prefix_begin,
t1.ex_prefix_end,
t1.yb_name_suffix,
t4.mid_unit_price`
if isBySku {
sql += `,
t2.id`
}
sqlData := `
SELECT
SQL_CALC_FOUND_ROWS
t1.id,
t1.created_at,
t1.updated_at,
t1.last_operator,
t1.deleted_at,
t1.prefix,
t1.name,
t1.brand_id,
t1.category_id,
t1.jd_category_id,
t1.is_global,
t1.unit,
t1.price,
t1.img,
t1.img2,
t1.status,
t1.is_spu,
t1.desc_img,
t1.upc,
/*
t1.jd_id,
t1.jd_sync_status,
*/
t1.ex_prefix,
t1.ex_prefix_begin,
t1.ex_prefix_end,
t1.yb_name_suffix,
t4.mid_unit_price,
CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t2.id, ',"comment":"', t2.comment, '","status":', t2.status,
',"createdAt":"', CONCAT(REPLACE(t2.created_at," ","T"),"+08:00"), '","updatedAt":"', CONCAT(REPLACE(t2.updated_at," ","T"),"+08:00"),
'","lastOperator":"', t2.last_operator, '","specQuality":', t2.spec_quality, ',"specUnit":"', t2.spec_unit,
'","exdSkuID":"', t2.exd_sku_id,
'","eclpID":"', t2.eclp_id,
'","weight":', t2.weight, ',"categoryID":', t2.category_id, ',"nameID":', t2.name_id,
', "seq":', t2.seq,
"}")), "]") skus_str,
CONCAT("[", GROUP_CONCAT(DISTINCT t3.place_code), "]") places_str
` + sql + `
ORDER BY MIN(t2.seq), t1.id DESC
LIMIT ? OFFSET ?`
pageSize = jxutils.FormalizePageSize(pageSize)
offset = jxutils.FormalizePageOffset(offset)
sqlParams = append(sqlParams, pageSize, offset)
skuNamesInfo = &SkuNamesInfo{}
dao.Begin(db) // todo 这里用事务的原因是SQL_CALC_FOUND_ROWS会出错
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
// globals.SugarLogger.Debug(sqlData)
// globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false))
if err = dao.GetRows(db, &skuNamesInfo.SkuNames, sqlData, sqlParams...); err == nil {
skuNamesInfo.TotalCount = dao.GetLastTotalRowCount(db)
dao.Commit(db)
var skuIDs []int
for _, skuName := range skuNamesInfo.SkuNames {
skuName.FullName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, "", "", 0, "", 0, skuName.ExPrefix, skuName.ExPrefixBegin, skuName.ExPrefixEnd)
if skuName.SkusStr != "" {
if err = utils.UnmarshalUseNumber([]byte(skuName.SkusStr), &skuName.Skus); err != nil {
dao.Rollback(db)
return nil, err
}
for _, v := range skuName.Skus {
skuIDs = append(skuIDs, v.ID)
}
}
if skuName.PlacesStr != "" {
if err = utils.UnmarshalUseNumber([]byte(skuName.PlacesStr), &skuName.Places); err != nil {
dao.Rollback(db)
return nil, err
}
}
}
if len(skuIDs) > 0 {
thingMapMap, err2 := dao.GetThingMapMap(db, model.ThingTypeSku, nil, skuIDs)
if err = err2; err == nil {
for _, skuName := range skuNamesInfo.SkuNames {
for _, v := range skuName.Skus {
v.MapList = thingMapMap[int64(v.ID)]
}
}
}
}
} else {
dao.Rollback(db)
}
return skuNamesInfo, err
}
func CheckHasSensitiveWord(word string) (bool, error) {
if hasSensitiveWord, sensitiveWord := IsSensitiveWordInList(word); hasSensitiveWord {
return true, errors.New(fmt.Sprintf("不能包含敏感词:[%s]", sensitiveWord))
}
return false, nil
}
func IsSensitiveWordInList(str string) (bool, string) {
wordList, err := dao.GetSensitiveWordList()
if err == nil {
for _, value := range wordList {
keyWord := value.Word
checkHas := strings.Contains(str, keyWord)
if checkHas {
return true, keyWord
}
}
}
return false, ""
}
func AddSkuName(ctx *jxcontext.Context, skuNameExt *model.SkuNameExt, userName string) (outSkuNameExt *model.SkuNameExt, err error) {
if skuNameExt.CategoryID == 0 {
return nil, errors.New("CategoryID不能为空")
}
if len(skuNameExt.Skus) == 0 {
return nil, errors.New("创建SKU NAME时必须至少创建一个SKU")
} else if skuNameExt.Unit != model.SpecialUnit {
if len(skuNameExt.Skus) != 1 {
return nil, errors.New("不为份的SKU NAME只能有一个SKU")
}
}
skuNameExt.Name = utils.TrimBlankChar(skuNameExt.Name)
if hasSensitiveWord, err := CheckHasSensitiveWord(skuNameExt.Name); hasSensitiveWord {
return nil, err
}
upc := utils.Pointer2String(skuNameExt.Upc)
if upc == "" {
skuNameExt.Upc = nil
} else if !jxutils.IsUpcValid(upc) {
return nil, fmt.Errorf("upc:%s不合法请仔细检查", upc)
}
db := dao.GetDB()
skuNameExt.SkuName.Status = model.SkuStatusNormal
if skuNameExt.IsSpu == 1 {
return nil, fmt.Errorf("不允许创建多规格商品")
// skuNameExt.SkuName.JdSyncStatus = model.SyncFlagNewMask
}
if skuNameExt.Unit == model.SpecialUnit {
skuNameExt.SpecQuality = float32(model.SpecialSpecQuality)
skuNameExt.SpecUnit = model.SpecialSpecUnit
} else {
skuNameExt.SpecQuality = skuNameExt.Skus[0].SpecQuality
skuNameExt.SpecUnit = skuNameExt.Skus[0].SpecUnit
}
if skuNameExt.YbNameSuffix == "" {
var name *model.SkuName
sql := "SELECT * FROM sku_name WHERE yb_name_suffix <> '' ORDER BY yb_name_suffix DESC LIMIT 1"
dao.GetRow(db, &name, sql, nil)
if name != nil {
prefix := utils.Int64ToStr(utils.Str2Int64(name.YbNameSuffix) + 1)
realPrefix := prefix
for i := 0; i < 4-len(prefix); i++ {
realPrefix = "0" + realPrefix
}
skuNameExt.YbNameSuffix = realPrefix
if utils.Str2Int64(prefix) > 9999 {
return nil, fmt.Errorf("银豹的商品后缀已超过9999!")
}
}
}
picType := true
for _, imgName := range []string{skuNameExt.Img, skuNameExt.Img2} {
if imgName != "" {
dataRes, err2 := datares.TryRegisterDataResource(ctx, skuNameExt.Name, imgName, model.ImgTypeMain, false)
if dataRes.ResourceType == model.MimeTypeJpeg || dataRes.ResourceType == model.MimeTypePng {
picType = false
}
if err = err2; err != nil {
return nil, err
}
}
}
if picType {
return nil, fmt.Errorf("商品图片应至少包含一张非gif格式的图片")
}
if skuNameExt.DescImg != "" {
dataRes, err2 := datares.TryRegisterDataResource(ctx, skuNameExt.Name+"desc", skuNameExt.DescImg, model.ImgTypeDesc, false)
if dataRes.ResourceType == model.MimeTypeGif {
return nil, fmt.Errorf("商品详情图片不能上传gif格式的图片")
}
if err = err2; err != nil {
return nil, err
}
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
dao.WrapAddIDCULDEntity(&skuNameExt.SkuName, userName)
if err = dao.CreateEntity(db, &skuNameExt.SkuName); err != nil {
dao.Rollback(db)
return nil, err
}
if err = OnCreateThing(ctx, db, nil, int64(skuNameExt.SkuName.ID), model.ThingTypeSkuName); err != nil {
dao.Rollback(db)
return nil, err
}
for _, v := range skuNameExt.Skus {
sku := v.Sku
dao.WrapAddIDCULDEntity(sku, userName)
sku.NameID = skuNameExt.ID
// sku.JdSyncStatus = model.SyncFlagNewMask
// sku.JdID = 0
if err = dao.CreateEntity(db, sku); err != nil {
dao.Rollback(db)
return nil, err
}
if sku.EclpID == "" {
if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return nil, err
}
}
}
for _, placeCode := range skuNameExt.Places {
placeBind := &model.SkuNamePlaceBind{}
dao.WrapAddIDCULEntity(placeBind, userName)
placeBind.NameID = skuNameExt.ID
placeBind.PlaceCode = placeCode
if err = dao.CreateEntity(db, placeBind); err != nil {
dao.Rollback(db)
return nil, err
}
}
dao.Commit(db)
tmpInfo, err := GetSkuNames(ctx, "", false, utils.Params2Map("nameID", skuNameExt.SkuName.ID), 0, 1)
if err != nil {
return nil, err
}
if tmpInfo.TotalCount != 1 {
return nil, ErrEntityNotExist
}
outSkuNameExt = tmpInfo.SkuNames[0]
_, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, -1, false, false, userName)
return outSkuNameExt, err
}
func UpdateSkuName(ctx *jxcontext.Context, nameID int, payload map[string]interface{}, isExd bool) (num int64, err error) {
userName := ctx.GetUserName()
skuName := &model.SkuName{}
skuName.ID = nameID
db := dao.GetDB()
if err = dao.GetEntity(db, skuName); err != nil {
return 0, err
}
if payload["name"] != nil {
newSkuName := utils.TrimBlankChar(utils.Interface2String(payload["name"]))
if hasSensitiveWord, err := CheckHasSensitiveWord(newSkuName); hasSensitiveWord {
return 0, err
}
payload["name"] = newSkuName
}
delete(payload, "isSpu")
delete(payload, "seq")
valid := dao.StrictMakeMapByStructObject(payload, skuName, userName)
valid = utils.RemoveGeneralMapKeys(valid, model.FieldSpecQuality, model.FieldSpecUnit)
_, hasPlaces := payload["places"]
if len(valid) > 0 || hasPlaces {
if valid["Upc"] != nil {
if upc, _ := valid["Upc"].(string); upc == "" {
valid["Upc"] = nil
} else if !jxutils.IsUpcValid(upc) {
return 0, fmt.Errorf("upc:%s不合法请仔细检查", upc)
}
}
globals.SugarLogger.Debugf("UpdateSkuName valid:%s", utils.Format4Output(valid, false))
for _, imgName := range []string{"img", "img2"} {
if valid[imgName] != nil {
if imgStr := utils.Interface2String(valid[imgName]); imgStr != "" {
_, err2 := datares.TryRegisterDataResource(ctx, skuName.Name, valid[imgName].(string), model.ImgTypeMain, true)
if err = err2; err != nil {
return 0, err
}
}
}
}
if valid["descImg"] != nil {
descImg := valid["descImg"].(string)
if descImg != "" {
_, err2 := datares.TryRegisterDataResource(ctx, skuName.Name+"_desc", descImg, model.ImgTypeDesc, false)
if err = err2; err != nil {
return 0, err
}
}
}
var eclpID string
if payload["eclpID"] != nil {
eclpID = payload["eclpID"].(string)
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
// valid[model.FieldJdSyncStatus] = model.SyncFlagModifiedMask | skuName.JdSyncStatus
if num, err = dao.UpdateEntityLogically(db, skuName, valid, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
if !isExd && eclpID == "" {
if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil {
dao.Rollback(db)
return 0, err
}
}
if utils.Interface2Int64WithDefault(payload["isGlobal"], 0) == 0 && payload["places"] != nil {
if places, ok := payload["places"].([]interface{}); ok {
if _, err = dao.DeleteSkuNamePlace(db, nameID, nil); err != nil {
dao.Rollback(db)
return 0, err
}
for _, placeCode := range places {
placeBind := &model.SkuNamePlaceBind{}
placeBind.PlaceCode = int(utils.Interface2Int64WithDefault(placeCode, 0))
if placeBind.PlaceCode > 0 {
dao.WrapAddIDCULEntity(placeBind, userName)
placeBind.NameID = nameID
err = dao.CreateEntity(db, placeBind)
} else {
dao.Rollback(db)
return 0, errors.New("地点代码非法")
}
}
}
}
skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil)
if err = err2; err == nil {
for _, v := range skuList {
sku := &v.Sku
// sku.JdSyncStatus |= model.SyncFlagModifiedMask
sku.LastOperator = userName
sku.UpdatedAt = time.Now()
if _, err = dao.UpdateEntity(db, sku); err != nil {
dao.Rollback(db)
return 0, err
}
if sku.ExdSkuID == "" && sku.EclpID == "" {
if err = OnUpdateThing(ctx, db, nil, int64(v.ID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return 0, err
}
}
}
}
skuIDs, err2 := dao.GetSkuIDByNames(db, []int{nameID})
if err = err2; err != nil {
dao.Rollback(db)
return 0, err
}
if len(skuIDs) > 0 {
if _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), skuIDs, model.SyncFlagModifiedMask); err != nil {
dao.Rollback(db)
return 0, err
}
}
dao.Commit(db)
errList := errlist.New()
errList.AddErr(err)
_, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName)
errList.AddErr(err)
err = errList.GetErrListAsOne()
}
return num, err
}
func SetStoreSkuSyncStatus2(db *dao.DaoDB, storeIDs []int, vendorIDs, skuIDs []int, syncStatus int) (num int64, err error) {
for _, vendorID := range vendorIDs {
num2, err2 := dao.SetStoreSkuSyncStatus(db, vendorID, storeIDs, skuIDs, syncStatus)
if err = err2; err != nil {
return 0, err
}
num += num2
}
return num, nil
}
func DeleteSkuName(ctx *jxcontext.Context, nameID int, userName string) (num int64, err error) {
db := dao.GetDB()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if _, err := dao.DeleteSkuNamePlace(db, nameID, nil); err != nil {
dao.Rollback(db)
return 0, err
}
if _, err = DeleteStoreSku(ctx, db, nameID, 0); err != nil {
dao.Rollback(db)
return 0, err
}
skuList, err2 := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil)
if err = err2; err == nil {
for _, v := range skuList {
sku := &v.Sku
if err = OnDeleteThing(ctx, db, nil, int64(v.ID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return 0, err
}
if _, err = dao.DeleteEntityLogically(db, sku, map[string]interface{}{
// model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
model.FieldStatus: model.SkuStatusDeleted,
}, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
}
}
if err = OnDeleteThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil {
dao.Rollback(db)
return 0, err
}
skuName := &model.SkuName{}
skuName.ID = nameID
if num, err = dao.DeleteEntityLogically(db, skuName, map[string]interface{}{
// model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
model.FieldStatus: model.SkuStatusDeleted,
}, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
dao.Commit(db)
if len(skuList) > 0 {
_, err = CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, false, userName)
}
return num, err
}
func AddSku(ctx *jxcontext.Context, nameID int, sku *model.Sku, userName string) (outSkuNameExt *model.SkuNameExt, err error) {
db := dao.GetDB()
skuName := &model.SkuName{}
skuName.ID = nameID
if err = dao.GetEntity(db, skuName); err != nil {
return nil, err
}
if skuName.Unit != model.SpecialUnit {
return nil, errors.New("不为份的SKU NAME只能有一个SKU")
}
dao.WrapAddIDCULDEntity(sku, userName)
// sku.JdSyncStatus = model.SyncFlagNewMask
// sku.JdID = 0
sku.NameID = nameID
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if err = dao.CreateEntity(db, sku); err != nil {
dao.Rollback(db)
return nil, err
}
if err = OnCreateThing(ctx, db, nil, int64(sku.ID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return nil, err
}
dao.Commit(db)
result, err2 := GetSkuNames(ctx, "", false, utils.Params2Map("skuID", sku.ID), 0, 0)
if err = err2; err == nil {
if result.TotalCount == 1 {
outSkuNameExt = result.SkuNames[0]
_, err = CurVendorSync.SyncSku(ctx, db, outSkuNameExt.SkuName.ID, sku.ID, false, false, userName)
} else {
err = ErrEntityNotExist
}
}
return outSkuNameExt, err
}
func UpdateSku(ctx *jxcontext.Context, skuID int, payload map[string]interface{}) (num int64, err error) {
userName := ctx.GetUserName()
sku := &model.Sku{}
sku.ID = skuID
db := dao.GetDB()
if err = dao.GetEntity(db, sku); err != nil {
return 0, err
}
valid := dao.StrictMakeMapByStructObject(payload, sku, userName)
if len(valid) > 0 {
// globals.SugarLogger.Debug(utils.Format4Output(valid, false))
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
maskValue := int8(model.SyncFlagModifiedMask)
if valid["specQuality"] != nil || valid["specUnit"] != nil {
maskValue |= model.SyncFlagSpecMask
}
// valid[model.FieldJdSyncStatus] = maskValue | sku.JdSyncStatus
if num, err = dao.UpdateEntityLogically(db, sku, valid, userName, nil); err != nil || num == 0 {
dao.Rollback(db)
if err == nil {
err = ErrEntityNotExist
}
return 0, err
}
if _, err = dao.ExecuteSQL(db, `
UPDATE sku_name t1
JOIN sku t2 ON t1.id = t2.name_id
SET t1.spec_quality = t2.spec_quality,
t1.spec_unit = t2.spec_unit
WHERE t1.deleted_at = ? AND t2.id = ? AND t1.unit <> ?
`, utils.DefaultTimeValue, skuID, model.SpecialUnit); err != nil {
dao.Rollback(db)
if err == nil {
err = ErrEntityNotExist
}
return 0, err
}
if sku.ExdSkuID == "" && sku.EclpID == "" {
if err = OnUpdateThing(ctx, db, nil, int64(skuID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return 0, err
}
}
dao.Commit(db)
if _, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), []int{skuID}, model.SyncFlagModifiedMask); err == nil {
if maskValue&model.SyncFlagSpecMask != 0 {
err = refreshStoreSkuPrice(ctx, db, skuID)
}
}
errList := errlist.New()
errList.AddErr(err)
_, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName)
errList.AddErr(err)
err = errList.GetErrListAsOne()
}
return num, err
}
func refreshStoreSkuPrice(ctx *jxcontext.Context, db *dao.DaoDB, skuID int) (err error) {
list, err := dao.GetStoreSkusAndSkuName(db, nil, []int{skuID}, nil)
task := tasksch.NewParallelTask("refreshStoreSkuPrice", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*dao.StoreSkuAndName)
storeID := v.StoreID
storeDetail, _ := dao.GetStoreDetail(db, storeID, model.VendorIDJX)
if storeDetail == nil {
return retVal, err
}
storeSku := &model.StoreSkuBind{}
storeSku.ID = v.BindID
storeSku.JdSyncStatus = v.JdSyncStatus | model.SyncFlagPriceMask
storeSku.MtwmSyncStatus = v.MtwmSyncStatus | model.SyncFlagPriceMask
storeSku.EbaiSyncStatus = v.EbaiSyncStatus | model.SyncFlagPriceMask
storeSku.Price = jxutils.CaculateSkuPrice(int(v.UnitPrice), v.SpecQuality, v.SpecUnit, v.Unit)
storeSku.JxPrice = jxutils.CaculatePriceByPricePack(storeDetail.PricePercentagePackObj, int(storeDetail.PricePercentage), int(storeSku.Price))
storeSku.LastOperator = ctx.GetUserName()
storeSku.UpdatedAt = time.Now()
dao.Begin(db)
defer func() {
if r := recover(); r != nil || err != nil {
dao.Rollback(db)
if r != nil {
panic(r)
}
}
}()
dao.UpdateEntity(db, storeSku, "Price", "JdSyncStatus", "MtwmSyncStatus", "EbaiSyncStatus", "JxPrice")
dao.Commit(db)
return retVal, err
}, list)
tasksch.HandleTask(task, nil, true).Run()
_, err = task.GetResult(0)
return err
}
func DeleteSku(ctx *jxcontext.Context, skuID int, userName string) (num int64, err error) {
db := dao.GetDB()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if _, err = DeleteStoreSku(ctx, db, 0, skuID); err != nil {
dao.Rollback(db)
return 0, err
}
if err = OnDeleteThing(ctx, db, nil, int64(skuID), model.ThingTypeSku); err != nil {
dao.Rollback(db)
return 0, err
}
sku := &model.Sku{}
sku.ID = skuID
if num, err = dao.DeleteEntityLogically(db, sku, map[string]interface{}{
model.FieldStatus: model.SkuStatusDeleted,
// model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
}, userName, nil); err != nil {
dao.Rollback(db)
return 0, err
}
dao.Commit(db)
if num == 1 {
_, err = CurVendorSync.SyncSku(ctx, db, -1, sku.ID, false, false, userName)
}
return num, err
}
func DeleteStoreSku(ctx *jxcontext.Context, db *dao.DaoDB, nameID, skuID int) (num int64, err error) {
if db == nil {
db = dao.GetDB()
}
sql := `
SELECT *
FROM sku t1
WHERE 1 = 1
`
sqlParams := []interface{}{}
if nameID > 0 {
sql += " AND t1.name_id = ?"
sqlParams = append(sqlParams, nameID)
} else {
sql += " AND t1.id = ?"
sqlParams = append(sqlParams, skuID)
}
var skuList []*model.Sku
if err = dao.GetRows(db, &skuList, sql, sqlParams); err == nil {
num = int64(len(skuList))
for _, v := range skuList {
storeSkuBind := &model.StoreSkuBind{}
_, err = dao.DeleteEntityLogically(db, storeSkuBind, map[string]interface{}{
model.FieldJdSyncStatus: model.SyncFlagDeletedMask,
model.FieldMtwmSyncStatus: model.SyncFlagDeletedMask,
model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask,
}, ctx.GetUserName(), map[string]interface{}{
model.FieldSkuID: v.ID,
model.FieldDeletedAt: utils.DefaultTimeValue,
})
if err != nil {
break
}
}
}
return num, err
}
func AddSkuNamePlace(ctx *jxcontext.Context, nameID, placeCode int, userName string) (outPlaceBind *model.SkuNamePlaceBind, err error) {
db := dao.GetDB()
placeBind := &model.SkuNamePlaceBind{
NameID: nameID,
PlaceCode: placeCode,
}
dao.WrapAddIDCULEntity(placeBind, userName)
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if err = dao.CreateEntity(db, placeBind); err != nil {
dao.Rollback(db)
return nil, err
}
if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil {
dao.Rollback(db)
return nil, err
}
dao.Commit(db)
_, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName)
return placeBind, err
}
func DeleteSkuNamePlace(ctx *jxcontext.Context, nameID, placeCode int, userName string) (num int64, err error) {
db := dao.GetDB()
placeBind := &model.SkuNamePlaceBind{}
placeBind.NameID = nameID
placeBind.PlaceCode = placeCode
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
if num, err = dao.DeleteEntity(db, placeBind, model.FieldNameID, model.FieldPlaceCode); err != nil || num == 0 {
dao.Rollback(db)
if err == nil {
err = ErrEntityNotExist
}
return 0, err
}
if err = OnUpdateThing(ctx, db, nil, int64(nameID), model.ThingTypeSkuName); err != nil {
dao.Rollback(db)
return 0, err
}
dao.Commit(db)
_, err = CurVendorSync.SyncSku(ctx, db, nameID, -1, false, false, userName)
return num, err
}
// func GetVendorSku(ctx *jxcontext.Context, vendorID int, vendorOrgCode, vendorSkuID string) (skuNameInfo *model.SkuNameExt, err error) {
// if handler := CurVendorSync.GetMultiStoreHandler(vendorID); handler != nil {
// return handler.ReadSku(ctx, vendorOrgCode, vendorSkuID)
// }
// return nil, ErrCanNotFindVendor
// }
func SortCategorySkus(ctx *jxcontext.Context, catID int, skuIDList []int) (err error) {
db := dao.GetDB()
userName := ctx.GetUserName()
var skuList []*model.Sku
if skuList, err = dao.GetSkuByCats(db, []int{catID}); err == nil && len(skuList) > 0 {
if len(skuList) != len(skuIDList) {
return errors.New("商品数量不匹配!")
}
skuIDMap := make(map[int]int)
for index, id := range skuIDList {
skuIDMap[id] = index + 1
}
for _, value := range skuList {
if _, ok := skuIDMap[value.ID]; !ok {
return errors.New("商品数据不匹配!")
}
}
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
nameIDList := []int{}
for _, value := range skuList {
seq := skuIDMap[value.ID]
if value.Seq != seq {
kvs := map[string]interface{}{
model.FieldSkuSeq: seq,
//model.FieldJdSyncStatus: (value.JdSyncStatus | model.SyncFlagModifiedMask),
}
dao.UpdateEntityLogically(db, value, kvs, userName, nil)
nameIDList = append(nameIDList, value.NameID)
}
}
//_, err = CurVendorSync.SyncSkus(ctx, db, nameIDList, []int{}, false, false, userName)
if err == nil && len(nameIDList) > 0 {
dao.Commit(db)
skuIDs, err2 := dao.GetSkuIDByNames(db, nameIDList)
if err = err2; err == nil && len(skuIDs) > 0 {
_, err = SetStoreSkuSyncStatus2(db, nil, partner.GetSingleStoreVendorIDs(), skuIDs, model.SyncFlagModifiedMask)
}
} else {
dao.Rollback(db)
}
}
return err
}
func GetJdUpcCodeByName(ctx *jxcontext.Context, name, upcCode string) (productInfos []*jdapi.ProductInfo, err error) {
var (
pageNo = 5
pageSize = 30
pageNoList []int
)
if name == "" && upcCode == "" {
return nil, fmt.Errorf("至少输入一个条件查询商品名或者upc码")
}
for i := 1; i < pageNo+1; i++ {
pageNoList = append(pageNoList, i)
}
task := tasksch.NewParallelTask("获取京东商品", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
pageNum := batchItemList[0].(int)
productInfo, err := api.JdAPI.GetJdUpcCodeByName(name, upcCode, pageNum, pageSize)
if err != nil {
return retVal, err
}
for _, v := range productInfo {
_, name, _, specUnit, unit, specQuality := jxutils.SplitSkuName(v.OriginalName)
v.Name = name
v.SpecQuality = specQuality
v.SpecUnit = specUnit
v.Unit = unit
}
retVal = productInfo
return retVal, err
}, pageNoList)
tasksch.HandleTask(task, nil, true).Run()
productInfoInterface, err := task.GetResult(0)
for _, v := range productInfoInterface {
productInfos = append(productInfos, v.(*jdapi.ProductInfo))
}
return productInfos, err
}
func UpdateSkuNamesExPrefix(ctx *jxcontext.Context, nameIDs []int, exPrefix, fromTime, toTime string, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
fromTimeP time.Time
toTimeP time.Time
db = dao.GetDB()
)
if fromTime != "" {
fromTimeP = utils.Time2Date(utils.Str2Time(fromTime))
}
if toTime != "" {
toTimeP = utils.Time2Date(utils.Str2Time(toTime))
}
if toTimeP.Before(fromTimeP) {
return "", fmt.Errorf("结束时间不可以小于开始时间!开始时间:[%v],结束时间:[%v]", fromTimeP, toTimeP)
}
task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
step := batchItemList[0].(int)
now := utils.Time2Date(time.Now())
switch step {
case 0:
task := tasksch.NewParallelTask("批量设置商品前缀", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
nameID := batchItemList[0].(int)
payload := map[string]interface{}{
"exPrefix": exPrefix,
"exPrefixBegin": fromTimeP,
"exPrefixEnd": toTimeP,
}
if now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0 {
_, err = UpdateSkuName(ctx, nameID, payload, false)
} else if now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0 {
payload["exPrefixBegin"] = nil
payload["exPrefixEnd"] = nil
_, err = UpdateSkuName(ctx, nameID, payload, false)
} else {
skuList, err := dao.GetSkus(db, nil, []int{nameID}, nil, nil, nil)
if err == nil && len(skuList) > 0 {
if skuList[0].ExPrefixBegin != nil {
_, err = UpdateSkuName(ctx, nameID, payload, false)
CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, []int{skuList[0].ID}, nil, model.SyncFlagModifiedMask, true, true)
} else {
skuName := &model.SkuName{
ExPrefix: exPrefix,
ExPrefixBegin: &fromTimeP,
ExPrefixEnd: &toTimeP,
}
skuName.ID = nameID
skuName.LastOperator = ctx.GetLoginID()
skuName.UpdatedAt = time.Now()
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
_, err = dao.UpdateEntity(db, skuName, "ExPrefix", "ExPrefixBegin", "ExPrefixEnd", "LastOperator", "UpdatedAt")
dao.Commit(db)
}
}
}
return retVal, err
}, nameIDs)
tasksch.HandleTask(task, nil, true).Run()
_, err = task.GetResult(0)
case 1:
if (now.Sub(toTimeP) <= 0 && now.Sub(fromTimeP) >= 0) || (now.Sub(fromTimeP) > 0 && now.Sub(toTimeP) > 0) {
var skuIDs []int
skuList, err2 := dao.GetSkus(db, nil, nameIDs, nil, nil, nil)
if err = err2; err == nil {
if len(skuList) > 0 {
for _, v := range skuList {
skuIDs = append(skuIDs, v.ID)
}
CurVendorSync.SyncStoresSkus2(ctx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, skuIDs, nil, model.SyncFlagModifiedMask, true, true)
}
}
}
}
return retVal, err
}, []int{0, 1})
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
_, err = task.GetResult(0)
hint = "1"
} else {
hint = task.GetID()
}
return hint, err
}
func SetSingleStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) {
_, err = dao.UpdateStoreSkuBindSyncStatusForExPrefix(db, vendorIDs)
return err
}
func SetMultiStoreSkuSyncModifyStatus(db *dao.DaoDB, vendorIDs []int) (err error) {
_, err = dao.UpdateSkuSyncStatusForExPrefix(db, vendorIDs)
return err
}
func DeleteSkuNameExPrefixOverdue(db *dao.DaoDB) (err error) {
_, err = dao.DeleteSkuNameExPrefixOverdue(db)
return err
}
func SumExianDaDepot(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
results, err := api.EbaiAPI.GetExianDaSkuDepot("")
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*ebaiapi.ExianDaSkus)
skus, err := api.EbaiAPI.GetExianDaSku(utils.Str2Int64(v.ElemeGoodsID))
if err != nil || skus == nil {
globals.SugarLogger.Debugf("GetExianDaSku[%v]", v.ElemeGoodsID)
return result, err
}
// sku := &model.Sku{}
// sku.ExdSkuID = v.ElemeGoodsID
// sku.DeletedAt = utils.DefaultTimeValue
// dao.GetEntity(db, sku, "ExdSkuID","DeletedAt")
skuNameExt := &model.SkuName{}
sql2 := `
SELECT a.*
FROM sku_name a
JOIN sku b ON b.name_id = a.id
WHERE a.upc = ?
AND a.deleted_at = ? AND b.deleted_at = ?
`
sqlParams2 := []interface{}{
skus.UpcIds[0],
utils.DefaultTimeValue, utils.DefaultTimeValue,
}
dao.GetRow(db, skuNameExt, sql2, sqlParams2)
prefix, _, _, specUnit, unit, specQuality := jxutils.SplitSkuName(v.GoodsName)
//京西库中存在此商品
if skuNameExt.ID != 0 {
var flag = false
if skuNameExt.Name != v.GoodsName {
skuNameExt.Name = v.GoodsName
skuNameExt.Prefix = prefix
skuNameExt.SpecUnit = specUnit
skuNameExt.Unit = unit
skuNameExt.SpecQuality = specQuality
flag = true
}
if skuNameExt.Img != v.ImageURL {
skuNameExt.Img = v.ImageURL
flag = true
}
if flag {
_, err = dao.UpdateEntity(db, skuNameExt, "Name", "Prefix", "SpecUnit", "Unit", "SpecQuality", "Img")
if err != nil {
return result, err
}
}
} else {
skuName := &model.SkuName{
Prefix: prefix,
Name: v.GoodsName,
IsGlobal: model.YES,
Unit: unit,
SpecQuality: specQuality,
SpecUnit: specUnit,
Price: 100,
Img: v.ImageURL,
Upc: &v.UpcID,
Status: model.SkuStatusNormal,
}
skuName.CategoryID = model.NoCatCatgoryID //默认给了个分类
dao.WrapAddIDCULDEntity(skuName, ctx.GetUserName())
err = dao.CreateEntity(db, skuName)
if err != nil {
return result, err
}
sku := &model.Sku{
NameID: skuName.ID,
SpecQuality: specQuality,
SpecUnit: specUnit,
Weight: int(utils.Str2Int64(skus.Weight)),
Status: model.SkuStatusNormal,
ExdSkuID: v.ElemeGoodsID,
ExdCategoryThirdID: skus.CategoryIDThird,
}
dao.WrapAddIDCULDEntity(sku, ctx.GetUserName())
err = dao.CreateEntity(db, sku)
if err != nil {
return result, err
}
}
return retVal, err
}
taskParallel := tasksch.NewParallelTask("更新京西上饿鲜达商品库", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, taskFunc, results)
tasksch.HandleTask(taskParallel, task, true).Run()
_, err = taskParallel.GetResult(0)
case 1:
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("合并饿鲜达商品库", ctx, isContinueWhenError, taskSeqFunc, 2)
tasksch.HandleTask(taskSeq, nil, true).Run()
if !isAsync {
_, err = taskSeq.GetResult(0)
hint = "1"
} else {
hint = taskSeq.GetID()
}
return hint, err
}
func UpdateExianDaSkuCategory(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) {
var (
db = dao.GetDB()
skus []*model.SkuName
)
sql := `
SELECT a.*
FROM sku_name a
JOIN sku b ON b.name_id = a.id
WHERE b.exd_sku_id <> ''
AND a.deleted_at = ?
AND b.deleted_at = ?
`
sqlParams := []interface{}{
utils.DefaultTimeValue, utils.DefaultTimeValue,
}
err = dao.GetRows(db, &skus, sql, sqlParams...)
task := tasksch.NewParallelTask("更新京西上饿鲜达商品分类", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
v := batchItemList[0].(*model.SkuName)
skuList, err := api.Ebai2API.GetEbaiDepotSku(ebaiapi.EbaiWholeCountryStore, *v.Upc)
if err != nil || len(skuList) == 0 || skuList[0] == nil {
return retVal, err
}
sku, err := api.Ebai2API.GetEbaiSku(skuList[0].UpcID, ebaiapi.EbaiWholeCountryStore)
if err != nil || sku == nil || sku.CustomCatName == "" {
return retVal, err
}
skuCat := &model.SkuCategory{}
sql := `
SELECT *
FROM sku_category
WHERE exd_name like ?
`
sqlParams := []interface{}{
"%" + sku.CustomCatName + "%",
}
err = dao.GetRow(db, skuCat, sql, sqlParams)
v.CategoryID = skuCat.ID
_, err = dao.UpdateEntity(db, v, "CategoryID")
if err != nil {
return retVal, err
}
return retVal, err
}, skus)
tasksch.HandleTask(task, nil, true).Run()
if !isAsync {
_, err = task.GetResult(0)
hint = "1"
} else {
hint = task.GetID()
}
return hint, err
}
func SendNoCatSkusToOperater(ctx *jxcontext.Context) (err error) {
var (
db = dao.GetDB()
skuNames []*model.SkuName
)
sql := `
SELECT * FROM sku_name WHERE deleted_at = ? AND category_id = ?
`
sqlParams := []interface{}{utils.DefaultTimeValue, model.NoCatCatgoryID}
err = dao.GetRows(db, &skuNames, sql, sqlParams)
if err != nil {
return err
}
if len(skuNames) > 10 {
noticeMsg := "有超过10个标品未进行分类"
for _, v := range skuNames {
noticeMsg += "NameID" + utils.Int2Str(v.ID) + ",商品名:" + v.Name + ""
}
for _, mobile := range sendNoCatSkusMobile {
if user, err := dao.GetUserByID(db, "mobile", mobile); err != nil {
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "标品未分类", noticeMsg)
}
}
}
return err
}
func CreateUpcSkuByExcel(ctx *jxcontext.Context, files []*multipart.FileHeader) (err error) {
if len(files) == 0 {
return errors.New("没有文件上传!")
}
fileHeader := files[0]
file, err := fileHeader.Open()
err = CreateUpcSkuByExcelBin(ctx, file)
file.Close()
return err
}
func CreateUpcSkuByExcelBin(ctx *jxcontext.Context, reader io.Reader) (err error) {
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
switch step {
case 0:
case 1:
case 2:
}
return result, err
}
taskSeq := tasksch.NewSeqTask2("根据excel创建标品-序列任务", ctx, true, taskSeqFunc, 3)
tasksch.HandleTask(taskSeq, nil, true).Run()
_, err = taskSeq.GetResult(0)
return err
}