package tempop import ( "bytes" "context" "fmt" "regexp" "strings" "time" "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" "git.rosy.net.cn/jx-callback/business/partner/delivery" "github.com/360EntSecGroup-Skylar/excelize" "github.com/qiniu/api.v7/storage" "git.rosy.net.cn/baseapi/platformapi/dadaapi" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils/errlist" "git.rosy.net.cn/jx-callback/business/jxstore/cms" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/model/legacymodel" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai" "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" ) var innerDataPat *regexp.Regexp func init() { innerDataPat = regexp.MustCompile(`"result":(.*),"code":200`) } func Convert2JDSPU(ctx *jxcontext.Context, count int, isAsync, isContinueWhenError bool) (hint string, err error) { // sql := ` // SELECT t1.* // FROM sku_name t1 // LEFT JOIN sku_name t2 ON t2.link_id = t1.id AND t2.deleted_at = ? // WHERE t1.deleted_at = ? AND t1.status <> ? AND t1.is_spu = 0/* AND t1.unit = '份'*/ // AND t2.id IS NULL // ORDER BY t1.id // ` // if count > 0 { // sql += " LIMIT " + utils.Int2Str(count) // } // sqlParams := []interface{}{ // utils.DefaultTimeValue, // utils.DefaultTimeValue, // model.SkuStatusDeleted, // } // db := dao.GetDB() // var skuNameList []*model.SkuName // if err = dao.GetRows(db, &skuNameList, sql, sqlParams...); err != nil { // return "", err // } // for _, skuName := range skuNameList { // sql = ` // SELECT * // FROM sku // WHERE name_id = ? AND deleted_at = ? AND status = ?; // ` // sqlParams := []interface{}{ // skuName.ID, // utils.DefaultTimeValue, // model.SkuStatusNormal, // } // var skuList []*model.Sku // if err = dao.GetRows(db, &skuList, sql, sqlParams...); err != nil { // return "", err // } // sql = ` // SELECT t1.* // FROM sku_name_place_bind t1 // WHERE t1.name_id = ? // ` // sqlParams = []interface{}{ // skuName.ID, // } // var skuNamePlaceBindList []*model.SkuNamePlaceBind // if err = dao.GetRows(db, &skuNamePlaceBindList, sql, sqlParams...); err != nil { // return "", err // } // globals.SugarLogger.Debugf("Convert2JDSPU, skuName:%s, skuCount:%d", skuName.Name, len(skuList)) // dao.Begin(db) // skuNameNew2 := *skuName // skuNameNew := &skuNameNew2 // dao.WrapAddIDCULEntity(skuNameNew, ctx.GetUserName()) // skuNameNew.JdID = 0 // skuNameNew.LinkID = skuName.ID // skuNameNew.IsSpu = 1 // skuNameNew.JdSyncStatus = model.SyncFlagNewMask // // skuNameNew.Status = model.SkuStatusDontSale // if err = dao.CreateEntity(db, skuNameNew); err != nil { // dao.Rollback(db) // return "", err // } // if len(skuList) > 0 { // for _, sku := range skuList { // skuNew2 := *sku // skuNew := &skuNew2 // dao.WrapAddIDCULEntity(skuNew, ctx.GetUserName()) // skuNew.JdID = 0 // skuNew.LinkID = sku.ID // skuNew.NameID = skuNameNew.ID // skuNew.JdSyncStatus = model.SyncFlagNewMask // if skuNameNew.Status == model.SkuStatusDontSale { // skuNew.Status = model.SkuStatusDontSale // } // globals.SugarLogger.Debugf("Convert2JDSPU, sku:%s", utils.Format4Output(skuNew, false)) // if err = dao.CreateEntity(db, skuNew); err != nil { // dao.Rollback(db) // return "", err // } // } // for _, placeBind := range skuNamePlaceBindList { // dao.WrapAddIDCULEntity(placeBind, ctx.GetUserName()) // placeBind.NameID = skuNameNew.ID // globals.SugarLogger.Debugf("Convert2JDSPU, placeBind:%s", utils.Format4Output(placeBind, false)) // if err = dao.CreateEntity(db, placeBind); err != nil { // dao.Rollback(db) // return "", err // } // } // } // dao.Commit(db) // } // sql = ` // SELECT DISTINCT t1.* // FROM sku_name t1 // JOIN sku t2 ON t1.id = t2.name_id AND t2.jd_sync_status <> 0 AND t2.deleted_at = ? // WHERE t1.link_id > 0; // ` // skuNameList = []*model.SkuName{} // if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil { // return "", err // } // rootTask := tasksch.NewParallelTask("Convert2JDSPU", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // skuName := batchItemList[0].(*model.SkuName) // _, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName()) // return nil, err // }, skuNameList) // tasksch.ManageTask(rootTask).Run() // if !isAsync { // _, err = rootTask.GetResult(0) // } else { // hint = rootTask.ID // } return hint, err } func Change2JDSPU4Store(ctx *jxcontext.Context, storeIDs []int, step int, isAsync, isContinueWhenError bool) (hint string, err error) { // db := dao.GetDB() // if len(storeIDs) == 0 { // if err = dao.GetRows(db, &storeIDs, ` // SELECT t1.id // FROM store t1 // JOIN store_map t2 ON t2.store_id = t1.id AND t2.vendor_id = 0 AND t2.deleted_at = ? AND t2.status <> ? // WHERE t1.deleted_at = ? AND t1.status <> ? /* AND t1.city_code IN (110100, 120100, 440100, 440300, 510100)*/ // `, utils.DefaultTimeValue, model.StoreStatusDisabled, utils.DefaultTimeValue, model.StoreStatusDisabled); err != nil { // return "", err // } // } // var sql string // var sqlParams []interface{} // dao.Begin(db) // defer dao.Rollback(db) // if step == 1 { // sql = ` // DELETE t1 // FROM store_sku_bind t1 // JOIN sku t2 ON t2.id = t1.sku_id AND t2.link_id > 0 // WHERE 1 = 1 // ` // sqlParams = []interface{}{} // if len(storeIDs) > 0 { // sql += " AND store_id IN (" + dao.GenQuestionMarks(len(storeIDs)) + ")" // sqlParams = append(sqlParams, storeIDs) // } // if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err != nil { // return "", err // } // sql = ` // INSERT INTO store_sku_bind(created_at, updated_at, last_operator, deleted_at, store_id, sku_id, price, unit_price, status, ebai_id, mtwm_id, jd_sync_status, ebai_sync_status, mtwm_sync_status) // SELECT NOW(), NOW(), ?, ?, t1.store_id, t2.id, t1.price, t1.unit_price, t1.status , 0, 0, ?, ?, ? // FROM store_sku_bind t1 // JOIN sku t2 ON t2.link_id = t1.sku_id AND t2.deleted_at = ? // JOIN store t3 ON t3.id = t1.store_id // JOIN sku_name t4 ON t4.id = t2.name_id // LEFT JOIN sku_name_place_bind t5 ON t5.place_code = t3.city_code AND t5.name_id = t4.id // WHERE t1.deleted_at = ? AND (t4.is_global = 1 OR t5.id IS NOT NULL) AND t1.price > 0 // ` // sqlParams = []interface{}{ // ctx.GetUserName(), // utils.DefaultTimeValue, // // model.SkuStatusDontSale, // model.SyncFlagNewMask, // 0, //model.SyncFlagNewMask, // 0, //model.SyncFlagNewMask, // utils.DefaultTimeValue, // utils.DefaultTimeValue, // } // } else if step == 2 { // sql = ` // SELECT COUNT(*) ct // FROM store_sku_bind t1 // JOIN sku t2 ON t2.id = t1.sku_id AND t2.link_id > 0 // WHERE 1 = 1 // ` // sqlParams = []interface{}{} // if len(storeIDs) > 0 { // sql += " AND store_id IN (" + dao.GenQuestionMarks(len(storeIDs)) + ")" // sqlParams = append(sqlParams, storeIDs) // } // ct := 0 // if err = dao.GetRow(db, &ct, sql, sqlParams...); err != nil { // return "", err // } // if ct == 0 { // return "", fmt.Errorf("%s看起来还没有执行《将转化的SPU在门店上架》", utils.Format4Output(storeIDs, true)) // } // sql = ` // UPDATE store_sku_bind t1 // JOIN sku t2 ON t2.link_id = t1.sku_id // SET t1.status = 0, // t1.jd_sync_status = ? // WHERE t1.deleted_at = ? // ` // sqlParams = []interface{}{ // model.SyncFlagSaleMask | model.SyncFlagModifiedMask, // utils.DefaultTimeValue, // } // } else { // return "", fmt.Errorf("非法的step") // } // if len(storeIDs) > 0 { // sql += " AND t1.store_id IN (" + dao.GenQuestionMarks(len(storeIDs)) + ")" // sqlParams = append(sqlParams, storeIDs) // } // globals.SugarLogger.Debug(sql) // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) // var num int64 // if num, err = dao.ExecuteSQL(db, sql, sqlParams...); err != nil { // return "", err // } // globals.SugarLogger.Debug(num) // dao.Commit(db) // var skuIDs []int // if step == 1 { // sql = ` // SELECT id // FROM sku t1 // WHERE t1.link_id > 0 AND t1.deleted_at = ? // ` // sqlParams = []interface{}{ // utils.DefaultTimeValue, // } // } else if step == 2 { // sql = ` // SELECT t1.link_id // FROM sku t1 // WHERE t1.link_id > 0 AND t1.deleted_at = ? // ` // sqlParams = []interface{}{ // utils.DefaultTimeValue, // } // } // if err = dao.GetRows(db, &skuIDs, sql, sqlParams...); err != nil { // return "", err // } // hint, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, storeIDs, skuIDs, false, isAsync, isContinueWhenError) return hint, err } // func TransferLegacyJdOrder(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { // sqlBatchCount := 1000 // rootTask := tasksch.NewSeqTask("TransferLegacyJdOrder", ctx, // func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // sql := ` // SELECT t1.* // FROM jdorder t1 // LEFT JOIN goods_order_original t2 ON t2.vendor_order_id = t1.vendor_order_id // WHERE t2.id IS NULL AND LENGTH(t1.data) > 10 AND t1.cityname = 'all' // ORDER BY t1.orderstatustime // LIMIT ? // ` // db := dao.GetDB() // var jdOrderList []*legacymodel2.Jdorder // if err = dao.GetRows(db, &jdOrderList, sql, sqlBatchCount); err != nil { // return nil, err // } // if len(jdOrderList) > 0 { // task := tasksch.NewParallelTask("TransferLegacyJdOrder2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetBatchSize(40), ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // var orderDetailList []*model.GoodsOrderOriginal // for _, v := range batchItemList { // jdOrder := v.(*legacymodel2.Jdorder) // var detail map[string]interface{} // if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(jdOrder.Data, "\n", "", -1), "\r", "", -1)), &detail); err != nil { // return nil, err // } // resultList := detail["result"].(map[string]interface{})["resultList"].([]interface{}) // if len(resultList) > 0 { // originalData := resultList[0].(map[string]interface{}) // orgCode := originalData["orgCode"].(string) // if orgCode == "320406" { // orderPurchaseTime := utils.Interface2String(originalData["orderPurchaseTime"]) // if orderPurchaseTime == "" { // globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal order:%s", jdOrder.VendorOrderID) // orderPurchaseTime = utils.Interface2String(originalData["orderStartTime"]) // } // if orderPurchaseTime != "" { // orderDetail := &model.GoodsOrderOriginal{ // VendorOrderID: jdOrder.VendorOrderID, // VendorID: model.VendorIDJD, // AccountNo: orgCode, // OrderCreatedAt: utils.Str2Time(orderPurchaseTime), // OriginalData: string(utils.MustMarshal(originalData)), // } // orderDetailList = append(orderDetailList, orderDetail) // } else { // globals.SugarLogger.Debugf("TransferLegacyJdOrder abnormal2 order:%s", jdOrder.VendorOrderID) // } // } // } // } // if len(orderDetailList) > 0 { // err = dao.CreateMultiEntities(db, orderDetailList) // } // return nil, err // }, jdOrderList) // // rootTask.AddChild(task).Run() // task.Run() // _, err = task.GetResult(0) // } else { // rootTask.Cancel() // } // return nil, err // }, math.MaxInt32) // tasksch.ManageTask(rootTask).Run() // if !isAsync { // _, err = rootTask.GetResult(0) // } else { // hint = rootTask.ID // } // return hint, err // } func TransferLegacyElmOrder(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { // sqlBatchCount := 1000 // rootTask := tasksch.NewSeqTask("TransferLegacyElmOrder", ctx.GetUserName(), func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // sql := ` // SELECT t1.* // FROM elemeorder t1 // LEFT JOIN goods_order_original t2 ON t2.vendor_order_id = t1.orderid // WHERE t2.id IS NULL AND LENGTH(t1.data) > 10 // ORDER BY t1.order_created_at // LIMIT ? // ` // db := dao.GetDB() // var elmOrderList []*legacymodel2.Elemeorder // if err = dao.GetRows(db, &elmOrderList, sql, sqlBatchCount); err != nil { // return "", err // } // if len(elmOrderList) > 0 { // task := tasksch.NewParallelTask("TransferLegacyElmOrder2", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetBatchSize(40), ctx.GetUserName(), func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // var orderDetailList []*model.GoodsOrderOriginal // for _, v := range batchItemList { // elmOrder := v.(*legacymodel2.Elemeorder) // if len(elmOrder.Data) > 10 { // var detail map[string]interface{} // if err = utils.UnmarshalUseNumber([]byte(strings.Replace(strings.Replace(elmOrder.Data, "\n", "", -1), "\r", "", -1)), &detail); err != nil { // return nil, err // } // orderDetail := &model.GoodsOrderOriginal{ // VendorOrderID: elmOrder.Orderid, // VendorID: model.VendorIDELM, // AccountNo: "fakeelm", // OrderCreatedAt: utils.Str2Time(detail["activeAt"].(string)), // OriginalData: elmOrder.Data, // } // orderDetailList = append(orderDetailList, orderDetail) // } // } // if len(orderDetailList) > 0 { // err = dao.CreateMultiEntities(db, orderDetailList) // } // return nil, err // }, elmOrderList) // // rootTask.AddChild(task).Run() // task.Run() // _, err = task.GetResult(0) // } else { // rootTask.Cancel() // } // return nil, err // }, math.MaxInt32) // tasksch.ManageTask(rootTask).Run() // if !isAsync { // _, err = rootTask.GetResult(0) // } else { // hint = rootTask.ID // } return hint, err } func saveJdOrderList(existJdIDMap map[string]int, jdOrderList []interface{}, jdStoreOrderList []map[string]interface{}) (err error) { var storeOrderList []*model.TempGoodsOrderMobile for _, v := range jdStoreOrderList { order := &model.TempGoodsOrderMobile{ VendorOrderID: v["orderId"].(string), VendorID: model.VendorIDJD, AccountNo: v["venderId"].(string), OrderCreatedAt: utils.Timestamp2Time(utils.MustInterface2Int64(v["orderPaidTime"]) / 1000), Mobile: v["mobile"].(string), } storeOrderList = append(storeOrderList, order) } var orderDetailList []*model.GoodsOrderOriginal for _, v := range jdOrderList { orderMap := v.(map[string]interface{}) orderID := utils.Int64ToStr(utils.MustInterface2Int64(orderMap["orderId"])) if existJdIDMap[orderID] == 0 { orgCode := orderMap["orgCode"].(string) orderDetail := &model.GoodsOrderOriginal{ VendorOrderID: orderID, VendorID: model.VendorIDJD, AccountNo: orgCode, OrderCreatedAt: utils.Str2Time(orderMap["orderPurchaseTime"].(string)), OriginalData: string(utils.MustMarshal(orderMap)), } orderDetailList = append(orderDetailList, orderDetail) } } if len(orderDetailList) > 0 || len(storeOrderList) > 0 { db := dao.GetDB() if len(orderDetailList) > 0 { // err = dao.CreateMultiEntities(db, orderDetailList) for _, v := range orderDetailList { dao.CreateEntity(db, v) } } if len(storeOrderList) > 0 { // err = dao.CreateMultiEntities(db, storeOrderList) for _, v := range storeOrderList { dao.CreateEntity(db, v) } } } return err } func PullJdOrder(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) { var existJdIDs []string db := dao.GetDB() if err = dao.GetRows(db, &existJdIDs, ` SELECT vendor_order_id FROM goods_order_original WHERE vendor_id = ?`, model.VendorIDJD); err != nil { return "", err } existJdIDMap := make(map[string]int) for _, v := range existJdIDs { existJdIDMap[v] = 1 } pageSize := 100 hourGap := 1 gapCount := int((toTime.Sub(fromTime)-time.Hour*time.Duration(hourGap))/(time.Hour*time.Duration(hourGap)) + 1) if gapCount <= 0 { gapCount = 1 } gapList := make([]int, gapCount) for k := range gapList { gapList[k] = k } rootTask := tasksch.NewParallelTask("PullJdOrder", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(20), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { gapIndex := batchItemList[0].(int) hourIndex := gapIndex * hourGap subFromTime := fromTime.Add(time.Duration(hourIndex) * time.Hour) subToTime := fromTime.Add(time.Duration(hourIndex+hourGap) * time.Hour) if subToTime.Sub(toTime) > 0 { subToTime = toTime } if true { //gapIndex < gapCount-1 { subToTime = subToTime.Add(-1 * time.Second) // 减一秒 } commonParams := map[string]interface{}{ jdapi.KeyPageSize: pageSize, "orderPurchaseTime_begin": utils.Time2Str(subFromTime), "orderPurchaseTime_end": utils.Time2Str(subToTime), } // globals.SugarLogger.Debugf("PullJdOrder, commonParams=%s", utils.Format4Output(commonParams, false)) orderList, totalCount, err := api.JdAPI.OrderQuery(commonParams) if err != nil { return "", err } storeOrderList, err := api.JdAPI.GetStoreOrderInfoList(utils.Time2Str(subFromTime), utils.Time2Str(subToTime)) if err != nil { } if err = saveJdOrderList(existJdIDMap, orderList, storeOrderList); err != nil { return "", err } if false { globals.SugarLogger.Debugf("subFromTime:%s, subToTime:%s, totalCount:%d, len(orderList):%d", utils.Time2Str(subFromTime), utils.Time2Str(subToTime), totalCount, len(orderList)) } return nil, err }, gapList) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return hint, err } func UpdateJdOrderRealMobile(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) { return hint, err } func DeleteWrongSpu(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { // sql := ` // SELECT t1.* // FROM sku_name t1 // JOIN sku_name t2 ON t2.link_id = t1.id AND t2.deleted_at = ? // WHERE t1.deleted_at = ?; // ` // db := dao.GetDB() // var skuNameList []*model.SkuName // if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue, utils.DefaultTimeValue); err != nil { // return "", err // } // rootTask := tasksch.NewSeqTask("DeleteWrongSpu", ctx.GetUserName(), func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // _, err = cms.DeleteSkuName(ctx, skuNameList[step].ID, ctx.GetUserName()) // if err != nil { // globals.SugarLogger.Debugf("DeleteWrongSpu failed nameid:%d, name:%s, with error:%v", skuNameList[step].ID, skuNameList[step].Name, err) // err = nil // 强制忽略错误 // } // return nil, err // }, len(skuNameList)) sql := ` SELECT t1.* FROM sku_name t1 WHERE t1.deleted_at = ? AND t1.is_spu = 1 AND t1.jd_id > 0 ORDER BY t1.id ` db := dao.GetDB() var skuNameList []*model.SkuName if err = dao.GetRows(db, &skuNameList, sql, utils.DefaultTimeValue); err != nil { return "", err } rootTask := tasksch.NewSeqTask2("DeleteWrongSpu", ctx, true, func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { mapData := map[string]interface{}{ "name": skuNameList[step].Name, } _, err = cms.UpdateSkuName(ctx, skuNameList[step].ID, mapData, false) if err != nil { globals.SugarLogger.Debugf("DeleteWrongSpu failed nameid:%d, name:%s, with error:%v", skuNameList[step].ID, skuNameList[step].Name, err) } return nil, err }, len(skuNameList)) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return hint, err } type GoodsOrderOriginalEx struct { model.GoodsOrderOriginal OrderStatus int } func TransformJdSpu2Sku(ctx *jxcontext.Context, skuNameIDs []int, count int, isAsync, isContinueWhenError bool) (hint string, err error) { // sql := ` // SELECT t1.* // FROM sku_name t1 // WHERE t1.deleted_at = ? AND t1.status <> ? AND t1.is_spu = 1 AND jd_id <> 0 // ` // sqlParams := []interface{}{ // utils.DefaultTimeValue, // model.SkuStatusDeleted, // } // if len(skuNameIDs) > 0 { // sql += " AND t1.id IN (" + dao.GenQuestionMarks(len(skuNameIDs)) + ")" // sqlParams = append(sqlParams, skuNameIDs) // } // sql += " ORDER BY t1.id" // if count > 0 { // sql += " LIMIT ?" // sqlParams = append(sqlParams, count) // } // db := dao.GetDB() // var skuNameList []*model.SkuName // if err = dao.GetRows(db, &skuNameList, sql, sqlParams...); err != nil { // return "", err // } // if len(skuNameList) == 0 { // return "", fmt.Errorf("待转换的skuName为空") // } // batchSize := 40 // rootTask := tasksch.NewSeqTask2("TransformJdSpu2Sku", ctx, isContinueWhenError, // func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // var ( // locker sync.Mutex // skuIDs []int // ) // lastIndex := (step + 1) * batchSize // if lastIndex > len(skuNameList) { // lastIndex = len(skuNameList) // } // batchSkNameList := skuNameList[step*batchSize : lastIndex] // subTask := tasksch.NewParallelTask(fmt.Sprintf("TransformJdSpu2Sku:%d", step), tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, // func(subTask *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // skuName := batchItemList[0].(*model.SkuName) // if !jxutils.IsEmptyID(skuName.JdID) { // sql = ` // SELECT * // FROM sku // WHERE name_id = ? AND deleted_at = ? AND status <> ?; // ` // sqlParams := []interface{}{ // skuName.ID, // utils.DefaultTimeValue, // model.SkuStatusDeleted, // } // var skuList []*model.Sku // if err = dao.GetRows(db, &skuList, sql, sqlParams...); err != nil { // return "", err // } // globals.SugarLogger.Debugf("TransformJdSpu2Sku skuList:%s", utils.Format4Output(skuList, false)) // if len(skuList) > 0 { // for _, sku := range skuList { // locker.Lock() // skuIDs = append(skuIDs, sku.ID) // locker.Unlock() // if !jxutils.IsEmptyID(sku.JdID) { // if globals.EnableJdStoreWrite { // if err = api.JdAPI.UpdateSkuBaseInfo(utils.Int2Str(skuName.ID), utils.Int2Str(sku.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)); err != nil { // if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 11004 { // err = nil // } else { // break // } // } // } // } // } // } // if err == nil && globals.EnableJdStoreWrite { // if err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusOffline)); err == nil { // err = api.JdAPI.UpdateSpu(utils.Int2Str(skuName.ID), utils.Params2Map(jdapi.KeyFixedStatus, jdapi.SkuFixedStatusDeleted)) // } else if errExt, ok := err.(*utils.ErrorWithCode); ok && errExt.IntCode() == 11035 { // err = nil // } // } // if err == nil { // skuName.IsSpu = 0 // skuName.JdID = 0 // if _, err = dao.UpdateEntity(db, skuName, "IsSpu", "JdID"); err == nil { // sql := ` // UPDATE sku t1 // SET // t1.jd_sync_status = ?, // t1.jd_id = 0 // WHERE t1.name_id = ? AND t1.deleted_at = ? AND t1.status <> ? // ` // sqlParams := []interface{}{ // model.SyncFlagNewMask, // skuName.ID, // utils.DefaultTimeValue, // model.SkuStatusDeleted, // } // if _, err = dao.ExecuteSQL(db, sql, sqlParams...); err == nil { // _, err = cms.CurVendorSync.SyncSku(ctx, db, skuName.ID, -1, false, isContinueWhenError, ctx.GetUserName()) // } // } // } // } else { // globals.SugarLogger.Debugf("TransformJdSpu2Sku skuName:%d is fake", skuName.ID) // } // return nil, err // }, batchSkNameList) // rootTask.AddChild(subTask).Run() // if _, err = subTask.GetResult(0); err == nil { // if len(skuIDs) > 0 { // if _, err = dao.SetStoreSkuSyncStatus(db, model.VendorIDJD, nil, skuIDs, model.SyncFlagStoreSkuModifiedMask); err == nil { // // time.Sleep(20 * time.Second) // // _, err = cms.CurVendorSync.SyncStoresSkus(ctx, db, []int{model.VendorIDJD}, nil, skuIDs, false, isContinueWhenError) // } // } // } // return nil, err // }, (len(skuNameList)-1)/batchSize+1) // tasksch.ManageTask(rootTask).Run() // if !isAsync { // _, err = rootTask.GetResult(0) // } else { // hint = rootTask.ID // } return hint, err } func ReProcessJdBadComment(ctx *jxcontext.Context, isForce, isAsync, isContinueWhenError bool) (hint string, err error) { sql := ` SELECT * FROM jx_bad_comments ` if !isForce { sql += " WHERE (createtime IS NULL OR createtime = '') OR (updatetime IS NULL OR updatetime = '')" } // sql += " LIMIT 1" db := dao.GetDB() var commentList []*legacymodel.JxBadComments if err = dao.GetRows(db, &commentList, sql); err == nil { if len(commentList) > 0 { rootTask := tasksch.NewParallelTask("ReProcessJdBadComment", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { badComment := batchItemList[0].(*legacymodel.JxBadComments) comment1, _ := unmarshalCommentText(badComment.Msg) comment2, _ := unmarshalCommentText(badComment.UpdatedMsg) if len(comment1) > 0 { badComment.Createtime = utils.Timestamp2Str(utils.MustInterface2Int64(comment1["createTime"].(map[string]interface{})["time"]) / 1000) badComment.Msg = string(utils.MustMarshal(comment1)) if len(comment2) > 0 { badComment.Updatetime = utils.Timestamp2Str(utils.MustInterface2Int64(comment2["createTime"].(map[string]interface{})["time"]) / 1000) badComment.UpdatedMsg = string(utils.MustMarshal(comment2)) } _, err = dao.UpdateEntity(db, badComment) } return nil, err }, commentList) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } } } return hint, err } func unmarshalCommentText(commentStr string) (retVal map[string]interface{}, isNeedUpdate bool) { var err error for { var retVal map[string]interface{} // 必须要用局部变量 if commentStr == "" { return nil, false } if err = jxutils.Strings2Objs(commentStr, &retVal); err == nil { if retVal["data"] != nil { commentStr = retVal["data"].(string) } else if retVal["result"] != nil { return retVal["result"].(map[string]interface{}), true } else { return retVal, false } } else { strList := innerDataPat.FindStringSubmatch(commentStr) if strList[1] != "" { commentStr = strList[1] } else { return nil, false } } } } func RefreshEbaiBadComment(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) { if utils.IsTimeZero(fromTime) { fromTime = utils.Str2Time("2018-05-03 00:00:00") } if utils.IsTimeZero(toTime) { toTime = time.Now().Add(-3 * time.Hour) } days := int(toTime.Sub(fromTime)/(24*time.Hour) + 1) globals.SugarLogger.Debugf("RefreshEbaiBadComment fromTime:%s, toTime:%s, days:%d", utils.Time2Str(fromTime), utils.Time2Str(toTime), days) rootTask := tasksch.NewSeqTask("RefreshEbaiBadComment", ctx, func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { batchFromTime := fromTime.Add(time.Duration(step) * 24 * time.Hour) batchToTime := batchFromTime.Add(24*time.Hour - time.Second) if batchToTime.Sub(toTime) > 0 { batchToTime = toTime } err = ebai.CurPurchaseHandler.RefreshComment(batchFromTime, batchToTime) return nil, err }, days) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return hint, err } func PrintMsg(ctx *jxcontext.Context, vendorID int, id1, id2, msgTitle, msgContent string) (printerStatus *partner.PrinterStatus, err error) { handler := partner.GetPrinterPlatformFromVendorID(vendorID) if handler == nil { return nil, fmt.Errorf("打印机厂商:%d当前不被支持,请检查vendorID", vendorID) } return handler.PrintMsg(ctx, id1, id2, msgTitle, msgContent) } func UpdateAllWeiXinRemark(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { var mobileList []string sql := ` SELECT tel FROM weixins WHERE openid <> '' AND tel <> ''` sqlParams := []interface{}{} if globals.EnableWXAuth2 { sql = ` SELECT t1.mobile FROM user t1 JOIN auth_bind t2 ON t2.user_id = t1.user_id AND t2.deleted_at = ? and t2.type = ? WHERE t1.deleted_at = ? AND t1.type & ? <> 0` sqlParams = []interface{}{ utils.DefaultTimeValue, weixin.AuthTypeMP, utils.DefaultTimeValue, model.UserTypeStoreBoss, } } if err = dao.GetRows(dao.GetDB(), &mobileList, sql, sqlParams...); err == nil { rootTask := tasksch.NewParallelTask("刷新微信备注", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { tel := batchItemList[0].(string) err = cms.HandleUserWXRemark(dao.GetDB(), tel, false) return nil, err }, mobileList) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } } return hint, err } // 从饿百得到执照信息 func RetrieveEbaiShopLicence(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { var ebaiStoreList []*model.StoreMap db := dao.GetDB() if err = dao.GetRows(db, &ebaiStoreList, ` SELECT * FROM store_map WHERE vendor_id = ? AND deleted_at = ? `, model.VendorIDEBAI, utils.DefaultTimeValue); err == nil { globals.SugarLogger.Debugf("RetrieveEbaiShopLicence, count:%d", len(ebaiStoreList)) rootTask := tasksch.NewParallelTask("XXXX", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { ebaiStore := batchItemList[0].(*model.StoreMap) xxList, err := api.EbaiAPI.ShopAptitudeGet("", utils.Str2Int64(ebaiStore.VendorStoreID)) if err == nil && ebaiStore != nil { if len(xxList) > 1 { ebaiStore2, err2 := api.EbaiAPI.ShopGet("", utils.Str2Int64(ebaiStore.VendorStoreID)) if err = err2; err == nil { shop := &legacymodel.EbaiShopLicence{ ShopName: utils.Interface2String(ebaiStore2["name"]), Licence: utils.Interface2String(xxList[1]["license_number"]), Address: utils.Interface2String(ebaiStore2["address"]), Owner: utils.Interface2String(xxList[1]["legal_representative_name"]), Tel: utils.Interface2String(ebaiStore2["service_phone"]), LicenceName: utils.Interface2String(xxList[1]["license_name"]), } err = dao.CreateEntity(db, shop) } } } return nil, err }, ebaiStoreList) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } } return hint, err } func RefreshMtpsWaybillFee(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { var waybillList []*model.Waybill db := dao.GetDB() if err = dao.GetRows(db, &waybillList, ` SELECT * FROM waybill WHERE status_time > '2019-04-01' AND waybill_vendor_id = 102 AND desired_fee = 0 `); err == nil { globals.SugarLogger.Debugf("RefreshMtpsWaybillFee, count:%d", len(waybillList)) rootTask := tasksch.NewParallelTask("RefreshMtpsWaybillFee", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { bill := batchItemList[0].(*model.Waybill) bill.DesiredFee, _ = delivery.CalculateBillDeliveryFee(bill) _, err = dao.UpdateEntity(db, bill, "DesiredFee") return nil, err }, waybillList) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } } return hint, err } func CreateConsumerFromOrders(ctx *jxcontext.Context, vendorIDs []int, fromDate, toDate time.Time, isForce, isAsync, isContinueWhenError bool) (hint string, err error) { if utils.IsTimeZero(fromDate) { return "", fmt.Errorf("fromDate必须指定") } if utils.IsTimeZero(toDate) { toDate = time.Now() } fromDate = utils.Time2Date(fromDate) toDate = utils.Time2Date(toDate) if len(vendorIDs) == 0 { vendorIDs = partner.GetPurchasePlatformVendorIDs() } var dateList []time.Time curDate := fromDate for { if toDate.Sub(curDate) < 0 { break } dateList = append(dateList, curDate) curDate = curDate.Add(24 * time.Hour) } type GoodsOrderWithOriginal struct { model.GoodsOrder OriginalData string `orm:"type(text)" json:"-"` } db := dao.GetDB() rootTask := tasksch.NewParallelTask("从订单中创建消费者账户", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { curDate := batchItemList[0].(time.Time) sql := ` SELECT t1.*, t2.original_data FROM goods_order t1 LEFT JOIN goods_order_original t2 ON t2.vendor_order_id = t1.vendor_order_id AND t2.vendor_id = t1.vendor_id WHERE t1.order_created_at >= ? AND t1.order_created_at < ?` sqlParams := []interface{}{ curDate, curDate.Add(24 * time.Hour), } if len(vendorIDs) > 0 { sql += " AND t1.vendor_id IN (" + dao.GenQuestionMarks(len(vendorIDs)) + ")" sqlParams = append(sqlParams, vendorIDs) } if !isForce { sql += " AND t1.user_id = ''" } var orderList []*GoodsOrderWithOriginal if err = dao.GetRows(db, &orderList, sql, sqlParams...); err == nil { if len(orderList) > 0 { // 并发必须是1,否则在HandleOrder4Consignee中可能导致主键重,错误 subTask := tasksch.NewParallelTask(fmt.Sprintf("处理日期:%s的订单", utils.Time2DateStr(curDate)), tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { order := batchItemList[0].(*GoodsOrderWithOriginal) if isForce || order.UserID == "" { if handler := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID); handler != nil { var updateFields []string if isForce || order.VendorUserID == "" { var order2 *model.GoodsOrder if order.OriginalData != "" { var orderData map[string]interface{} if utils.UnmarshalUseNumber([]byte(order.OriginalData), &orderData) == nil { order2 = handler.Map2Order(orderData) if order2.VendorUserID == "" { order2 = nil } } } if order2 == nil && order.VendorID == model.VendorIDMTWM && time.Now().Sub(curDate) < 60*24*time.Hour { order2, err = handler.GetOrder(order.VendorOrgCode, order.VendorOrderID) } if order2 != nil { if order2.VendorUserID != "" && order.VendorUserID != order2.VendorUserID { updateFields = append(updateFields, "VendorUserID") order.VendorUserID = order2.VendorUserID } } } /* if err = cms.HandleOrder4Consignee(&order.GoodsOrder); err == nil { updateFields = append(updateFields, "UserID") } */ if len(updateFields) > 0 { dao.UpdateEntity(db, &order.GoodsOrder, updateFields...) } } } return nil, err }, orderList) tasksch.HandleTask(subTask, task, true).Run() _, err = subTask.GetResult(0) } } return nil, err }, dateList) tasksch.HandleTask(rootTask, nil, true).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return hint, err } func CheckImages(ctx *jxcontext.Context, isAsync, isContinueWhenError bool) (hint string, err error) { // db := dao.GetDB() // rootTask := tasksch.NewSeqTask("检查图片的有效性", ctx, // func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { // switch step { // case 0: // 检查图片的格式与大小 // var imgList []*model.DataResource // if err = dao.GetRows(db, &imgList, ` // SELECT t1.* // FROM data_resource t1 // WHERE t1.use_type = 1 // `); err == nil && len(imgList) > 0 { // calcTask := tasksch.NewParallelTask("检查京西图片的有效性", // tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // dataRes := batchItemList[0].(*model.DataResource) // binaryData, hashCode, err2 := jxutils.DownloadFileByURL(dataRes.MainURL) // if err = err2; err == nil { // errMsg := "" // if hashCode != dataRes.HashCode { // errMsg = fmt.Sprintf("hashcode:%s", hashCode) // dataRes.HashCode = hashCode // } // resType := http.DetectContentType(binaryData) // if resType != dataRes.ResourceType { // errMsg += "," + resType // dataRes.ResourceType = resType // } // var img image.Image // if dataRes.ResourceType == "image/png" { // img, err = png.Decode(bytes.NewReader(binaryData)) // } else if dataRes.ResourceType == "image/jpeg" { // img, err = jpeg.Decode(bytes.NewReader(binaryData)) // } // if err == nil { // if img != nil { // if img.Bounds().Dx() != 800 || img.Bounds().Dy() != 800 { // errMsg += fmt.Sprintf(",size:%dx%d", img.Bounds().Dx(), img.Bounds().Dy()) // } // } // } else { // errMsg += "," + err.Error() // } // if errMsg != "" { // dataRes.Remark = errMsg // dao.UpdateEntity(dao.GetDB(), dataRes, "Remark", "ResourceType", "HashCode") // } // } // return retVal, err // }, imgList) // tasksch.HandleTask(calcTask, task, false).Run() // _, err = calcTask.GetResult(0) // } // case 1: // 检查京东商品图片 // skuNameInfo, err2 := cms.GetSkuNames(ctx, "", false, map[string]interface{}{}, 0, -1) // if err = err2; err == nil && len(skuNameInfo.SkuNames) > 0 { // calcTask := tasksch.NewParallelTask("检查京东图片的有效性", // tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError).SetParallelCount(5), ctx, // func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { // skuName := batchItemList[0].(*model.SkuNameExt) // for _, sku := range skuName.Skus { // if sku.JdID != 0 { // skuPageInfo, err2 := api.JdAPI.GetSkuPageInfo(sku.JdID) // if err = err2; err == nil && skuPageInfo.FixedStatus && len(skuPageInfo.Image) == 0 { // err = fmt.Errorf("skuName:%d, sku:%d, jdid:%d, 没有图片", skuName.ID, sku.ID, sku.JdID) // skuName.ImgHashCode = "np" // dao.UpdateEntity(dao.GetDB(), &skuName.SkuName, "ImgHashCode") // } // break // } // } // return retVal, err // }, skuNameInfo.SkuNames) // tasksch.HandleTask(calcTask, task, false).Run() // _, err = calcTask.GetResult(0) // } // } // return result, err // }, 2) // tasksch.HandleTask(rootTask, nil, true).Run() // if !isAsync { // if _, err = rootTask.GetResult(0); err == nil { // hint = "1" // } // } else { // hint = rootTask.ID // } return hint, err } func fixMtwmCategoryList(cats []*partner.BareCategoryInfo, vendorStoreID string, name2CatMap map[string]*model.SkuCategory, id2CatMap map[int]*model.SkuCategory) (err error) { errList := errlist.New() for _, v := range cats { // 深度优先,先处理底层次的分类 errList.AddErr(fixMtwmCategoryList(v.Children, vendorStoreID, name2CatMap, id2CatMap)) var cat *model.SkuCategory var catCodeStr string rFilterCatName := utils.FilterEmoji(v.Name) if rCatCode := int(utils.Str2Int64WithDefault(v.VendorCatID, 0)); rCatCode > 0 { catCodeStr = utils.Int2Str(rCatCode) if catCodeStr == v.VendorCatID { // 防止带有数字分类名误被认为是catCode cat = id2CatMap[rCatCode] } else { catCodeStr = "" } } if cat == nil { cat = name2CatMap[rFilterCatName] } if cat != nil { if v.Name != cat.Name || v.VendorCatID != utils.Int2Str(cat.ID) { errList.AddErr(api.MtwmAPI.RetailCatUpdate(vendorStoreID, cat.Name, &mtwmapi.Param4UpdateCat{ CategoryCodeOrigin: catCodeStr, CategoryNameOrigin: v.Name, CategoryCode: utils.Int2Str(cat.ID), Sequence: v.Seq, })) } } else if rFilterCatName != v.Name { errList.AddErr(api.MtwmAPI.RetailCatUpdate(vendorStoreID, rFilterCatName[:len(rFilterCatName)-2], &mtwmapi.Param4UpdateCat{ CategoryCodeOrigin: catCodeStr, CategoryNameOrigin: v.Name, Sequence: v.Seq, })) } } return errList.GetErrListAsOne() } func FixMtwmCategory(ctx *jxcontext.Context, mtwmStoreIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { id2CatMap := make(map[int]*model.SkuCategory) name2CatMap := make(map[string]*model.SkuCategory) var mtwmIDMap map[string]int if len(mtwmStoreIDs) > 0 { mtwmIDMap = make(map[string]int) for _, v := range mtwmStoreIDs { mtwmIDMap[utils.Int2Str(v)] = 1 } } task := tasksch.NewParallelTask("修复美团分类信息", tasksch.NewParallelConfig().SetParallelCount(1), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { step := batchItemList[0].(int) switch step { case 0: var catList []*model.SkuCategory sql := ` SELECT * FROM sku_category t1 WHERE t1.deleted_at = ? ` db := dao.GetDB() if err = dao.GetRows(db, &catList, sql, utils.DefaultTimeValue); err != nil { return nil, err } for _, v := range catList { v.Name = utils.FilterEmoji(v.Name) id2CatMap[v.ID] = v name2CatMap[v.Name] = v } case 1: storeIDs, err := mtwm.CurPurchaseHandler.GetAllStoresVendorID(ctx, "") if err != nil { return nil, err } subTask := tasksch.NewParallelTask("修复美团分类信息2", tasksch.NewParallelConfig().SetParallelCount(5).SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeID := batchItemList[0].(string) if mtwmIDMap == nil || mtwmIDMap[storeID] == 1 { catList, err := mtwm.CurPurchaseHandler.GetStoreAllCategories(ctx, 0, storeID) if err == nil { err = fixMtwmCategoryList(catList, storeID, name2CatMap, id2CatMap) } } return retVal, err }, storeIDs) tasksch.HandleTask(subTask, task, true).Run() _, err = subTask.GetResult(0) } 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 JdStoreInfo1125() (hint string, err error) { fileName := "老格恢复拓店进度.xlsx" db := dao.GetDB() storeList, err := dao.GetStoresMapList(db, []int{model.VendorIDJD}, nil, nil, model.StoreStatusAll, model.StoreIsSyncYes, "", "") if err == nil { var validStoreList []*dao.StoreDetail for _, v := range storeList { if v.Status != model.StoreStatusDisabled && v.CreatedAt.Sub(utils.Str2Time("2019-10-01")) > 0 { storeInfo, err := api.JdAPI.GetStoreInfoByStationNo2(v.VendorStoreID) if err == nil && storeInfo.CreateTime.GoTime().Sub(utils.Str2Time("2019-10-25")) > 0 { if storeDetail, err := dao.GetStoreDetail(db, v.StoreID, v.VendorID); err == nil { validStoreList = append(validStoreList, storeDetail) } } } } getStoreList := func(lng, lat, lng2, lat2 int) (vendorStoreIDs []string) { for _, v := range validStoreList { if v.Lng >= lng && v.Lng <= lng2 && v.Lat >= lat && v.Lat <= lat2 { vendorStoreIDs = append(vendorStoreIDs, v.VendorStoreID) } } return vendorStoreIDs } sheetName := "老格明细" file, err2 := excelize.OpenFile(fileName) if err = err2; err == nil { // globals.SugarLogger.Debug(err, file) rows, err2 := file.GetRows(sheetName) if err = err2; err == nil { str2Coords := func(str string) (lng, lat int) { list := strings.Split(str, ",") if len(list) >= 2 { lng, lat = jxutils.StandardCoordinate2Int(utils.Str2Float64WithDefault(list[1], 0)), jxutils.StandardCoordinate2Int(utils.Str2Float64WithDefault(list[0], 0)) } return lng, lat } for i := 1; i < len(rows); i++ { lng, lat := str2Coords(rows[i][8]) lng2, lat2 := str2Coords(rows[i][7]) vendorStoreIDs := getStoreList(lng, lat, lng2, lat2) // fmt.Printf("%d,%v", i, vendorStoreIDs) countInfo := fmt.Sprintf("京西已拓%d", len(vendorStoreIDs)) axis, _ := excelize.CoordinatesToCellName(5, i+1) file.SetCellStr(sheetName, axis, countInfo) axis2, _ := excelize.CoordinatesToCellName(6, i+1) file.SetCellStr(sheetName, axis2, strings.Join(vendorStoreIDs, ",")) } file.SaveAs("ffff.xlsx") } } } return hint, err } func BuildSkuFromEbaiStore(ctx *jxcontext.Context, baiduShopID int64, isAsync, isContinueWhenError bool) (hint string, err error) { ebaiCatIDKey := "ebaiCatID" catList, err := api.EbaiAPI.PageGetCustomCatList(baiduShopID) if err != nil { return hint, err } catMap := make(map[string]map[string]interface{}) allSkuInfo := make(map[string]map[string]map[string]map[string]interface{}) for _, cat := range catList { catName := utils.Interface2String(cat["cat_name"]) if catName == "限时特惠" || catName == "应季热销" { catName = "应季水果" } skuNameMap := allSkuInfo[catName] if skuNameMap == nil { skuNameMap = make(map[string]map[string]map[string]interface{}) allSkuInfo[catName] = skuNameMap } if catMap[catName] == nil { catMap[catName] = cat } skuList, err2 := api.EbaiAPI.PageGetCustomSkuList(baiduShopID, utils.Str2Int64(utils.Interface2String(cat["cat_id"]))) if err = err2; err != nil { return hint, err } for _, sku := range skuList { _, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(sku["upc_name"].(string)) if specQuality > 0 { if catMap[catName][ebaiCatIDKey] == nil { catMap[catName][ebaiCatIDKey] = utils.Interface2String(sku["cat3_id"]) } skuNameKey := sku["photos"].([]interface{})[0].(map[string]interface{})["url"].(string) if skuNameMap[skuNameKey] == nil { skuNameMap[skuNameKey] = make(map[string]map[string]interface{}) } skuNameMap[skuNameKey][fmt.Sprintf("%f.%s", specQuality, specUnit)] = sku } } } allSkuInfo2 := make(map[*model.SkuCategory][]*model.SkuNameExt) catSeq := 0 for catName, catSkuNameMap := range allSkuInfo { if len(catSkuNameMap) > 0 { skuCat := &model.SkuCategory{ Name: catName, ParentID: 0, Level: 1, Type: model.SkuCategoryNormal, Seq: catSeq, EbaiCategoryID: utils.Str2Int64(utils.Interface2String(catMap[catName][ebaiCatIDKey])), } catSeq++ for _, skuList := range catSkuNameMap { var skuNameExt *model.SkuNameExt for _, sku := range skuList { prefix, name, comment, specUnit, unit, specQuality := jxutils.SplitSkuName(sku["upc_name"].(string)) if skuNameExt == nil { skuNameExt = &model.SkuNameExt{ SkuName: model.SkuName{ Prefix: prefix, Name: name, // CategoryID: IsGlobal: 1, Unit: unit, SpecQuality: specQuality, SpecUnit: specUnit, Price: int(jxutils.StandardPrice2Int(utils.MustInterface2Float64(sku["sale_price"]))), Img: sku["photos"].([]interface{})[0].(map[string]interface{})["url"].(string), Status: model.SkuStatusNormal, IsSpu: 0, }, } if len(skuList) > 1 { skuNameExt.Unit = "份" skuNameExt.SpecQuality = 500 skuNameExt.SpecUnit = "g" } if skuNameExt.Unit == "份" { tmpSpecQuality := specQuality if specUnit == "kg" || specUnit == "l" { tmpSpecQuality *= 1000 } skuNameExt.Price = int(float32(skuNameExt.Price) * 500 / tmpSpecQuality) } } mySku := &model.SkuWithVendor{ Sku: &model.Sku{ // CategoryID: // NameID: Comment: comment, SpecQuality: specQuality, SpecUnit: specUnit, Weight: int(utils.Str2Int64(utils.Interface2String(sku["weight"]))), Status: model.SkuStatusNormal, SkuIndex: int(jxutils.StandardPrice2Int(utils.MustInterface2Float64(sku["sale_price"]))), // 临时传递价格用 }, } if sku["enabled"].(string) == "0" { mySku.Status = model.SkuStatusDontSale } skuNameExt.Skus = append(skuNameExt.Skus, mySku) } allSkuInfo2[skuCat] = append(allSkuInfo2[skuCat], skuNameExt) } } } startOutSkuID := 1000 var skuCatList []*model.SkuCategory for cat := range allSkuInfo2 { skuCatList = append(skuCatList, cat) } putPolicy := storage.PutPolicy{ Scope: globals.QiniuBucket, // Expires: 10 * 60, } cfg := &storage.Config{} upToken := putPolicy.UploadToken(api.QiniuAPI) rootTask := tasksch.NewSeqTask("BuildSkuFromEbaiStore", ctx, func(rootTask *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { var catID string cat := skuCatList[step] skuNameExtList := allSkuInfo2[cat] catID, err = addShopCategory(0, cat.Name, int(cat.Level), cat.Seq, ctx.GetUserName()) if err == nil { shopCategories := []int64{utils.Str2Int64(catID)} for _, skuNameExt := range skuNameExtList { var imgContent []byte skuNameExt.CategoryID = cat.ID skuNameExt.Img = strings.Replace(skuNameExt.Img, "https://", "http://", 1) if imgContent, _, err = jxutils.DownloadFileByURL(skuNameExt.Img); err != nil { globals.SugarLogger.Infof("download pic %s failed with error:%v", skuNameExt.Img, err) if !isContinueWhenError { return nil, err } err = nil continue } formUploader := storage.NewFormUploader(cfg) ret := storage.PutRet{} key := jxutils.GenPicFileName(".jpeg") for i := 0; i < 3; i++ { if err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(imgContent), int64(len(imgContent)), &storage.PutExtra{}); err == nil { break } } if err != nil { globals.SugarLogger.Infof("upload pic %s failed with error:%v", skuNameExt.Img, err) if !isContinueWhenError { return nil, err } err = nil continue } qiniuImgURL := jxutils.ComposeQiniuResURL(key) + "?imageMogr2/thumbnail/x800/gravity/Center/crop/800x800" for _, sku := range skuNameExt.Skus { jdCatID := 22410 // 其他国产水果 if cat.Name == "进口水果" { jdCatID = 20342 // 其他进口水果 } price := sku.SkuIndex skuName := jxutils.ComposeSkuNameOriginal(skuNameExt.Prefix, skuNameExt.Name, sku.Comment, skuNameExt.Unit, sku.SpecQuality, sku.SpecUnit, jdapi.MaxSkuNameCharCount) fixedStatus := 1 if sku.Status != model.SkuStatusNormal { fixedStatus = 2 } var vendorSkuID string vendorSkuID, err = addSku(utils.Int2Str(startOutSkuID), jdCatID, shopCategories, jd.DefBrandID, skuName, price, jxutils.IntWeight2Float(sku.Weight), []string{qiniuImgURL}, fixedStatus, true, nil) if err == nil { globals.SugarLogger.Debugf("vendorSkuID=%s", vendorSkuID) } else { globals.SugarLogger.Infof("create %s failed with error:%v", skuName, err) if !isContinueWhenError { return nil, err } err = nil } // fmt.Printf("%s,[%s]%s-%f-%s, %s, %s\n", cat.Name, skuNameExt.Prefix, skuNameExt.Name, skuNameExt.SpecQuality, skuNameExt.SpecUnit, qiniuImgURL, skuName) startOutSkuID++ // rootTask.Cancel() // return nil, nil } } } else { return nil, err } return nil, err }, len(skuCatList)) tasksch.ManageTask(rootTask).Run() if !isAsync { _, err = rootTask.GetResult(0) } else { hint = rootTask.ID } return hint, err } func addShopCategory(pid int64, shopCategoryName string, shopCategoryLevel, sort int, userName string) (catId string, err error) { // globals.SugarLogger.Debug(pid, shopCategoryName, shopCategoryLevel, sort, userName) // return "123", err return api.JdAPI.AddShopCategory(pid, shopCategoryName, shopCategoryLevel, sort, userName) } func addSku(outSkuId string, cagtegoryId int, shopCategories []int64, brandId int, skuName string, skuPrice int, weight float32, images []string, fixedStatus int, isSale bool, addParams map[string]interface{}) (skuId string, err error) { // globals.SugarLogger.Debug(outSkuId, cagtegoryId, shopCategories, brandId, skuName, skuPrice, weight, images, fixedStatus, isSale, addParams) // return "456", err return api.JdAPI.AddSku(outSkuId, cagtegoryId, shopCategories, brandId, skuName, skuPrice, weight, images, fixedStatus, isSale, addParams) } func UploadJdsImage(ctx *jxcontext.Context) (err error) { // db := dao.GetDB() // result1, _ := api.JdShopAPI.GetProvince() // for _, v := range result1 { // place1, _ := dao.GetPlaceByName(db, v.AreaName, 1, 0) // place1.JdsCode = v.AreaID // dao.UpdateEntity(db, place1, "JdsCode") // result2, _ := api.JdShopAPI.GetCity(v.AreaID) // for _, vv := range result2 { // place2, _ := dao.GetPlaceByName(db, vv.AreaName, 2, 0) // place2.JdsCode = vv.AreaID // dao.UpdateEntity(db, place2, "JdsCode") // place22, _ := dao.GetPlaceByName(db, vv.AreaName, 3, 0) // if place22 != nil { // place22.JdsCode = vv.AreaID // dao.UpdateEntity(db, place22, "JdsCode") // } // result3, _ := api.JdShopAPI.GetCounty(vv.AreaID) // for _, vvv := range result3 { // place3, _ := dao.GetPlaceByName(db, vvv.AreaName, 3, 0) // place3.JdsCode = vvv.AreaID // dao.UpdateEntity(db, place3, "JdsCode") // } // } // } //京东商城商品不同 // type tTmp struct { // SkuID int `json:"skuID"` // Reason string `json:"reason"` // } // var vendorMap = make(map[int]*partner.SkuNameInfo) // var localMap = make(map[int]*model.StoreSkuBind) // var addList, deleteList []int // var updateList []*tTmp // vendorStock2JxStatus := func(stock int) (status int) { // if stock > 0 { // return model.StoreSkuBindStatusNormal // } else { // return model.StoreSkuBindStatusDontSale // } // } // handler := partner.GetPurchasePlatformFromVendorID(model.VendorIDJDShop).(partner.ISingleStoreStoreSkuHandler) // skuNameList, err := handler.GetStoreSkusFullInfo(ctx, nil, 0, "", nil) // storeSkuList, err := dao.GetStoresSkusInfo(dao.GetDB(), []int{model.JdShopMainStoreID}, nil) // for _, v := range skuNameList { // vendorMap[v.SkuList[0].SkuID] = v // } // for _, v := range storeSkuList { // if vendorMap[v.SkuID] == nil { // if v.Status == model.StoreSkuBindStatusNormal { // addList = append(addList, v.SkuID) // } // } else { // if int64(v.JdsPrice) != vendorMap[v.SkuID].SkuList[0].VendorPrice { // updateList = append(updateList, &tTmp{ // SkuID: v.SkuID, // Reason: "价格不同", // }) // } // if v.Status != vendorStock2JxStatus(vendorMap[v.SkuID].SkuList[0].Stock) { // updateList = append(updateList, &tTmp{ // SkuID: v.SkuID, // Reason: "库存可售不同", // }) // } // skus, _ := dao.GetSkus(dao.GetDB(), []int{v.SkuID}, nil, nil, nil, nil) // if skus[0].Comment != "" { // if skus[0].Comment != vendorMap[v.SkuID].SkuList[0].Comment { // updateList = append(updateList, &tTmp{ // SkuID: v.SkuID, // Reason: "备注与销售属性不同", // }) // } // } // } // localMap[v.SkuID] = v // } // for k, _ := range vendorMap { // if localMap[k] == nil { // deleteList = append(deleteList, k) // } // } // fmt.Println("addList2", addList) // fmt.Println("updateList2", utils.Format4Output(updateList, false)) // fmt.Println("deleteList2", deleteList) var ( db = dao.GetDB() ) list, err := dao.GetStoreCourierList(db, nil, []int{model.VendorIDDada}, model.StoreStatusAll, model.StoreAuditStatusAll) for _, v := range list { sd, _ := api.DadaAPI.ShopDetail(v.VendorStoreID) if !strings.Contains(sd.StationName, globals.StoreName) { shopInfo := &dadaapi.ShopInfo{ OriginShopID: v.VendorStoreID, StationName: globals.StoreName + "-" + sd.StationName, } api.DadaAPI.ShopUpdate(shopInfo) } } return err } func RefreshJXPriceChange(ctx *jxcontext.Context, storeID int) (hint string, err error) { db := dao.GetDB() var ( stores []*model.Store vendorIDs = []int{0, 1, 3, 5, 9} isAsync = true isContinueWhenError = true ) sql := ` SELECT * FROM store WHERE deleted_at = ? AND pay_percentage > 50 ` sqlParams := []interface{}{utils.DefaultTimeValue} if storeID != 0 { sql += " AND id = ?" sqlParams = append(sqlParams, storeID) } err = dao.GetRows(db, &stores, sql, sqlParams) task := tasksch.NewParallelTask("刷新门店价格", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { store := batchItemList[0].(*model.Store) var skuBindInfos []*cms.StoreSkuBindInfo for _, v := range vendorIDs { storeMaps, _ := dao.GetStoresMapList(db, []int{v}, []int{store.ID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "") if len(storeMaps) > 0 { storeMap := storeMaps[0] switch v { case model.VendorIDJD: storeMap.PricePercentagePack = "京东测试报价=结算价" dao.UpdateEntity(db, storeMap, "PricePercentagePack") case model.VendorIDEBAI: storeMap.PricePercentagePack = "美团测试报价=结算价" dao.UpdateEntity(db, storeMap, "PricePercentagePack") case model.VendorIDMTWM: storeMap.PricePercentagePack = "饿百测试报价=结算价" dao.UpdateEntity(db, storeMap, "PricePercentagePack") case model.VendorIDJDShop: storeMap.PricePercentagePack = "京西100-100" dao.UpdateEntity(db, storeMap, "PricePercentagePack") case model.VendorIDJX: storeMap.PricePercentagePack = "京西100-100" dao.UpdateEntity(db, storeMap, "PricePercentagePack") } } } storeSkus, err := dao.GetStoresSkusInfo(db, []int{store.ID}, nil) for _, v := range storeSkus { skuAndName, _ := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil) skuBindInfo := &cms.StoreSkuBindInfo{ // StoreID: store.ID, NameID: skuAndName[0].NameID, UnitPrice: v.UnitPrice * store.PayPercentage / 100, } skuBindInfos = append(skuBindInfos, skuBindInfo) } // cms.UpdateStoresSkusByBind(ctx, task, skuBindInfos, isAsync, isContinueWhenError, false) cms.UpdateStoresSkusWithoutSync(ctx, []int{store.ID}, skuBindInfos, false) store.PayPercentage = 100 dao.UpdateEntity(db, store, "PayPercentage") return retVal, err }, stores) tasksch.HandleTask(task, nil, true).Run() if isAsync { hint = task.GetID() } else { _, err = task.GetResult(0) hint = "1" } return hint, err }