package cms import ( "errors" "strconv" "strings" "time" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" ) type SkuNameExt struct { model.SkuName Skus []*model.Sku `orm:"-" json:"skus"` SkusStr string `json:"-"` Places []*model.SkuNamePlaceBind `orm:"-" json:"places"` PlacesStr string `json:"-"` } type SkuNamesInfo struct { TotalCount int `json:"totalCount"` SkuNames []*SkuNameExt `json:"skuNames"` } var ( ErrInputCatsDoesntMatch = errors.New("输入的类别列表不合法,需要输入一个父ID下的所有子类别") ) // parentID 为-1表示所有 func GetVendorCategories(vendorID int, parentID int) (vendorCats []*model.SkuVendorCategory, err error) { cond := map[string]interface{}{ model.FieldVendorID: vendorID, } if parentID != -1 { cond[model.FieldParentID] = parentID } return vendorCats, dao.GetEntities(nil, &vendorCats, cond, false) } // parentID 为-1表示所有 func GetCategories(parentID int) (cats []*model.SkuCategory, err error) { if parentID == -1 { return cats, dao.GetEntities(nil, &cats, nil, false) } return cats, dao.GetEntities(nil, &cats, utils.Params2Map(model.FieldParentID, parentID), false) } func AddCategory(cat *model.SkuCategory, userName string) (outCat *model.SkuCategory, err error) { dao.WrapAddIDCULDEntity(cat, userName) cat.JdSyncStatus = model.SyncFlagNewMask if err = dao.CreateEntity(nil, cat); err == nil { outCat = cat err = CurVendorSync.SyncCategory(nil, cat.ID, false, userName) } return outCat, err } func UpdateCategory(categoryID int, payload map[string]interface{}, userName string) (num int64, err error) { cat := &model.SkuCategory{} cat.ID = categoryID valid := dao.NormalMakeMapByStructObject(payload, cat, userName) if len(valid) > 0 { valid[model.FieldJdSyncStatus] = model.SyncFlagModifiedMask db := dao.GetDB() if num, err = dao.UpdateEntityByKV(db, cat, valid, nil); err == nil { err = CurVendorSync.SyncCategory(db, categoryID, false, userName) } } return num, err } func ReorderCategories(parentID int, categoryIDs []int, userName string) (err error) { var cats []*model.SkuCategory parentCat := &model.SkuCategory{} parentCat.ID = parentID db := dao.GetDB() if err = dao.GetEntity(db, parentCat); err == nil { if err = dao.GetEntities(db, &cats, utils.Params2Map(model.FieldParentID, parentID), false); err == nil { catsLen := len(cats) if catsLen != len(categoryIDs) { return ErrInputCatsDoesntMatch } catsMap := make(map[int]*model.SkuCategory, catsLen) for _, cat := range cats { catsMap[cat.ID] = cat } for k, v := range categoryIDs { catsMap[v].Seq = k * 5 // catsMap[v].JdSyncStatus = model.SyncFlagModifiedMask if _, err = dao.UpdateEntity(db, catsMap[v], "Seq"); err != nil { break } } // todo 这里应该也需要先置标记 if err == nil { err = GetPurchaseHandler(model.VendorIDJD).ReorderCategories(parentCat, userName) } } } return err } func DeleteCategory(categoryID int, isForce bool, 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 = ? UNION ALL SELECT COUNT(*) ct FROM sku_name t1 WHERE t1.category_id = ? UNION ALL SELECT COUNT(*) ct FROM sku_category t1 WHERE t1.parent_id = ? `, categoryID, categoryID, categoryID, &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("还有商品类别使用此类别,不能删除") } if num, err = dao.DeleteEntityLogically(db, cat, nil, userName, utils.Params2Map(model.FieldJdSyncStatus, model.SyncFlagDeletedMask)); err == nil && num == 1 { err = CurVendorSync.SyncCategory(db, cat.ID, false, userName) } } return num, err } func GetSkuNames(keyword string, 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 = '1970-01-01 00:00:00' LEFT JOIN sku_name_place_bind t3 ON t1.id = t3.name_id WHERE t1.deleted_at = '1970-01-01 00:00:00'` sqlParams := make([]interface{}, 0) if keyword != "" { keywordLike := "%" + keyword + "%" sql += " AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t1.comment LIKE ?" sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike) if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil { sql += " OR t2.jd_id = ? OR t1.id = ? OR t1.category_id = ?" sqlParams = append(sqlParams, keywordInt64, keywordInt64, keywordInt64) } sql += ")" } if params["nameID"] != nil { sql += " AND t1.id = ?" sqlParams = append(sqlParams, params["nameID"].(int)) } if params["categoryID"] != nil { cat := &model.SkuCategory{} cat.ID = params["categoryID"].(int) if err = dao.GetEntity(db, cat); err != nil { return nil, err } if cat.Level == 1 { sql += " AND t1.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)" } else { sql += " AND t1.category_id = ?" } sqlParams = append(sqlParams, cat.ID) } if params["jdID"] != nil { sql += " AND t1.jd_id = ?" sqlParams = append(sqlParams, params["jdID"].(int)) } 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["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.prefix, t1.name, t1.comment, t1.brand_id, t1.category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.elm_img_hash_code ` sqlData := ` SELECT SQL_CALC_FOUND_ROWS t1.id, t1.created_at, t1.updated_at, t1.last_operator, t1.prefix, t1.name, t1.comment, t1.brand_id, t1.category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.elm_img_hash_code, CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t2.id, ',"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, '","weight":', t2.weight, ',"jdID":', t2.jd_id, ',"categoryID":', t2.category_id, ',"nameID":', t2.name_id, "}")), "]") skus_str, CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t3.id, ',"createdAt":"', CONCAT(REPLACE(t3.created_at," ","T"),"+08:00"), '","updatedAt":"', CONCAT(REPLACE(t3.updated_at," ","T"),"+08:00"), '","lastOperator":"', t3.last_operator, '","nameID":', t3.name_id, ',"placeCode":', t3.place_code, "}")), "]") places_str ` + sql + ` ORDER BY t1.id LIMIT ? OFFSET ?` if pageSize == 0 { pageSize = model.DefPageSize } if offset < 0 { offset = 0 } sqlParams = append(sqlParams, pageSize, offset) skuNamesInfo = &SkuNamesInfo{} globals.SugarLogger.Debug(sqlData) if err = dao.GetRows(db, &skuNamesInfo.SkuNames, sqlData, sqlParams...); err == nil { countInfo := &struct{ Ct int }{} if err = dao.GetRow(db, countInfo, "SELECT FOUND_ROWS() ct"); err == nil { skuNamesInfo.TotalCount = countInfo.Ct for _, skuName := range skuNamesInfo.SkuNames { if skuName.SkusStr != "" { if err = utils.UnmarshalUseNumber([]byte(skuName.SkusStr), &skuName.Skus); err != nil { break } } if skuName.PlacesStr != "" { if err = utils.UnmarshalUseNumber([]byte(skuName.PlacesStr), &skuName.Places); err != nil { break } } } } } return skuNamesInfo, err } func AddSkuName(skuNameExt *SkuNameExt, userName string) (outSkuNameExt *SkuNameExt, err error) { if skuNameExt.CategoryID == 0 { return nil, errors.New("CategoryID不能为空") } db := dao.GetDB() dao.Begin(db) dao.WrapAddIDCULDEntity(&skuNameExt.SkuName, userName) if err = dao.CreateEntity(db, &skuNameExt.SkuName); err != nil { dao.Rollback(db) return nil, err } for _, sku := range skuNameExt.Skus { dao.WrapAddIDCULDEntity(sku, userName) sku.NameID = skuNameExt.ID sku.JdSyncStatus = model.SyncFlagNewMask if err = dao.CreateEntity(db, sku); err != nil { dao.Rollback(db) return nil, err } } for _, placeBind := range skuNameExt.Places { dao.WrapAddIDCULEntity(placeBind, userName) placeBind.NameID = skuNameExt.ID if err = dao.CreateEntity(db, placeBind); err != nil { dao.Rollback(db) return nil, err } } dao.Commit(db) tmpInfo, err := GetSkuNames("", utils.Params2Map("id", 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(db, outSkuNameExt.SkuName.ID, -1, false, userName) return outSkuNameExt, err } func UpdateSkuName(nameID int, payload map[string]interface{}, userName string) (num int64, err error) { skuName := &model.SkuName{} skuName.ID = nameID valid := dao.NormalMakeMapByStructObject(payload, skuName, userName) if len(valid) > 0 { db := dao.GetDB() if num, err = dao.UpdateEntityByKV(db, skuName, valid, nil); err == nil && num == 1 { sku := &model.Sku{} _, err2 := dao.UpdateEntityByKV(db, sku, utils.Params2Map(model.FieldJdSyncStatus, model.SyncFlagModifiedMask), utils.Params2Map(model.FieldNameID, skuName.ID)) if err = err2; err == nil { if err = dao.GetEntity(db, skuName); err == nil { err = CurVendorSync.SyncSku(db, skuName.ID, -1, false, userName) } } } } return num, err } func DeleteSkuName(nameID int, userName string) (num int64, err error) { db := dao.GetDB() dao.Begin(db) skuName := &model.SkuName{} skuName.ID = nameID if num, err = dao.DeleteEntityLogically(db, skuName, nil, userName, nil); err == nil && num == 1 { dummy := &model.Sku{} num2, err2 := dao.UpdateEntityByKV(db, dummy, map[string]interface{}{ model.FieldDeletedAt: time.Now(), model.FieldLastOperator: userName, model.FieldJdSyncStatus: model.SyncFlagDeletedMask, "Status": model.SkuStatusDeleted, }, utils.Params2Map(model.FieldNameID, skuName.ID)) if err2 == nil { dao.Commit(db) if num2 > 0 { err = CurVendorSync.SyncSku(db, skuName.ID, -1, false, userName) } return num, err } } dao.Rollback(db) return num, err } func AddSku(nameID int, sku *model.Sku, userName string) (outSkuNameExt *SkuNameExt, err error) { db := dao.GetDB() dao.WrapAddIDCULDEntity(sku, userName) sku.JdSyncStatus = model.SyncFlagNewMask sku.NameID = nameID if err = dao.CreateEntity(db, sku); err == nil { result, err2 := GetSkuNames("", utils.Params2Map("skuID", sku.ID), 0, 0) if err = err2; err == nil { if result.TotalCount == 1 { outSkuNameExt = result.SkuNames[0] err = CurVendorSync.SyncSku(db, outSkuNameExt.SkuName.ID, sku.ID, false, userName) } else { err = ErrEntityNotExist } } } return outSkuNameExt, err } func UpdateSku(skuID int, payload map[string]interface{}, userName string) (num int64, err error) { sku := &model.Sku{} sku.ID = skuID valid := dao.NormalMakeMapByStructObject(payload, sku, userName) if len(valid) > 0 { valid[model.FieldJdSyncStatus] = model.SyncFlagModifiedMask db := dao.GetDB() if num, err = dao.UpdateEntityByKV(db, sku, valid, nil); err == nil { if num == 1 { err = CurVendorSync.SyncSku(db, -1, sku.ID, false, userName) } else { err = ErrEntityNotExist } } } return num, err } func DeleteSku(skuID int, userName string) (num int64, err error) { db := dao.GetDB() sku := &model.Sku{} sku.ID = skuID if num, err = dao.DeleteEntityLogically(db, sku, nil, userName, nil); err == nil { if num == 1 { err = CurVendorSync.SyncSku(db, -1, sku.ID, false, userName) } else { err = ErrEntityNotExist } } return num, err } func AddSkuNamePlace(nameID, placeCode int, userName string) (outPlaceBind *model.SkuNamePlaceBind, err error) { db := dao.GetDB() placeBind := &model.SkuNamePlaceBind{ NameID: nameID, PlaceCode: placeCode, } dao.WrapAddIDCULEntity(placeBind, userName) if err = dao.CreateEntity(db, placeBind); err == nil { err = CurVendorSync.SyncSku(db, nameID, -1, false, userName) } return placeBind, err } func DeleteSkuNamePlace(nameID, placeCode int, userName string) (num int64, err error) { db := dao.GetDB() placeBind := &model.SkuNamePlaceBind{} placeBind.NameID = nameID placeBind.PlaceCode = placeCode if num, err = dao.DeleteEntity(db, placeBind, model.FieldNameID, model.FieldPlaceCode); err == nil { if num == 1 { err = CurVendorSync.SyncSku(db, nameID, -1, false, userName) } else { err = ErrEntityNotExist } } return num, err }