package dao import ( "fmt" "time" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals" ) var ( imgFieldMap = map[int]string{ model.VendorIDWSC: "img_weimob", model.VendorIDEBAI: "img_ebai", } descImgFieldMap = map[int]string{ model.VendorIDEBAI: "desc_img_ebai", } ) type SkuStoreCatInfo struct { model.SkuCategory MapID int `orm:"column(map_id)"` // 这个主要用于判断是否有store_sku_category_map VendorCatID string `orm:"column(vendor_cat_id)"` StoreCatSyncStatus int8 ParentCatName string ParentMapID int `orm:"column(parent_map_id)"` // 这个主要用于判断是否有父store_sku_category_map ParentVendorCatID string `orm:"column(parent_vendor_cat_id)"` ParentCatSyncStatus int8 } type StoreSkuSyncInfo struct { // 平台无关的store sku信息 BindID int `orm:"column(bind_id)"` // 换名的原因是与Sku.ID同名区别 StoreID int `orm:"column(store_id)"` SkuID int `orm:"column(sku_id)"` // 这个与Sku.ID的区别是SkuID是必然存在的 Price int64 UnitPrice int64 // 平台相关的store sku信息 StoreSkuStatus int StoreSkuSyncStatus int8 VendorSkuID string `orm:"column(vendor_sku_id)"` model.Sku // sku_name Prefix string NameID int `orm:"column(name_id)"` VendorNameID string `orm:"column(vendor_name_id)"` Name string Unit string Upc string // 平台相关的图片信息 Img string DescImg string VendorVendorCatID int64 `orm:"column(vendor_vendor_cat_id)"` // 平台商品分类(叶子结点) VendorVendorCatID2 int64 `orm:"column(vendor_vendor_cat_id2)"` // 平台商品分类上一级 VendorVendorCatID3 int64 `orm:"column(vendor_vendor_cat_id3)"` // 平台商品分类再上一级 // sku的商家分类信息 SkuStoreCatSyncStatus int8 SkuVendorCatID string `orm:"column(sku_vendor_cat_id)"` // sku_name的商家分类信息 StoreCatSyncStatus int8 VendorCatID string `orm:"column(vendor_cat_id)"` CatPricePercentage int VendorPrice int64 MergedStatus int SkuName string } type MissingStoreSkuInfo struct { StoreID int `orm:"column(store_id)"` NameID int `orm:"column(name_id)"` SkuID int `orm:"column(sku_id)"` SpecQuality float32 SpecUnit string Unit string RefPrice int } type StoreSkuBindWithVendorInfo struct { model.StoreSkuBind VendorStoreID string `orm:"column(vendor_store_id)"` VendorSkuID string `orm:"column(vendor_sku_id)"` } // 单门店模式厂商适用 // 从store_sku_bind中,得到所有依赖的商家分类信息 func GetSkusCategories(db *DaoDB, vendorID, storeID int, skuIDs []int, level int) (cats []*SkuStoreCatInfo, err error) { sql := ` SELECT DISTINCT t4.*, t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status store_cat_sync_status, t4p.name parent_cat_name, t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status FROM store_sku_bind t1 JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? AND t2.status = ? JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ? ` if level == 2 { sql += ` JOIN sku_category t4 ON (t3.category_id = t4.id OR t2.category_id = t4.id) AND t4.level = 2 AND t4.deleted_at = ? ` } else { sql += ` LEFT JOIN sku_category t4c ON (t3.category_id = t4c.id OR t2.category_id = t4c.id) JOIN sku_category t4 ON (t4.id = t4c.parent_id OR (t3.category_id = t4.id OR t2.category_id = t4.id)) AND t4.level = 1 AND t4.deleted_at = ? ` } sql += ` LEFT JOIN store_sku_category_map t5 ON t4.id = t5.category_id AND t5.store_id = t1.store_id AND t5.deleted_at = ? LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5p.store_id = t1.store_id AND t5p.deleted_at = ? WHERE t1.deleted_at = ? AND t1.store_id = ? AND t1.status = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, storeID, model.SkuStatusNormal, } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql = fmt.Sprintf(sql, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix) if err = GetRows(db, &cats, sql, sqlParams...); err != nil { return nil, err } return cats, err } // 单门店模式厂商适用 // 单纯的从已经创建的store_sku_category_map中,得到相关的同步信息 func GetStoreCategories(db *DaoDB, vendorID, storeID int, level int) (cats []*SkuStoreCatInfo, err error) { fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := fmt.Sprintf(` SELECT t4.*, t5.id map_id, t5.%s_id vendor_cat_id, t5.%s_sync_status store_cat_sync_status, t4p.name parent_cat_name, t5p.id parent_map_id, t5p.%s_id parent_vendor_cat_id, t5p.%s_sync_status parent_cat_sync_status FROM store_sku_category_map t5 JOIN sku_category t4 ON t5.category_id = t4.id AND t4.deleted_at = ? LEFT JOIN sku_category t4p ON t4.parent_id = t4p.id LEFT JOIN store_sku_category_map t5p ON t4p.id = t5p.category_id AND t5.store_id = t5p.store_id AND t5p.deleted_at = ? WHERE t5.store_id = ? AND t4.level = ? AND t5.%s_sync_status <> 0 AND t5.deleted_at = ? `, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix) if err = GetRows(db, &cats, sql, utils.DefaultTimeValue, utils.DefaultTimeValue, storeID, level, utils.DefaultTimeValue); err != nil { return nil, err } return cats, err } // 以store_sku_bind为基础来做同步,正常情况下使用 // 单多门店模式厂商通用 func GetStoreSkus2(db *DaoDB, vendorID, storeID int, skuIDs []int, isDirty bool) (skus []*StoreSkuSyncInfo, err error) { if vendorID < 0 { panic("vendorID<0") } isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1 tableName := "t1" if !isSingleStorePF { tableName = "t2" } vendorSkuNameField := "0" if vendorID == model.VendorIDWSC { vendorSkuNameField = "t1.wsc_id2" } fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` SELECT t1.id bind_id, t1.sku_id, t1.price, t1.unit_price, t1.status store_sku_status, %s.%s_id vendor_sku_id, t1.%s_sync_status store_sku_sync_status, %s vendor_name_id, t1.store_id, t2.*, t3.id name_id, t3.prefix, t3.name, t3.unit, IF(t3.%s <> '', t3.%s, t3.img) img, t3.upc, t3.%s desc_img, t4.%s_category_id vendor_vendor_cat_id, t4.%s_price_percentage cat_price_percentage ` fmtParams := []interface{}{ tableName, fieldPrefix, fieldPrefix, vendorSkuNameField, GetImgFieldName(vendorID), GetImgFieldName(vendorID), GetDescImgFieldName(vendorID), fieldPrefix, fieldPrefix, } if vendorID == model.VendorIDEBAI { sql += `, t4vp.vendor_category_id vendor_vendor_cat_id2, t4vp.parent_id vendor_vendor_cat_id3` } if isSingleStorePF { sql += `, t5.%s_sync_status store_cat_sync_status, t5.%s_id vendor_cat_id, t5sku.%s_sync_status sku_store_cat_sync_status, t5sku.%s_id sku_vendor_cat_id` fmtParams = append(fmtParams, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix) } sql += ` FROM store_sku_bind t1 LEFT JOIN sku t2 ON t1.sku_id = t2.id AND t2.deleted_at = ? AND t2.status = ? LEFT JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ? LEFT JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ?` sqlParams := []interface{}{ utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, } if vendorID == model.VendorIDEBAI { sql += ` LEFT JOIN sku_vendor_category t4v ON t4v.vendor_category_id = t4.%s_category_id AND t4v.vendor_id = ? LEFT JOIN sku_vendor_category t4vp ON t4vp.vendor_category_id = t4v.parent_id AND t4v.vendor_id = ?` fmtParams = append(fmtParams, fieldPrefix) sqlParams = append(sqlParams, vendorID, vendorID) } if isSingleStorePF { sql += ` LEFT JOIN store_sku_category_map t5 ON t4.id = t5.category_id AND t5.store_id = t1.store_id AND t5.deleted_at = ? LEFT JOIN store_sku_category_map t5sku ON t2.category_id = t5sku.category_id AND t5sku.store_id = t1.store_id AND t5sku.deleted_at = ?` sqlParams = append(sqlParams, utils.DefaultTimeValue, utils.DefaultTimeValue) } sql += " WHERE 1 = 1" if storeID > 0 { sql += " AND t1.store_id = ?" sqlParams = append(sqlParams, storeID) } if isDirty { sql += " AND (t1.%s_sync_status <> 0 OR (%s.%s_id <> 0 AND t3.id IS NULL))" fmtParams = append(fmtParams, fieldPrefix, tableName, fieldPrefix) } else { sql += " AND t1.deleted_at = ?" sqlParams = append(sqlParams, utils.DefaultTimeValue) } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } if !isSingleStorePF { sql += " AND t2.%s_id <> 0" fmtParams = append(fmtParams, fieldPrefix) } sql = fmt.Sprintf(sql, fmtParams...) sql += " ORDER BY t1.price" // globals.SugarLogger.Debug(sql) if err = GetRows(db, &skus, sql, sqlParams...); err != nil { return nil, err } return skus, err } func GetStoreSkus(db *DaoDB, vendorID, storeID int, skuIDs []int) (skus []*StoreSkuSyncInfo, err error) { return GetStoreSkus2(db, vendorID, storeID, skuIDs, true) } // 以sku为基础来做全同步, // 多门店模式厂商适用 func GetFullStoreSkus(db *DaoDB, vendorID, storeID int) (skus []*StoreSkuSyncInfo, err error) { globals.SugarLogger.Debugf("GetFullStoreSkus, storeID:%d, vendorID:%d", storeID, vendorID) sql := ` SELECT t1.id bind_id, t1.price, t1.unit_price, t1.status store_sku_status, t2.%s_id vendor_sku_id, t1.%s_sync_status store_sku_sync_status, t1.store_id, t2.*, t2.id sku_id, t3.id name_id, t3.prefix, t3.name, t3.unit, IF(t3.%s <> '', t3.%s, t3.img) img, t4.%s_category_id vendor_vendor_cat_id, t4.%s_sync_status store_cat_sync_status, t4.%s_id vendor_cat_id, t5sku.%s_sync_status sku_store_cat_sync_status, t5sku.%s_id sku_vendor_cat_id FROM sku t2 LEFT JOIN store_sku_bind t1 ON t1.sku_id = t2.id AND t1.store_id = ? AND t1.deleted_at = ? JOIN sku_name t3 ON t2.name_id = t3.id AND t3.deleted_at = ? AND t3.status = ? JOIN sku_category t4 ON t3.category_id = t4.id AND t4.deleted_at = ? LEFT JOIN sku_category t5sku ON t2.category_id = t5sku.id WHERE t2.deleted_at = ? AND t2.status = ? AND t2.%s_id <> 0 ORDER BY t1.price DESC` sqlParams := []interface{}{ storeID, utils.DefaultTimeValue, utils.DefaultTimeValue, model.SkuStatusNormal, utils.DefaultTimeValue, utils.DefaultTimeValue, model.SkuStatusNormal, } fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql = fmt.Sprintf(sql, fieldPrefix, fieldPrefix, GetImgFieldName(vendorID), GetImgFieldName(vendorID), fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix, fieldPrefix) // globals.SugarLogger.Debug(sql) // globals.SugarLogger.Debug(utils.Format4Output(sqlParams, false)) if err = GetRows(db, &skus, sql, sqlParams...); err != nil { return nil, err } return skus, err } // 这个函数之前是要设置没有删除或同步标志不为0的,会导致将同步标志不为0且删除了的把标志去掉,现在改为只设置没有删除的 func SetStoreSkuSyncStatus(db *DaoDB, vendorID int, storeIDs []int, skuIDs []int, syncStatus int) (num int64, err error) { globals.SugarLogger.Debugf("SetStoreSkuSyncStatus, storeIDs:%v, vendorID:%d", storeIDs, vendorID) isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1 fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` UPDATE store_sku_bind t1 SET t1.%s_sync_status = t1.%s_sync_status | ? ` fmtParams := []interface{}{ fieldPrefix, fieldPrefix, } sqlParams := []interface{}{ syncStatus, } if isSingleStorePF && (syncStatus&model.SyncFlagNewMask) != 0 { sql += `, t1.%s_id = 0 ` fmtParams = append(fmtParams, fieldPrefix) } sql += " WHERE (t1.deleted_at = ?)" // fmtParams = append(fmtParams, fieldPrefix) sqlParams = append(sqlParams, utils.DefaultTimeValue) if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } sql = fmt.Sprintf(sql, fmtParams...) return ExecuteSQL(db, sql, sqlParams...) } func SetStoreCategorySyncStatus(db *DaoDB, vendorID int, storeIDs []int, catIDs []int, syncStatus int) (num int64, err error) { globals.SugarLogger.Debugf("SetStoreCategorySyncStatus, storeIDs:%v, vendorID:%d", storeIDs, vendorID) isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1 fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql := ` UPDATE store_sku_category_map t1 SET t1.%s_sync_status = IF(t1.deleted_at = ?, t1.%s_sync_status | ?, 0) ` fmtParams := []interface{}{ fieldPrefix, fieldPrefix, } sqlParams := []interface{}{ utils.DefaultTimeValue, syncStatus, } if isSingleStorePF && (syncStatus&model.SyncFlagNewMask) != 0 { sql += `, t1.%s_id = 0 ` fmtParams = append(fmtParams, fieldPrefix) } sql += " WHERE (t1.deleted_at = ? OR t1.%s_sync_status <> 0)" fmtParams = append(fmtParams, fieldPrefix) sqlParams = append(sqlParams, utils.DefaultTimeValue) if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(catIDs) > 0 { sql += " AND t1.category_id IN (" + GenQuestionMarks(len(catIDs)) + ")" sqlParams = append(sqlParams, catIDs) } sql = fmt.Sprintf(sql, fmtParams...) return ExecuteSQL(db, sql, sqlParams...) } func GetImgFieldName(vendorID int) (fieldName string) { fieldName = imgFieldMap[vendorID] if fieldName == "" { fieldName = "img" } return fieldName } func GetDescImgFieldName(vendorID int) (fieldName string) { fieldName = descImgFieldMap[vendorID] if fieldName == "" { fieldName = "desc_img" } return fieldName } func GetStoresSkusInfo(db *DaoDB, storeIDs, skuIDs []int) (storeSkuList []*model.StoreSkuBind, err error) { sql := ` SELECT * FROM store_sku_bind t1 WHERE t1.deleted_at = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, } if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } if len(skuIDs) > 0 { sql += " AND t1.sku_id IN (" + GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } err = GetRows(db, &storeSkuList, sql, sqlParams...) return storeSkuList, err } // vendorID, vendorStoreIDs和vendorSkuIDs都是必须参数 func GetStoresSkusInfoByVendorInfo(db *DaoDB, vendorID int, vendorStoreIDs, vendorSkuIDs []string) (storeSkuList []*StoreSkuBindWithVendorInfo, err error) { if len(vendorStoreIDs) == 0 || len(vendorSkuIDs) == 0 { return nil, nil } sql := ` SELECT t1.*, %s.%s_id vendor_sku_id, t2.vendor_store_id FROM store_sku_bind t1 JOIN store_map t2 ON t2.store_id = t1.store_id AND t2.vendor_id = ? AND t2.deleted_at = ? JOIN sku t3 ON t3.id = t1.sku_id WHERE t1.deleted_at = ? AND t2.vendor_store_id IN (` + GenQuestionMarks(len(vendorStoreIDs)) + `) AND %s.%s_id IN (` + GenQuestionMarks(len(vendorSkuIDs)) + `)` sqlParams := []interface{}{ vendorID, utils.DefaultTimeValue, utils.DefaultTimeValue, vendorStoreIDs, vendorSkuIDs, } isSingleStorePF := model.MultiStoresVendorMap[vendorID] != 1 tableName := "t1" if !isSingleStorePF { tableName = "t3" } fieldPrefix := ConvertDBFieldPrefix(model.VendorNames[vendorID]) sql = fmt.Sprintf(sql, tableName, fieldPrefix, tableName, fieldPrefix) err = GetRows(db, &storeSkuList, sql, sqlParams...) return storeSkuList, err } func GetMissingStoreSkuFromOrder(db *DaoDB, storeIDs []int, fromTime time.Time) (storeSkuList []*MissingStoreSkuInfo, err error) { if time.Now().Sub(fromTime) > 24*time.Hour*60 { return nil, fmt.Errorf("GetMissingStoreSkuFromOrder,时间超过60天") } sql := ` SELECT IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) store_id, t4.name_id, t1.sku_id, t4.spec_quality, t4.spec_unit, t5.unit, COUNT(*) ct, CAST(AVG(IF(t1.vendor_price <> 0, t1.vendor_price, t1.sale_price)) AS SIGNED) ref_price FROM order_sku t1 JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id LEFT JOIN store_sku_bind t3 ON t3.store_id = IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) AND t3.sku_id = t1.sku_id AND t3.deleted_at = ? JOIN sku t4 ON t4.id = t1.sku_id JOIN sku_name t5 ON t5.id = t4.name_id WHERE t2.status = ? AND IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) > 0 AND t1.sku_id > 0 AND t1.shop_price = 0 AND t1.order_created_at > ? AND t3.id IS NULL ` sqlParams := []interface{}{ utils.DefaultTimeValue, model.OrderStatusFinished, fromTime, } if len(storeIDs) > 0 { sql += " AND IF(t2.jx_store_id <> 0, t2.jx_store_id, t2.store_id) IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } sql += ` GROUP BY 1,2,3,4,5,6 ORDER BY 1,2,3,4,5,6 ` err = GetRows(db, &storeSkuList, sql, sqlParams...) return storeSkuList, err } func GetAutoSaleStoreSku(db *DaoDB, storeIDs []int) (storeSkuList []*model.StoreSkuBind, err error) { sql := ` SELECT * FROM store_sku_bind t1 WHERE t1.deleted_at = ? AND t1.auto_sale_at <> ?` sqlParams := []interface{}{ utils.DefaultTimeValue, utils.DefaultTimeValue, } if len(storeIDs) > 0 { sql += " AND t1.store_id IN (" + GenQuestionMarks(len(storeIDs)) + ")" sqlParams = append(sqlParams, storeIDs) } err = GetRows(db, &storeSkuList, sql, sqlParams...) return storeSkuList, err }