Accept Merge Request #189: (su -> mark)

Merge Request: 饿先达商品分类完善
Created By: @苏尹岚
Accepted By: @苏尹岚
URL: https://rosydev.coding.net/p/jx-callback/d/jx-callback/git/merge/189
This commit is contained in:
苏尹岚
2020-02-18 20:35:14 +08:00
15 changed files with 294 additions and 35 deletions

View File

@@ -1454,10 +1454,10 @@ func getOrderOperatorInfo(order *model.GoodsOrder, storeDetail *dao.StoreDetail)
case model.VendorIDJD:
operatorPhone = storeDetail.OperatorPhone
operatorName = storeDetail.OperatorName
case model.VendorIDEBAI:
case model.VendorIDMTWM:
operatorPhone = storeDetail.OperatorPhone2
operatorName = storeDetail.OperatorName2
case model.VendorIDMTWM:
case model.VendorIDEBAI:
operatorPhone = storeDetail.OperatorPhone3
operatorName = storeDetail.OperatorName3
}

View File

@@ -132,9 +132,11 @@ func AddCategory(ctx *jxcontext.Context, cat *model.SkuCategory, userName string
dao.Rollback(db)
return nil, err
}
if err = OnCreateThing(ctx, db, nil, int64(cat.ID), model.ThingTypeCategory); 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
@@ -191,9 +193,11 @@ func UpdateCategory(ctx *jxcontext.Context, categoryID int, payload map[string]i
dao.Rollback(db)
return 0, err
}
if err = OnUpdateThing(ctx, db, nil, int64(categoryID), model.ThingTypeCategory); 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)
@@ -289,13 +293,14 @@ func ReorderCategories(ctx *jxcontext.Context, parentID int, categoryIDs []int,
dao.Rollback(db)
return err
}
if err = OnUpdateThing(ctx, db, nil, int64(catsMap[v].ID), model.ThingTypeCategory); 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)
@@ -422,6 +427,8 @@ func GetSkuNames(ctx *jxcontext.Context, keyword string, isBySku bool, params ma
} else {
sql += " AND t2.exd_sku_id = ''"
}
} else {
sql += " AND t2.exd_sku_id = ''"
}
if params["categoryID"] != nil {
cat := &model.SkuCategory{}
@@ -1511,3 +1518,59 @@ func SumExianDaDepot(ctx *jxcontext.Context) (err error) {
}
return err
}
func CopyEbaiSkuPriceToJx(ctx *jxcontext.Context, baiduShopID string) (err error) {
db := dao.GetDB()
skuList, err := api.EbaiAPI.PageGetSkuList(utils.Str2Int64(baiduShopID))
for _, v := range skuList {
sku, _ := api.EbaiAPI.PageGetSku(utils.Str2Int64(baiduShopID), utils.Str2Int64(v["sku_id"].(string)))
var skuName model.SkuName
sql2 := `
SELECT * FROM sku_category WHERE exd_name like ? AND deleted_at = ?
`
sqlParams2 := []interface{}{
"%" + sku.CustomCatName + "%",
utils.DefaultTimeValue,
}
dao.GetRow(db, &skuName, sql2, sqlParams2)
price := int(utils.Float64TwoInt64(utils.Interface2Float64WithDefault(v["sale_price"], 0) * 100))
sql := `
UPDATE sku_name a
JOIN sku b ON a.id = b.name_id
SET a.price = ?,a.category_id = ?
WHERE a.upc = ?
`
sqlParams := []interface{}{
price, skuName.ID,
v["upc"].(string),
}
dao.ExecuteSQL(db, sql, sqlParams)
}
return err
}
func CopyEbaiStoreSkusToJx(ctx *jxcontext.Context, baiduShopID string, storeID int) (err error) {
db := dao.GetDB()
var storeSkuBindInfo []*StoreSkuBindInfo
skuList, err := api.EbaiAPI.PageGetSkuList(utils.Str2Int64(baiduShopID))
for _, v := range skuList {
var skuName model.SkuName
sql2 := `
SELECT * FROM sku_name WHERE upc = ?
`
sqlParams2 := []interface{}{
v["upc"].(string),
}
dao.GetRow(db, &skuName, sql2, sqlParams2)
skuBindInfo := &StoreSkuBindInfo{
StoreID: storeID,
NameID: skuName.ID,
UnitPrice: skuName.Price,
IsFocus: 1,
IsSale: 1,
}
storeSkuBindInfo = append(storeSkuBindInfo, skuBindInfo)
}
UpdateStoresSkusByBind(ctx, nil, storeSkuBindInfo, true, true)
return err
}

