Files
jx-callback/business/model/dao/store_sku.go

529 lines
18 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package 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)"`
BindDeletedAt time.Time `orm:"type(datetime);default('1970-01-01 00:00:00')" json:"bindDeletedAt"`
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)"`
}
type StoreSkuNameInfo struct {
StoreID int `orm:"column(store_id)"`
NameID int `orm:"column(name_id)"`
UnitPrice int64
}
// 单门店模式厂商适用
// 从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, t1.deleted_at bind_deleted_at,
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, t1.deleted_at bind_deleted_at,
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
}
func GetExistingStoreSkuNameInfo(db *DaoDB, storeIDs, skuNameIDs []int) (storeSkuNameList []*StoreSkuNameInfo, err error) {
if len(storeIDs) == 0 || len(skuNameIDs) == 0 {
return nil, nil
}
sql := `
SELECT t1.store_id, t2.name_id, MAX(t1.unit_price) unit_price
FROM store_sku_bind t1
JOIN sku t2 ON t2.id = t1.sku_id
WHERE t1.deleted_at = ? AND t1.store_id IN (` + GenQuestionMarks(len(storeIDs)) + `)
AND t2.name_id IN (` + GenQuestionMarks(len(skuNameIDs)) + `)
GROUP BY 1, 2`
sqlParams := []interface{}{
utils.DefaultTimeValue,
storeIDs,
skuNameIDs,
}
err = GetRows(db, &storeSkuNameList, sql, sqlParams...)
return storeSkuNameList, err
}