package cms import ( "math" "strconv" "strings" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" ) // GetStoreSkus用 type StoreSkuNameExt struct { model.SkuName UnitPrice int `json:"unitPrice"` Skus []map[string]interface{} `orm:"-" json:"skus"` SkusStr string `json:"-"` } // GetStoreSkus用 type StoreSkuNamesInfo struct { TotalCount int `json:"totalCount"` SkuNames []*StoreSkuNameExt `json:"skuNames"` } // UpdateStoreSku用,API调用时 type StoreSkuBindSkuInfo struct { SubStoreID int `json:"subStoreID"` SkuID int `json:"skuID"` IsFocus int `json:"isFocus"` // -1:不关注,0:忽略,1:关注 IsSale int `json:"isSale"` // -1:不可售,0:忽略,1:可售 ElmID int64 `json:"elmID"` EbaiID int64 `json:"ebaiID"` } // UpdateStoreSku用,API调用时 type StoreSkuBindInfo struct { NameID int `json:"nameID"` UnitPrice int `json:"unitPrice"` Skus []*StoreSkuBindSkuInfo `json:"skus"` } type tStoreSkuBindAndSpec struct { model.StoreSkuBind SpecQuality float32 SpecUnit string } func GetStoreSkus(storeID int, isFocused bool, keyword string, params map[string]interface{}, offset, pageSize int) (skuNamesInfo *StoreSkuNamesInfo, err error) { db := dao.GetDB() sql := ` FROM sku_name t1 JOIN sku t2 ON t1.id = t2.name_id AND t2.deleted_at = '1970-01-01 00:00:00' LEFT JOIN store_sku_bind t4 ON t4.sku_id = t2.id AND t4.deleted_at = '1970-01-01 00:00:00' AND t4.store_id = ? WHERE t1.deleted_at = '1970-01-01 00:00:00' ` if isFocused { sql += " AND t4.sku_id IS NOT NULL" } else { sql += " AND t4.sku_id IS NULL" } sqlParams := []interface{}{ storeID, } if keyword != "" { keywordLike := "%" + keyword + "%" sql += " AND (t1.name LIKE ? OR t1.prefix LIKE ? OR t1.comment LIKE ?" sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike) if keywordInt64, err2 := strconv.ParseInt(keyword, 10, 64); err2 == nil { sql += " OR t2.jd_id = ? OR t4.id = ?" sqlParams = append(sqlParams, keywordInt64, keywordInt64) } sql += ")" } if params["nameID"] != nil { sql += " AND t1.id = ?" sqlParams = append(sqlParams, params["nameID"].(int)) } if params["categoryID"] != nil { cat := &model.SkuCategory{} cat.ID = params["categoryID"].(int) if err = dao.GetEntity(db, cat); err != nil { return nil, err } if cat.Level == 1 { sql += " AND t1.category_id IN (SELECT id FROM sku_category WHERE parent_id = ?)" } else { sql += " AND t1.category_id = ?" } sqlParams = append(sqlParams, cat.ID) } if params["jdID"] != nil { sql += " AND t1.jd_id = ?" sqlParams = append(sqlParams, params["jdID"].(int)) } if params["name"] != nil { sql += " AND t1.name LIKE ?" sqlParams = append(sqlParams, "%"+params["name"].(string)+"%") } if params["prefix"] != nil { sql += " AND t1.prefix LIKE ?" sqlParams = append(sqlParams, "%"+params["prefix"].(string)+"%") } if params["unit"] != nil { sql += " AND t1.unit = ?" sqlParams = append(sqlParams, params["unit"].(string)) } if params["skuID"] != nil { skuID, ok := params["skuID"].(int) if ok { sql += " AND t2.id = ?" sqlParams = append(sqlParams, skuID) } else { skuIDs := params["skuID"].([]interface{}) sql += " AND t2.id IN (" + dao.GenQuestionMarks(len(skuIDs)) + ")" sqlParams = append(sqlParams, skuIDs) } } if params["fromStatus"] != nil { fromStatus := params["fromStatus"].(int) toStatus := fromStatus if params["toStatus"] != nil { toStatus = params["toStatus"].(int) } sql += " AND t2.status >= ? AND t2.status <= ? AND t4.status >= ? AND t4.status <= ?" sqlParams = append(sqlParams, fromStatus, toStatus, fromStatus, toStatus) } sql += ` GROUP BY t1.id, t1.created_at, t1.updated_at, t1.last_operator, t1.deleted_at, t1.prefix, t1.name, t1.comment, t1.brand_id, t1.category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.elm_img_hash_code ` sqlData := ` SELECT SQL_CALC_FOUND_ROWS t1.id, t1.created_at, t1.updated_at, t1.last_operator, t1.deleted_at, t1.prefix, t1.name, t1.comment, t1.brand_id, t1.category_id, t1.is_global, t1.unit, t1.price, t1.img, t1.elm_img_hash_code, CONCAT("[", GROUP_CONCAT(DISTINCT CONCAT('{"id":', t2.id, ',"status":', t2.status, ',"createdAt":"', CONCAT(REPLACE(t4.created_at," ","T"),"+08:00"), '","updatedAt":"', CONCAT(REPLACE(t4.updated_at," ","T"),"+08:00"), '","lastOperator":"', t4.last_operator, '","specQuality":', t2.spec_quality, ',"specUnit":"', t2.spec_unit, '","weight":', t2.weight, ',"jdID":', t2.jd_id, ',"categoryID":', t2.category_id, ',"nameID":', t2.name_id, ',"subStoreID":', IF(t4.sub_store_id IS NULL, 0, t4.sub_store_id), ',"price":', IF(t4.price IS NULL, 0, t4.price), ',"unitPrice":', IF(t4.unit_price IS NULL, 0, t4.unit_price), ',"storeSkuStatus":', IF(t4.status IS NULL, 0, t4.status), "}")), "]") skus_str ` + sql + ` ORDER BY t1.id LIMIT ? OFFSET ?` if pageSize == 0 { pageSize = model.DefPageSize } if offset < 0 { offset = 0 } sqlParams = append(sqlParams, pageSize, offset) skuNamesInfo = &StoreSkuNamesInfo{} // globals.SugarLogger.Debug(sqlData) dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() if err = dao.GetRows(db, &skuNamesInfo.SkuNames, sqlData, sqlParams...); err == nil { countInfo := &struct{ Ct int }{} if err = dao.GetRow(db, countInfo, "SELECT FOUND_ROWS() ct"); err == nil { skuNamesInfo.TotalCount = countInfo.Ct for _, skuName := range skuNamesInfo.SkuNames { if skuName.SkusStr != "" { if err = utils.UnmarshalUseNumber([]byte(skuName.SkusStr), &skuName.Skus); err != nil { break } if len(skuName.Skus) > 0 { skuName.UnitPrice = int(utils.MustInterface2Int64(skuName.Skus[0]["unitPrice"])) for _, v := range skuName.Skus { delete(v, "unitPrice") } } } } } } dao.Commit(db) return skuNamesInfo, err } func UpdateStoreSku(storeID int, skuBindInfo *StoreSkuBindInfo, userName string) (num int64, err error) { db := dao.GetDB() skuBinds := skuBindInfo.Skus var existBinds []*tStoreSkuBindAndSpec addNum, delNum, updateNum := 0, 0, 0 if err = dao.GetRows(db, &existBinds, ` SELECT t1.*, t2.spec_quality, t2.spec_unit FROM store_sku_bind t1 JOIN sku t2 ON t1.sku_id = t2.id WHERE store_id = ? AND t2.name_id = ?`, storeID, skuBindInfo.NameID); err == nil { skuIDs := make([]int, len(existBinds)) for k, v := range existBinds { skuIDs[k] = v.SkuID } existBindsMap := make(map[int]*model.StoreSkuBind, len(existBinds)) dao.Begin(db) defer func() { if r := recover(); r != nil { dao.Rollback(db) panic(r) } }() unitPrice := 0 if skuBindInfo.UnitPrice != 0 { unitPrice = skuBindInfo.UnitPrice } else { unitPrice = existBinds[0].UnitPrice } for _, v := range existBinds { if skuBindInfo.UnitPrice != 0 { v.UnitPrice = unitPrice v.Price = calStoreSkuPrice(unitPrice, v.SpecQuality, v.SpecUnit) v.JdSyncStatus |= model.SyncFlagPriceMask v.ElmSyncStatus |= model.SyncFlagPriceMask v.EbaiSyncStatus |= model.SyncFlagPriceMask dao.WrapUpdateULEntity(v, userName) if _, err2 := dao.UpdateEntity(db, &v.StoreSkuBind); err2 != nil { dao.Rollback(db) return 0, err2 } } existBindsMap[v.SkuID] = &v.StoreSkuBind } for _, v := range skuBinds { skuBind, ok := existBindsMap[v.SkuID] if !ok { if v.IsFocus == 1 { sku := &model.Sku{} sku.ID = v.SkuID if err2 := dao.GetEntity(db, sku); err2 != nil { dao.Rollback(db) return 0, err2 } skuBind = &model.StoreSkuBind{ StoreID: storeID, SkuID: v.SkuID, SubStoreID: v.SubStoreID, // todo 这个应该从用户信息中自动获得 UnitPrice: unitPrice, Price: calStoreSkuPrice(unitPrice, sku.SpecQuality, sku.SpecUnit), Status: model.StoreSkuBindStatusDontSale, } dao.WrapAddIDCULDEntity(skuBind, userName) } } else { if v.IsFocus != -1 { dao.WrapUpdateULEntity(skuBind, userName) } } if skuBind != nil { if v.IsSale != 0 { if v.IsSale == 1 { skuBind.Status = model.StoreSkuBindStatusNormal } else { skuBind.Status = model.StoreSkuBindStatusDontSale } skuBind.JdSyncStatus |= model.SyncFlagSaleMask skuBind.ElmSyncStatus |= model.SyncFlagSaleMask skuBind.EbaiSyncStatus |= model.SyncFlagSaleMask } if ok { if v.IsFocus == -1 { delNum++ _, err = dao.DeleteEntityLogically(db, skuBind, map[string]interface{}{ model.FieldStatus: model.StoreSkuBindStatusDeleted, model.FieldJdSyncStatus: model.SyncFlagDeletedMask, model.FieldElmSyncStatus: model.SyncFlagDeletedMask, model.FieldEbaiSyncStatus: model.SyncFlagDeletedMask, }, userName, nil) } else { // todo 如果修改ebai与elm ID怎么处理呢? if v.IsFocus == 1 { skuBind.DeletedAt = utils.DefaultTimeValue } updateNum++ skuBind.JdSyncStatus |= model.SyncFlagModifiedMask skuBind.ElmSyncStatus |= model.SyncFlagModifiedMask skuBind.EbaiSyncStatus |= model.SyncFlagModifiedMask _, err = dao.UpdateEntity(db, skuBind) } } else { if v.EbaiID != 0 { skuBind.EbaiID = v.EbaiID } if v.ElmID != 0 { skuBind.ElmID = v.ElmID } addNum++ skuBind.JdSyncStatus = model.SyncFlagNewMask skuBind.ElmSyncStatus = model.SyncFlagNewMask skuBind.EbaiSyncStatus = model.SyncFlagNewMask err = dao.CreateEntity(db, skuBind) } } if err != nil { dao.Rollback(db) return 0, err } } if skuBindInfo.UnitPrice != 0 { num = int64(addNum + len(existBinds)) } else { num = int64(addNum + delNum + updateNum) } dao.Commit(db) err = CurVendorSync.SyncStoreSku(db, storeID, skuIDs, false, userName) } return num, err } // 计算SKU价格,unitPrice为一斤的单价,specQuality为质量,单位为克 func calStoreSkuPrice(unitPrice int, specQuality float32, specUnit string) int { if strings.ToLower(specUnit) == "kg" { specQuality *= 1000 } return int(math.Round(float64(float32(unitPrice) * specQuality / 500))) }