@@ -3,7 +3,9 @@ package cms
import (
"errors"
"fmt"
"io"
"math"
"mime/multipart"
"sort"
"strconv"
"sync"
@@ -23,6 +25,7 @@ import (
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
"github.com/360EntSecGroup-Skylar/excelize"
"github.com/astaxie/beego/orm"
)
@@ -34,80 +37,6 @@ const (
CopyStoreSkuModeUpdatePrice = "updatePrice" // 增量复制价格
)
type StoreSkuExt struct {
NameID int ` orm:"column(name_id)" json:"nameID" `
SkuID int ` orm:"column(sku_id)" json:"id" `
Comment string ` orm:"size(255)" json:"comment" `
SkuCategoryID int ` orm:"column(sku_category_id)" json:"categoryID" `
SkuSpecQuality float32 ` json:"specQuality" `
SkuSpecUnit string ` orm:"size(8)" json:"specUnit" ` // 质量或容量
Weight int ` json:"weight" ` // 重量/质量, 单位为克, 当相应的SkuName的SpecUnit为g或kg时, 必须等于SpecQuality
JdID string ` orm:"column(sku_jd_id);null;index" json:"jdID" `
SkuStatus int ` json:"status" `
BindCreatedAt time . Time ` orm:"auto_now_add;type(datetime)" json:"createdAt" `
BindUpdatedAt time . Time ` orm:"auto_now;type(datetime)" json:"updatedAt" `
BindLastOperator string ` orm:"size(32)" json:"lastOperator" ` // 最后操作员
BindDeletedAt time . Time ` orm:"type(datetime)" json:"deletedAt" `
SubStoreID int ` orm:"column(sub_store_id)" json:"subStoreID" `
BindPrice int ` json:"price" ` // 单位为分, 不用int64的原因是这里不需要累加
UnitPrice int ` json:"unitPrice" ` // 这个是一斤的门店商品价, 放在这里的原因是避免额外增加一张store sku_name表, 逻辑上要保证同一SKU NAME中的所有SKU这个字段的数据一致
StoreSkuStatus int ` json:"storeSkuStatus" `
EbaiID string ` orm:"column(ebai_id);index" json:"ebaiID" `
MtwmID string ` orm:"column(mtwm_id)" json:"mtwmID" ` // 这个也不是必须的, 只是为了DAO取数据语句一致
// WscID string `orm:"column(wsc_id);index" json:"wscID"` // 表示微盟skuId
// WscID2 string `orm:"column(wsc_id2);index" json:"wscID2"` // 表示微盟goodsId
JdSyncStatus int8 ` orm:"default(2)" json:"jdSyncStatus" `
EbaiSyncStatus int8 ` orm:"default(2)" json:"ebaiSyncStatus" `
MtwmSyncStatus int8 ` orm:"default(2)" json:"mtwmSyncStatus" `
// WscSyncStatus int8 `orm:"default(2)" json:"wscSyncStatus"`
JdPrice int ` json:"jdPrice" `
EbaiPrice int ` json:"ebaiPrice" `
MtwmPrice int ` json:"mtwmPrice" `
JxPrice int ` json:"jxPrice" `
AutoSaleAt time . Time ` orm:"type(datetime);null" json:"autoSaleAt" `
ActPrice int ` json:"actPrice" `
ActID int ` orm:"column(act_id)" json:"actID" `
ActType int ` orm:"column(act_type)" json:"actType" `
EarningPrice int ` json:"earningPrice" `
EarningActID int ` orm:"column(earning_act_id)" json:"earningActID" `
RealEarningPrice int ` json:"realEarningPrice" `
StatusSaleBegin int16 ` json:"statusSaleBegin" ` //商品可售时间范围
StatusSaleEnd int16 ` json:"statusSaleEnd" `
Count int ` json:"count" `
Times int ` json:"times" `
}
// GetStoreSkus用
type StoreSkuNameExt struct {
StoreID int ` orm:"column(store_id)" json:"storeID" `
StoreName string ` json:"storeName" `
model . SkuName
PayPercentage int ` json:"-" `
UnitPrice int ` json:"unitPrice" `
Skus [ ] * StoreSkuExt ` orm:"-" json:"skus,omitempty" `
SkusStr string ` json:"-" `
PendingOpType int8 ` json:"pendingOpType" ` // 取值同 StoreOpRequest.Type
PendingUnitPrice int ` json:"pendingUnitPrice" ` // 这个是待审核的价格申请
}
// GetStoreSkus用
type StoreSkuNamesInfo struct {
TotalCount int ` json:"totalCount" `
SkuNames [ ] * StoreSkuNameExt ` json:"skuNames" `
}
// UpdateStoreSku用, API调用时
type StoreSkuBindSkuInfo struct {
SkuID int ` json:"skuID" `
@@ -171,7 +100,36 @@ type tGetStoresSkusInfo struct {
model . SkuName
PayPercentage int ` json:"-" `
StoreSkuExt
dao . StoreSkuExt
}
type SheetParam struct {
OutSkuIDCol int
SkuNameIDCol int
SkuPriceCol int
SkuNameCol int
SkuUnitCol int
SkuRow int
}
type DataSuccess struct {
NameID string ` json:"商品编码" `
Name string ` json:"商品名称" `
OrgPrice float64 ` json:"原价" `
NowPrice float64 ` json:"现价" `
MixPrice float64 ` json:"涨跌" `
}
type DataFailed struct {
NameID string ` json:"商品ID" `
Name string ` json:"商品名称" `
Comment string ` json:"备注" `
}
type DataLock struct {
dataSuccessList [ ] DataSuccess
dataFailedList [ ] DataFailed
locker sync . RWMutex
}
const (
@@ -187,9 +145,10 @@ var (
"18180948107" : 1 , // 徐
// "13684045763": 1, // 周
}
dataLock DataLock
)
func GetStoreSkus ( ctx * jxcontext . Context , storeID int , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * StoreSkuNamesInfo , err error ) {
func GetStoreSkus ( ctx * jxcontext . Context , storeID int , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * dao . StoreSkuNamesInfo, err error ) {
return GetStoresSkus ( ctx , [ ] int { storeID } , skuIDs , isFocus , keyword , isBySku , isAct , params , offset , pageSize )
}
@@ -373,11 +332,11 @@ func getGetStoresSkusBaseSQL(db *dao.DaoDB, storeIDs, skuIDs []int, isFocus bool
return sql , sqlParams , err
}
func GetStoresSkus ( ctx * jxcontext . Context , storeIDs , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * StoreSkuNamesInfo , err error ) {
func GetStoresSkus ( ctx * jxcontext . Context , storeIDs , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * dao . StoreSkuNamesInfo, err error ) {
return GetStoresSkusNew ( ctx , storeIDs , skuIDs , isFocus , keyword , isBySku , isAct , params , offset , pageSize )
}
func GetStoresSkusNew ( ctx * jxcontext . Context , storeIDs , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * StoreSkuNamesInfo , err error ) {
func GetStoresSkusNew ( ctx * jxcontext . Context , storeIDs , skuIDs [ ] int , isFocus bool , keyword string , isBySku , isAct bool , params map [ string ] interface { } , offset , pageSize int ) ( skuNamesInfo * dao . StoreSkuNamesInfo, err error ) {
if ! isFocus && ! isBySku && ( len ( storeIDs ) > 1 || len ( storeIDs ) == 0 ) {
return nil , fmt . Errorf ( "未关注按SkuName只能查询单店" )
}
@@ -416,7 +375,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
catOrderBy = "t2.seq, "
}
skuNamesInfo = & StoreSkuNamesInfo { }
skuNamesInfo = & dao . StoreSkuNamesInfo{ }
if ! isBySku && sqlPageSize != model . UnlimitedPageSize {
sql2 := `
SELECT SQL_CALC_FOUND_ROWS
@@ -476,12 +435,12 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
}
dao . Commit ( db )
globals . SugarLogger . Debugf ( "GetStoresSkusNew get result2:%v" , time . Now ( ) . Sub ( beginTime ) )
storeNameMap := make ( map [ int64 ] * StoreSkuNameExt )
storeNameMap := make ( map [ int64 ] * dao . StoreSkuNameExt)
for _ , v := range tmpList {
var storeName * StoreSkuNameExt
var storeName * dao . StoreSkuNameExt
index := jxutils . Combine2Int ( v . StoreID , v . ID )
if isBySku || storeNameMap [ index ] == nil {
storeName = & StoreSkuNameExt {
storeName = & dao . StoreSkuNameExt{
StoreID : v . StoreID ,
StoreName : v . StoreName ,
SkuName : v . SkuName ,
@@ -508,7 +467,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
storeIDs , skuIDs = GetStoreAndSkuIDsFromInfo ( skuNamesInfo )
}
beginTime := time . Now ( )
err = u pdateActPrice4StoreSkuNameNew( db , storeIDs , skuIDs , skuNamesInfo , actVendorID )
err = dao . U pdateActPrice4StoreSkuNameNew( db , storeIDs , skuIDs , skuNamesInfo , actVendorID )
globals . SugarLogger . Debugf ( "GetStoresSkusNew updateActPrice4StoreSkuName:%v" , time . Now ( ) . Sub ( beginTime ) )
if ! isFocus {
err = updateUnitPrice4StoreSkuNameNew ( db , skuNamesInfo )
@@ -519,7 +478,7 @@ func GetStoresSkusNew(ctx *jxcontext.Context, storeIDs, skuIDs []int, isFocus bo
return skuNamesInfo , err
}
func GetStoreAndSkuIDsFromInfo ( skuNamesInfo * StoreSkuNamesInfo ) ( storeIDs , skuIDs [ ] int ) {
func GetStoreAndSkuIDsFromInfo ( skuNamesInfo * dao . StoreSkuNamesInfo) ( storeIDs , skuIDs [ ] int ) {
storeIDMap := make ( map [ int ] int )
skuIDMap := make ( map [ int ] int )
for _ , skuName := range skuNamesInfo . SkuNames {
@@ -532,7 +491,7 @@ func GetStoreAndSkuIDsFromInfo(skuNamesInfo *StoreSkuNamesInfo) (storeIDs, skuID
}
// 根据已经部分关注的商品,得到已经存在的门店商品单价
func updateUnitPrice4StoreSkuNameNew ( db * dao . DaoDB , skuNamesInfo * StoreSkuNamesInfo ) ( err error ) {
func updateUnitPrice4StoreSkuNameNew ( db * dao . DaoDB , skuNamesInfo * dao . StoreSkuNamesInfo) ( err error ) {
storeIDMap := make ( map [ int ] int )
skuNameIDMap := make ( map [ int ] int )
for _ , skuName := range skuNamesInfo . SkuNames {
@@ -554,49 +513,7 @@ func updateUnitPrice4StoreSkuNameNew(db *dao.DaoDB, skuNamesInfo *StoreSkuNamesI
return err
}
// skuIDs为空, 会导致性能极低, 所以要skuIDs必须有值
func updateActPrice4StoreSkuNameNew ( db * dao . DaoDB , storeIDs , skuIDs [ ] int , skuNamesInfo * StoreSkuNamesInfo , actVendorID int ) ( err error ) {
if len ( skuIDs ) == 0 {
return nil
}
var vendorIDs [ ] int
if actVendorID >= 0 {
vendorIDs = [ ] int { actVendorID }
}
actStoreSkuList , err := dao . GetEffectiveActStoreSkuInfo ( db , 0 , vendorIDs , storeIDs , skuIDs , time . Now ( ) , time . Now ( ) )
if err != nil {
globals . SugarLogger . Errorf ( "GetEffectiveActStoreSkuInfo can not get sku promotion info for error:%v" , err )
return err
}
actStoreSkuMap4Act := jxutils . NewActStoreSkuMap ( actStoreSkuList , true )
actStoreSkuMap4EarningPrice := jxutils . NewActStoreSkuMap ( actStoreSkuList , false )
for _ , skuName := range skuNamesInfo . SkuNames {
if len ( skuName . Skus ) > 0 {
for _ , v := range skuName . Skus {
if actStoreSku := actStoreSkuMap4Act . GetActStoreSku ( skuName . StoreID , v . SkuID , - 1 ) ; actStoreSku != nil {
v . ActPrice = int ( actStoreSku . ActualActPrice )
v . ActID = actStoreSku . ActID
v . ActType = actStoreSku . Type
}
if actStoreSku := actStoreSkuMap4EarningPrice . GetActStoreSku ( skuName . StoreID , v . SkuID , - 1 ) ; actStoreSku != nil {
v . EarningPrice = int ( actStoreSku . EarningPrice )
v . EarningActID = actStoreSku . ActID
}
v . RealEarningPrice = v . EarningPrice
if v . RealEarningPrice == 0 {
v . RealEarningPrice = int ( jxutils . CaculateSkuEarningPrice ( int64 ( v . BindPrice ) , int64 ( v . BindPrice ) , skuName . PayPercentage ) )
}
}
} else {
skuName . UnitPrice = skuName . Price
}
}
return err
}
func updateSaleInfo4StoreSkuName ( ctx * jxcontext . Context , db * dao . DaoDB , storeIDs , skuIDs [ ] int , params map [ string ] interface { } , skuNamesInfo * StoreSkuNamesInfo , offset , pageSize int ) ( err error ) {
func updateSaleInfo4StoreSkuName ( ctx * jxcontext . Context , db * dao . DaoDB , storeIDs , skuIDs [ ] int , params map [ string ] interface { } , skuNamesInfo * dao . StoreSkuNamesInfo , offset , pageSize int ) ( err error ) {
var (
saleInfoList [ ] * SkuSaleInfo
timeList [ ] time . Time
@@ -625,9 +542,9 @@ func updateSaleInfo4StoreSkuName(ctx *jxcontext.Context, db *dao.DaoDB, storeIDs
for _ , saleInfo := range saleInfoList {
saleInfoMap [ jxutils . Combine2Int ( saleInfo . StoreID , saleInfo . SkuID ) ] = saleInfo
}
var newSkuNames [ ] * StoreSkuNameExt
var newSkuNames [ ] * dao . StoreSkuNameExt
for _ , skuName := range skuNamesInfo . SkuNames {
var newSkus [ ] * StoreSkuExt
var newSkus [ ] * dao . StoreSkuExt
for _ , sku := range skuName . Skus {
saleInfo := saleInfoMap [ jxutils . Combine2Int ( skuName . StoreID , sku . SkuID ) ]
if saleInfo == nil && fromCount == 0 {
@@ -2161,16 +2078,16 @@ func ReCalculateJxPrice(ctx *jxcontext.Context, storeIDs []int) (err error) {
return err
}
func GetTopSkusByStoreIDs ( ctx * jxcontext . Context , storeIDs [ ] int ) ( skuAnd NameExt [ ] * dao . SkuAnd NameExt , err error ) {
func GetTopSkusByStoreIDs ( ctx * jxcontext . Context , storeIDs [ ] int ) ( storeSku NameExt [ ] * dao . StoreSku NameExt , err error ) {
if len ( storeIDs ) == 0 {
return skuAnd NameExt , err
return storeSku NameExt , err
}
db := dao . GetDB ( )
skuAnd NameExt , err = dao . GetTopSkusByStoreIDs ( db , storeIDs )
storeSku NameExt , err = dao . GetTopSkusByStoreIDs ( db , storeIDs )
if err != nil {
return nil , err
}
return skuAnd NameExt , err
return storeSku NameExt , err
}
func GetTopCategorysByStoreIDs ( ctx * jxcontext . Context , storeIDs [ ] int ) ( skuCategory [ ] * model . SkuCategory , err error ) {
@@ -2190,3 +2107,77 @@ func RefershStoreSkusMidPrice(ctx *jxcontext.Context, storeIDs []int) (err error
_ , err = dao . RefershStoreSkusMidPrice ( db , storeIDs )
return err
}
func RefreshJxPriceByExcel ( ctx * jxcontext . Context , storeIDs [ ] int , files [ ] * multipart . FileHeader , isAsync , isContinueWhenError bool ) ( hint string , err error ) {
if len ( files ) == 0 {
return "" , errors . New ( "没有文件上传!" )
}
if len ( storeIDs ) == 0 {
return "" , errors . New ( "请选择至少一个门店!" )
}
fileHeader := files [ 0 ]
file , err := fileHeader . Open ( )
hint , err = RefreshJxPriceByExcelBin ( ctx , storeIDs , file , true , true )
file . Close ( )
return hint , err
}
func RefreshJxPriceByExcelBin ( ctx * jxcontext . Context , storeIDs [ ] int , reader io . Reader , isAsync , isContinueWhenError bool ) ( hint string , err error ) {
var storeSkuNamePriceList [ ] * model . StoreSkuNamePrice
dataLock . dataFailedList = dataLock . dataFailedList [ 0 : 0 ]
dataLock . dataSuccessList = dataLock . dataSuccessList [ 0 : 0 ]
sheetParam := & SheetParam {
SkuNameIDCol : 5 ,
SkuPriceCol : 3 ,
SkuNameCol : 1 ,
SkuRow : 1 ,
SkuUnitCol : 2 ,
OutSkuIDCol : 0 ,
}
xlsx , err := excelize . OpenReader ( reader )
if err != nil {
return "" , err
}
rows , _ := xlsx . GetRows ( xlsx . GetSheetName ( 1 ) )
for rowNum , row := range rows {
if rowNum < sheetParam . SkuRow {
continue
}
storeSkuNamePrice := & model . StoreSkuNamePrice { }
GetCellIntoStruct ( rowNum , row , sheetParam , storeSkuNamePrice )
storeSkuNamePriceList = append ( storeSkuNamePriceList , storeSkuNamePrice )
}
return hint , err
}
func GetCellIntoStruct ( rowNum int , row [ ] string , sheetParam * SheetParam , storeSkuNamePrice * model . StoreSkuNamePrice ) {
for k , cell := range row {
if k == sheetParam . OutSkuIDCol {
storeSkuNamePrice . OutSkuID = cell
}
if k == sheetParam . SkuNameCol {
storeSkuNamePrice . Name = cell
}
if k == sheetParam . SkuNameIDCol {
storeSkuNamePrice . NameIDGroup = cell
}
if k == sheetParam . SkuPriceCol {
storeSkuNamePrice . Price = int ( utils . Float64TwoInt64 ( utils . Str2Float64 ( cell ) * 100 ) )
}
if k == sheetParam . SkuUnitCol {
storeSkuNamePrice . Unit = cell
}
}
}
func ( d * DataLock ) AppendDataSuccess ( dataSuccess DataSuccess ) {
d . locker . Lock ( )
defer d . locker . Unlock ( )
d . dataSuccessList = append ( d . dataSuccessList , dataSuccess )
}
func ( d * DataLock ) AppendDataFailed ( dataFailed DataFailed ) {
d . locker . Lock ( )
defer d . locker . Unlock ( )
d . dataFailedList = append ( d . dataFailedList , dataFailed )
}