View File

@@ -2388,7 +2388,8 @@ func GetStoreListByLocation(ctx *jxcontext.Context, lng, lat float64, needWalkDi
// 为了审核用
if len(storeList2) == 0 {
sqlParams = []interface{}{
sqlParams2 := []interface{}{
model.VendorIDJX, utils.DefaultTimeValue, model.StoreStatusDisabled,
utils.DefaultTimeValue,
model.StoreStatusDisabled,
jxutils.StandardCoordinate2Int(0),
@@ -2396,7 +2397,7 @@ func GetStoreListByLocation(ctx *jxcontext.Context, lng, lat float64, needWalkDi
jxutils.StandardCoordinate2Int(0),
jxutils.StandardCoordinate2Int(10000),
}
dao.GetRows(dao.GetDB(), &storeList2, sql, sqlParams...)
dao.GetRows(dao.GetDB(), &storeList2, sql, sqlParams2...)
if len(storeList2) > 1 {
storeList2 = storeList2[:1]
}
@@ -2745,3 +2746,103 @@ func RefreshJdLevel(ctx *jxcontext.Context) (err error) {
}
return err
}
type tJdStoreInfo struct {
model.Store
VendorOrgCode string `orm:"size(32)" json:"vendorOrgCode"` // 同一平台下不同的商户代码,如果只有一个,可以为空
FreightDeductionPack string `orm:"size(32)" json:"freightDeductionPack"` //
JdCityCode int
JdDistrictCode int
JdStoreStatus int
VendorStoreID string `orm:"column(vendor_store_id)"`
RealLastOperator string
SyncStatus int
VendorStoreName string
}
func UpdateJdStoreNameAll(ctx *jxcontext.Context) (err error) {
storeMap := map[int]int{
100345: 100345,
100347: 100347,
100852: 100852,
101689: 101689,
102654: 102654,
102381: 102381,
102500: 102500,
102810: 102810,
}
db := dao.GetDB()
userName := ctx.GetUserName()
for _, v := range storeMap {
var stores []*tJdStoreInfo
sql := `
SELECT
t1.*, city.jd_code jd_city_code, district.jd_code jd_district_code,
t2.status jd_store_status, t2.vendor_store_id, IF(t1.updated_at > t2.updated_at, t1.last_operator,
t2.last_operator) real_last_operator,
t2.sync_status, t2.freight_deduction_pack, t2.vendor_org_code, t2.vendor_store_name
FROM store t1
JOIN store_map t2 ON t1.id = t2.store_id AND t2.vendor_id = ?
LEFT JOIN place city ON t1.city_code = city.code
LEFT JOIN place district ON t1.district_code = district.code
WHERE t1.id = ?
ORDER BY t2.updated_at
`
if err = dao.GetRows(db, &stores, sql, model.VendorIDJD, v); err == nil {
for _, store := range stores {
a := jd.GetAPI(store.VendorOrgCode)
storeParams := &jdapi.OpStoreParams{
StationNo: store.VendorStoreID,
Operator: userName,
Phone: store.Tel1,
Mobile: store.Tel2,
}
if store.SyncStatus&model.SyncFlagDeletedMask == 0 {
storeParams.OutSystemID = utils.Int2Str(int(store.ID))
} else {
storeParams.OutSystemID = store.VendorStoreID
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreName) != 0 {
if store.VendorStoreName != "" {
storeParams.StationName = store.VendorStoreName
} else {
storeParams.StationName = jxutils.ComposeStoreName(store.Name, model.VendorIDJD)
}
storeParams.StationName = utils.LimitUTF8StringLen(storeParams.StationName, jdapi.MaxStoreNameLen)
}
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagStoreAddress) != 0 {
storeParams.StationAddress = store.Address
storeParams.CoordinateType = jdapi.CoordinateTypeAutonavi // 一直用高德
storeParams.Lng = jxutils.IntCoordinate2Standard(store.Lng)
storeParams.Lat = jxutils.IntCoordinate2Standard(store.Lat)
if store.JdCityCode != 0 {
storeParams.City = store.JdCityCode
}
if store.JdDistrictCode != 0 {
storeParams.County = store.JdDistrictCode
}
}
// if specialDistrictMap[storeParams.County] != 0 {
// storeParams.City = storeParams.County
// storeParams.County = specialDistrictMap[storeParams.County]
// }
storeParams.StoreNotice = store.PromoteInfo
modifyCloseStatus := false
if store.SyncStatus&(model.SyncFlagNewMask|model.SyncFlagDeletedMask|model.SyncFlagStoreStatus) != 0 {
modifyCloseStatus = true
_, storeParams.CloseStatus = jd.JxStoreStatus2JdStatus(jxutils.MergeStoreStatus(store.Status, store.JdStoreStatus))
}
// fillOpTimeParams(storeParams, store.GetOpTimeList())
// globals.SugarLogger.Debug(utils.Format4Output(storeParams, false))
errList := errlist.New()
if globals.EnableJdStoreWrite {
errList.AddErr(a.UpdateStoreInfo4Open2(storeParams, modifyCloseStatus))
}
err = errList.GetErrListAsOne()
}
}
}
return err
}

View File

@@ -1041,8 +1041,8 @@ func updateStoresSkusWithoutSync(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
// globals.SugarLogger.Debug(utils.Format4Output(inSkuBind, false))
var skuBind *model.StoreSkuBind
if v.ID == 0 {
if v.ExdSkuID == "" {
// if !(strings.Contains(v.StoreName, model.ExdStoreName) && v.ExdSkuID == "") {
// if v.ExdSkuID == "" {
if (strings.Contains(v.StoreName, model.ExdStoreName) && v.ExdSkuID != "") || (!strings.Contains(v.StoreName, model.ExdStoreName) && v.ExdSkuID == "") {
if skuBindInfo.IsFocus == 1 && v.SkuNameStatus == model.SkuStatusNormal && v.SkuStatus == model.SkuStatusNormal && isCanChangePrice {
skuBind = &model.StoreSkuBind{
StoreID: storeID,

View File

@@ -84,6 +84,11 @@ func SyncStoreCategories(ctx *jxcontext.Context, parentTask tasksch.ITask, vendo
storeCatMap := &model.StoreSkuCategoryMap{}
storeCatMap.ID = catInfo.MapID
var failedList []*partner.StoreSkuInfoWithErr
if catInfo.IsExdSpec == model.YES {
if vendorID == model.VendorIDJD || vendorID == model.VendorIDMTWM {
return nil, err
}
}
if model.IsSyncStatusDelete(catInfo.CatSyncStatus) { // 删除
if model.IsSyncStatusDelete(catInfo.CatSyncStatus) && !dao.IsVendorThingIDEmpty(catInfo.VendorCatID) {
err = handler.DeleteStoreCategory(ctx, storeID, vendorStoreID, catInfo.VendorCatID, level)

View File

@@ -31,7 +31,7 @@ type CheckCookie struct {
Status string `json:"status"`
}
func AddOperateEvent(ctx *jxcontext.Context, accessUUID, jsonData string, errCode, errMsg string, useTime int) (err error) {
func AddOperateEvent(ctx *jxcontext.Context, accessUUID, jsonData string, errCode, errMsg string, useTime int, apiFunctionSpec string) (err error) {
var (
apiFunction string
db = dao.GetDB()
@@ -39,9 +39,13 @@ func AddOperateEvent(ctx *jxcontext.Context, accessUUID, jsonData string, errCod
if ctx.GetRequest() == nil {
return nil
}
url := ctx.GetRequest().URL.Path
if url != "" {
apiFunction = url[strings.LastIndex(url, "/")+1 : len(url)]
if apiFunctionSpec != "" {
url := ctx.GetRequest().URL.Path
if url != "" {
apiFunction = url[strings.LastIndex(url, "/")+1 : len(url)]
}
} else {
apiFunction = apiFunctionSpec
}
if apiFunction != "" {
if apiFunction[0:3] == "Get" || NoUseEventMap[apiFunction] != "" {

View File

@@ -398,6 +398,11 @@ const (
MaxVendorPricePercentage = 400
)
const (
YES = 1 //通用
NO = 0
)
func IsPurchaseVendorExist(vendorID int) bool {
_, ok := VendorNames[vendorID]
return ok && vendorID >= VendorIDPurchaseBegin && vendorID <= VendorIDPurchaseEnd

View File

@@ -70,7 +70,8 @@ func GetCategories(db *DaoDB, parentID, level int, catIDs []int, isExd bool) (ca
if isExd {
sql += " ORDER BY t1.level, t1.exd_seq"
} else {
sql += " ORDER BY t1.level, t1.seq"
sql += ` AND t1.is_exd_spec = 0
ORDER BY t1.level, t1.seq`
}
return cats, GetRows(db, &cats, sql, params)
}

View File

@@ -151,8 +151,9 @@ type SkuCategory struct {
Status int8 `orm:"default(1)" json:"status"` //分类状态0表示禁用1表示启用
Img string `orm:"size(512)" json:"img"` //分类图片
ExdName string `json:"exdName"` //饿鲜达对应分类名
ExdSeq int `json:"exdSeq"`
ExdName string `json:"exdName"` //饿鲜达对应分类名
ExdSeq int `json:"exdSeq"`
IsExdSpec int `json:"isExdSpec"` //是否是饿鲜达特有新建的分类
// JdID int64 `orm:"column(jd_id);index" json:"jdID"` // 这个是指商家自己的商品类别在京东平台上的ID
// JdSyncStatus int8 `orm:"default(2)" json:"jdSyncStatus"`
}

View File

@@ -24,6 +24,10 @@ const (
var (
sensitiveWordRegexp = regexp.MustCompile(`商品名称中含有敏感词(\[.*\])`)
categoryCheck = map[int]string{
175: "赠品专区",
18: "烧烤吧台",
}
)
func (p *PurchaseHandler) GetStoreSkusBatchSize(funcID int) (batchSize int) {
@@ -71,24 +75,29 @@ func (p *PurchaseHandler) IsErrCategoryNotExist(err error) (isNotExist bool) {
return ebaiapi.IsErrCategoryNotExist(err)
}
func getCheckExdStoreNameAndSeq(storeID int, storeCat *dao.SkuStoreCatInfo) (name string, seq int) {
func getCheckExdStoreNameAndSeq(storeID int, storeCat *dao.SkuStoreCatInfo) (name string, seq int, isCheck bool) {
store, err := dao.GetStoreDetail(dao.GetDB(), storeID, model.VendorIDEBAI)
if err != nil || store == nil {
return storeCat.Name, storeCat.Seq
return storeCat.Name, storeCat.Seq, false
}
if strings.Contains(store.Name, model.ExdStoreName) {
return storeCat.ExdName, storeCat.ExdSeq
if categoryCheck[storeCat.ID] != "" {
return storeCat.ExdName, storeCat.ExdSeq, true
} else {
return storeCat.ExdName, storeCat.ExdSeq, false
}
} else {
return storeCat.Name, storeCat.Seq
return storeCat.Name, storeCat.Seq, false
}
return name, seq
return name, seq, false
}
func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
var vendorCatID int64
if globals.EnableEbaiStoreWrite {
catName, catSeq := getCheckExdStoreNameAndSeq(storeID, storeCat)
vendorCatID, err = api.EbaiAPI.ShopCategoryCreate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.ParentVendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
if catName, catSeq, isCheck := getCheckExdStoreNameAndSeq(storeID, storeCat); !isCheck {
vendorCatID, err = api.EbaiAPI.ShopCategoryCreate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.ParentVendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
}
} else {
vendorCatID = jxutils.GenFakeID()
}
@@ -98,8 +107,9 @@ func (p *PurchaseHandler) CreateStoreCategory(ctx *jxcontext.Context, storeID in
func (p *PurchaseHandler) UpdateStoreCategory(ctx *jxcontext.Context, storeID int, vendorStoreID string, storeCat *dao.SkuStoreCatInfo) (err error) {
if globals.EnableEbaiStoreWrite {
catName, catSeq := getCheckExdStoreNameAndSeq(storeID, storeCat)
err = api.EbaiAPI.ShopCategoryUpdate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.VendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
if catName, catSeq, isCheck := getCheckExdStoreNameAndSeq(storeID, storeCat); !isCheck {
err = api.EbaiAPI.ShopCategoryUpdate(utils.Int2Str(storeID), utils.Str2Int64WithDefault(storeCat.VendorCatID, 0), formatCatName(catName), jxCatSeq2Ebai(catSeq))
}
// todo, 饿百将一个分类重复改名也会报分类名重复错特殊处理一下不过因为GetStoreCategory其实会拉取所有的门店分类是比较耗时的操作
if utils.IsErrMatch(err, "1", []string{"分类名称已经存在"}) {
if cat, err2 := p.GetStoreCategory(ctx, storeID, vendorStoreID, storeCat.Name); err2 == nil {
@@ -335,7 +345,7 @@ func genSkuParamsFromStoreSkuInfo2(storeSku *dao.StoreSkuSyncInfo, isCreate, isE
params["upc"] = storeSku.Upc
params["name"] = storeSku.Name
params["cat3_id"] = storeSku.ExdCategoryThirdID
params["category_id"] = utils.Str2Int64(storeSku.VendorCatID)
params["category_id"] = utils.Str2Int64WithDefault(storeSku.VendorCatID, 0)
}
if storeSku.DescImg != "" {
params["rtf"] = storeSku.DescImg

View File

@@ -762,7 +762,7 @@ func AutoPayForPopluarMan(ctx *jxcontext.Context) (err error) {
} else {
errCode = model.ErrCodeSuccess
}
err = event.AddOperateEvent(ctx, ctx.GetTrackInfo(), cms.BuildDiffData(mapResult), errCode, errMsg, 0)
err = event.AddOperateEvent(ctx, ctx.GetTrackInfo(), cms.BuildDiffData(mapResult), errCode, errMsg, 0, "AutoPayForPopluarMan")
return err
}

View File

@@ -1,6 +1,6 @@
appname = jx-callback
httpport = 8080
runmode = dev
runmode = alpha
autorender = false
copyrequestbody = true
EnableDocs = true

View File

@@ -431,3 +431,32 @@ func (c *SkuController) SumExianDaDepot() {
return retVal, "", err
})
}
// @Title 复制一个饿百的店的商品的价格和分类到京西饿鲜达商品
// @Description 复制一个饿百的店的商品的价格和分类到京西饿鲜达商品
// @Param token header string true "认证token"
// @Param baiduShopID formdata string true "饿百店ID"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /CopyEbaiSkuPriceToJx [post]
func (c *SkuController) CopyEbaiSkuPriceToJx() {
c.callCopyEbaiSkuPriceToJx(func(params *tSkuCopyEbaiSkuPriceToJxParams) (retVal interface{}, errCode string, err error) {
err = cms.CopyEbaiSkuPriceToJx(params.Ctx, params.BaiduShopID)
return retVal, "", err
})
}
// @Title 复制饿鲜达的门店商品到京西对应门店
// @Description 复制饿鲜达的门店商品到京西对应门店
// @Param token header string true "认证token"
// @Param baiduShopID formdata string true "饿百店ID"
// @Param storeID formdata int true "门店ID"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /CopyEbaiStoreSkusToJx [post]
func (c *SkuController) CopyEbaiStoreSkusToJx() {
c.callCopyEbaiStoreSkusToJx(func(params *tSkuCopyEbaiStoreSkusToJxParams) (retVal interface{}, errCode string, err error) {
err = cms.CopyEbaiStoreSkusToJx(params.Ctx, params.BaiduShopID, params.StoreID)
return retVal, "", err
})
}

View File

@@ -634,3 +634,16 @@ func (c *StoreController) RefreshJdLevel() {
return retVal, "", err
})
}
// @Title 同步指定京东门店
// @Description 同步京东门店
// @Param token header string true "认证token"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /SyncJdStore [post]
func (c *StoreController) SyncJdStore() {
c.callSyncJdStore(func(params *tStoreSyncJdStoreParams) (retVal interface{}, errCode string, err error) {
err = cms.UpdateJdStoreNameAll(params.Ctx)
return retVal, "", err
})
}

View File

@@ -1251,6 +1251,24 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "CopyEbaiSkuPriceToJx",
Router: `/CopyEbaiSkuPriceToJx`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "CopyEbaiStoreSkusToJx",
Router: `/CopyEbaiStoreSkusToJx`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "DeleteCategory",
@@ -1638,6 +1656,15 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"],
beego.ControllerComments{
Method: "SyncJdStore",
Router: `/SyncJdStore`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"],
beego.ControllerComments{
Method: "SyncStoresCourierInfo",