Commit bb6e33c3 by mushishixian

初步完成

parent d62003c2
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
"sync" "sync"
) )
const goods_slice_count = 10 //每多少个型号id开启一个协程 const goods_slice_count = 10 //每多少个型号id开启一个协程
/* /*
...@@ -29,62 +28,62 @@ const goods_slice_count = 10 //每多少个型号id开启一个协程 ...@@ -29,62 +28,62 @@ const goods_slice_count = 10 //每多少个型号id开启一个协程
*/ */
func Synchronization(ctx *gin.Context) { func Synchronization(ctx *gin.Context) {
common.PrintDebugHeader(ctx) //开启debug调试 common.PrintDebugHeader(ctx) //开启debug调试
zyService := service.ZiyingService{} //实例化自营查询 zyService := service.ZiyingService{} //实例化自营查询
lyService := service.LyService{} //实例化自营查询 lyService := service.LyService{} //实例化自营查询
//抽取自营 或者联营 goods_id //抽取自营 或者联营 goods_id
GoodsIdStr := ctx.Request.FormValue("goods_id") GoodsIdStr := ctx.Request.FormValue("goods_id")
if GoodsIdStr == "" { if GoodsIdStr == "" {
common.Output(ctx,1001,"查询型号ID不得为空","") common.Output(ctx, 1001, "查询型号ID不得为空", "")
return return
} }
GoodsRes := sync.Map{} GoodsRes := sync.Map{}
goodsIdArr := php2go.Explode(",",GoodsIdStr) goodsIdArr := php2go.Explode(",", GoodsIdStr)
wg := sync.WaitGroup{} //协程 wg := sync.WaitGroup{} //协程
zyGoodsId := make([]string,0) zyGoodsId := make([]string, 0)
lyGoodsId := make([]string,0) lyGoodsId := make([]string, 0)
for _,goods_id := range goodsIdArr { for _, goods_id := range goodsIdArr {
if len(goods_id) < 19 { //自营 if len(goods_id) < 19 { //自营
zyGoodsId = append(zyGoodsId,goods_id) zyGoodsId = append(zyGoodsId, goods_id)
if len(zyGoodsId) >= goods_slice_count { if len(zyGoodsId) >= goods_slice_count {
common.PrintDebugHtml(ctx,"zy增加协程:") common.PrintDebugHtml(ctx, "zy增加协程:")
common.PrintDebugHtml(ctx,zyGoodsId) common.PrintDebugHtml(ctx, zyGoodsId)
wg.Add(1) //协程计数一 wg.Add(1) //协程计数一
go zyService.ZyGoodsDetail(ctx,zyGoodsId,&GoodsRes,&wg) go zyService.ZyGoodsDetail(ctx, zyGoodsId, &GoodsRes, &wg)
zyGoodsId = zyGoodsId[:0:0] zyGoodsId = zyGoodsId[:0:0]
} }
}else{ //联营 } else { //联营
lyGoodsId = append(lyGoodsId,goods_id) lyGoodsId = append(lyGoodsId, goods_id)
if len(lyGoodsId) >= goods_slice_count { if len(lyGoodsId) >= goods_slice_count {
common.PrintDebugHtml(ctx,"ly增加协程:") common.PrintDebugHtml(ctx, "ly增加协程:")
common.PrintDebugHtml(ctx,zyGoodsId) common.PrintDebugHtml(ctx, zyGoodsId)
wg.Add(1) wg.Add(1)
go lyService.LyGoodsDetail(lyGoodsId,&wg) go lyService.LyGoodsDetail(ctx, lyGoodsId, &GoodsRes, &wg)
lyGoodsId = lyGoodsId[:0:0] lyGoodsId = lyGoodsId[:0:0]
} }
} }
} }
if len(zyGoodsId) >0 { if len(zyGoodsId) > 0 {
common.PrintDebugHtml(ctx,"zy增加协程:") common.PrintDebugHtml(ctx, "zy增加协程:")
common.PrintDebugHtml(ctx,zyGoodsId) common.PrintDebugHtml(ctx, zyGoodsId)
wg.Add(1) //协程计数一 wg.Add(1) //协程计数一
go zyService.ZyGoodsDetail(ctx,zyGoodsId,&GoodsRes,&wg) go zyService.ZyGoodsDetail(ctx, zyGoodsId, &GoodsRes, &wg)
} }
if len(lyGoodsId) >= goods_slice_count { if len(lyGoodsId) >= 0 {
common.PrintDebugHtml(ctx,"ly增加协程:") common.PrintDebugHtml(ctx, "ly增加协程:")
common.PrintDebugHtml(ctx,zyGoodsId) common.PrintDebugHtml(ctx, zyGoodsId)
wg.Add(1) wg.Add(1)
go lyService.LyGoodsDetail(lyGoodsId,&wg) go lyService.LyGoodsDetail(ctx, lyGoodsId, &GoodsRes, &wg)
} }
wg.Wait() wg.Wait()
...@@ -92,18 +91,17 @@ func Synchronization(ctx *gin.Context) { ...@@ -92,18 +91,17 @@ func Synchronization(ctx *gin.Context) {
//异步map最后转成map //异步map最后转成map
temp := make(map[string]interface{}) temp := make(map[string]interface{})
GoodsRes.Range(func(k, v interface{}) bool { GoodsRes.Range(func(k, v interface{}) bool {
s,_ := k.(string) s, _ := k.(string)
temp[s] = v temp[s] = v
return true return true
}) })
common.Output(ctx,0,"查询成功",temp) common.Output(ctx, 0, "查询成功", temp)
} }
/* /*
健康监测 健康监测
*/ */
func Health(ctx *gin.Context) { func Health(ctx *gin.Context) {
ctx.String(200,"ok") ctx.String(200, "ok")
} }
package model
type Coefficient struct {
Cn float64 `json:"cn"`
Hk float64 `json:"hk"`
ExtraRatio float64 `json:"extra_ratio"`
IsDefault int64 `json:"is_default"`
Ratio float64 `json:"ratio"`
Tax float64 `json:"tax"`
}
...@@ -12,9 +12,10 @@ type LadderPrice struct { ...@@ -12,9 +12,10 @@ type LadderPrice struct {
PriceUs float64 `json:"price_us"` //数量对应的英文价格 PriceUs float64 `json:"price_us"` //数量对应的英文价格
PriceCn float64 `json:"price_cn"` //数量对应的中文价格 PriceCn float64 `json:"price_cn"` //数量对应的中文价格
PriceAc float64 `json:"price_ac"` PriceAc float64 `json:"price_ac"`
CostPrice float64 `json:"-"`
} }
//立创价格梯度 //立创价格梯度
type LadderPriceLc struct { type LadderPriceLc struct {
Purchases int64 `json:"purchases"` //购买数量 Purchases int64 `json:"purchases"` //购买数量
Price float64 `json:"price"` //立创价格,人民币 Price float64 `json:"price"` //立创价格,人民币
} }
\ No newline at end of file
package model
import (
"github.com/tidwall/gjson"
"go_sku_server/pkg/common"
)
//联营sku结构体
type LySku struct {
GoodsId int64 `json:"goods_id"`
GoodsSn string `json:"goods_sn"`
SpuId string `json:"spu_id"`
BrandId int64 `json:"brand_id"`
BrandName string `json:"brand_name"`
UpdateTime int64 `json:"update_time"`
GoodsStatus int64 `json:"goods_status"`
GoodsName string `json:"goods_name"`
GoodsType int64 `json:"goods_type"`
SupplierId int64 `json:"supplier_id"`
Encoded string `json:"encoded"`
BatchSn string `json:"batch_sn"`
Moq int64 `json:"moq"`
Mpq int64 `json:"mpq"`
Stock int64 `json:"stock"`
HkDeliveryTime string `json:"hk_delivery_time"`
CnDeliveryTime string `json:"cn_delivery_time"`
GoodsDetails string `json:"goods_details"`
GoodsImages string `json:"goods_images"`
LadderPrice []LadderPrice `json:"ladder_price"`
Original []LadderPrice `json:"original_price"`
Canal string `json:"canal"`
CpTime int64 `json:"cp_time"`
Packing string `json:"packing"`
ImagesL string `json:"images_l"`
Pdf string `json:"pdf"`
ClassName string `json:"class_name"`
ClassName1 string `json:"class_name1"`
ClassName2 string `json:"class_name2"`
ClassName3 string `json:"class_name3"`
ErpTax map[string]interface{} `json:"erp_tax"`
SupplierName string `json:"supplier_name"`
Attrs []map[string]string `json:"attrs"`
ScmBrand map[string]interface{} `json:"scm_brand"`
AcType int `json:"ac_type"`
AllowCoupon int `json:"allow_coupon"`
Ratio float64 `json:"ratio"`
SuppExtendFee interface{} `json:"supp_extend_fee"`
IsBuy int `json:"is_buy"`
//spu信息
ClassID1 int `json:"class_id1"`
ClassID2 int `json:"class_id2"`
ClassID3 int `json:"class_id3"`
SpuName string `json:"spu_name"`
SpuBrief string `json:"spu_brief"`
Status int `json:"status"`
Encap string `json:"encap"`
//活动信息
ActivityEndTime int64 `json:"activity_end_time,omitempty"`
ActivityInfo map[string]interface{} `json:"activity_info,omitempty"`
//系数相关
Coefficient Coefficient `json:"coefficient,omitempty"`
//Spu额外的信息
}
//为什么不直接映射到结构,而要用gjson,因为redis存的数据结构不一定正常,可能类型不一致
func InitSkuData(sku string) (data LySku) {
goodsId := common.MyInt64(gjson.Get(sku, "goods_id").String())
data.GoodsId = goodsId
goodsSn := gjson.Get(sku, "goods_sn").String()
data.GoodsSn = goodsSn
spuId := gjson.Get(sku, "spu_id").String()
data.SpuId = spuId
updateTime := gjson.Get(sku, "update_time").Int()
data.UpdateTime = updateTime
goodsStatus := gjson.Get(sku, "goods_status").Int()
data.GoodsStatus = goodsStatus
goodsName := gjson.Get(sku, "goods_name").String()
data.GoodsName = goodsName
goodsType := gjson.Get(sku, "goods_type").Int()
data.GoodsType = goodsType
supplierId := gjson.Get(sku, "supplier_id").Int()
data.SupplierId = supplierId
encoded := gjson.Get(sku, "encoded").String()
data.Encoded = encoded
batchSn := gjson.Get(sku, "batch_sn").String()
data.BatchSn = batchSn
moq := gjson.Get(sku, "moq").Int()
data.Moq = moq
mpq := gjson.Get(sku, "mpq").Int()
data.Mpq = mpq
stock := gjson.Get(sku, "stock").Int()
data.Stock = stock
hkDeliveryTime := gjson.Get(sku, "hk_delivery_time").String()
data.HkDeliveryTime = hkDeliveryTime
cnDeliveryTime := gjson.Get(sku, "cn_delivery_time").String()
data.CnDeliveryTime = cnDeliveryTime
goodsDetail := gjson.Get(sku, "goods_details").String()
data.GoodsDetails = goodsDetail
goodsImages := gjson.Get(sku, "goods_details").String()
data.GoodsDetails = goodsImages
canal := gjson.Get(sku, "canal").String()
data.Canal = canal
cpTime := gjson.Get(sku, "cp_time").Int()
data.CpTime = cpTime
LadderPriceStr := gjson.Get(sku, "ladder_price").String()
data.LadderPrice = getLadderPrice(LadderPriceStr)
return
}
//获取联营商品的阶梯价
func getLadderPrice(ladderPriceStr string) (ladderPrice []LadderPrice) {
ladderPriceArr := gjson.Get(ladderPriceStr, "*").Array()
for _, price := range ladderPriceArr {
ladderPrice = append(ladderPrice, LadderPrice{
Purchases: price.Get("purchases").Int(),
PriceUs: price.Get("price_us").Float(),
PriceCn: price.Get("price_cn").Float(),
PriceAc: price.Get("price_ac").Float(),
CostPrice: price.Get("cost_price").Float(),
})
}
return
}
package model
type Spu struct {
ClassID1 int `json:"class_id1"`
ClassID2 int `json:"class_id2"`
SpuName string `json:"spu_name"`
BrandID int `json:"brand_id"`
Pdf string `json:"pdf"`
ImagesL string `json:"images_l"`
SpuBrief string `json:"spu_brief"`
Status int `json:"status"`
UpdateTime int `json:"update_time"`
Encap string `json:"encap"`
}
\ No newline at end of file
package common
var KeywordRegular = map[string]string{
//`^(.* )?([\d\.]+)(欧|欧姆|R|r)( .*)?$`: `$1$2Ω$4`,
//`^(.* )?([\d\.]+)(U|u|μ)(.?)( .*)?$`: `$1$2Μ$4$5`,
"COG": "C0G",
"NPO|NP0|nPO|npO|npo|nP0|np0": "C0G",
"华科|华新科技|华新科": "华新",
`(欧姆|欧|O|o|R|r)`: "Ω",
`(Uf|uf|μf|uF|UF)`: "μF",
`(Uh|uh|μh|uH|UH)`: "μH",
`K`: "nF",
`v`: "V",
}
var PureNumberRegular = `(\d+(\.\d+)?)`
var PureLetterRegular = `[a-zA-Z0-9]+`
var GetAttrUnitRegular = `[\d.]|±|\+_|\+-|/|\(.*\)|\+/-|`
//属性单位对应属性
var UnitAttrMapping = map[string]string{
"r": "阻值(欧姆)|直流电阻(内阻)",
"Ω": "阻值(欧姆)|直流电阻(内阻)",
"OHM": "阻值(欧姆)|直流电阻(内阻)",
"mh": "电感",
"F": "容值",
"w": "功率",
"W": "功率",
"Ω/r ": "内阻",
"%": "精度",
"V": "额定电压",
"A": "额定电流",
}
//属性对应的基础属性
var UnitBaseMapping = map[string]string{
"μΩ": "Ω",
"mΩ": "Ω",
"Ω": "Ω",
"kΩ": "Ω",
"KΩ": "Ω",
"MΩ": "Ω",
"pF": "F",
"nF": "F",
"μF": "F",
"μf": "F",
"mF": "F",
"F": "F",
"μH": "H",
"mH": "H",
"H": "H",
"V": "V",
"kV": "V",
"mA": "A",
"A": "A",
"W": "W",
"kW": "W",
"KW": "W",
"%": "%",
}
//根据单位对值的转换,比如1kΩ=>1000Ω
var UnitValueMapping = map[string]string{
"μΩ": "0.000001",
"mΩ": "0.001",
"Ω": "1",
"kΩ": "1000",
"KΩ": "1000",
"MΩ": "1000000",
"pF": "1",
"nF": "1000",
"μF": "1000000",
"mF": "1000000000",
"F": "1000000000000",
"μH": "1",
"mH": "1000",
"H": "1000000",
"V": "1",
"kV": "1000",
"mA": "1",
"A": "1000",
"W": "1",
"kW": "1000",
"%": "0.01",
}
...@@ -12,22 +12,22 @@ type RedisDatabase struct { ...@@ -12,22 +12,22 @@ type RedisDatabase struct {
//多数据库配置 //多数据库配置
func BuildRedisConfgs() (RedisDatabaseMap map[string]RedisDatabase) { func BuildRedisConfgs() (RedisDatabaseMap map[string]RedisDatabase) {
redis_read_max_idle,_ := Get("default_redis_read.max_idle").Int() redisReadMaxIdle,_ := Get("default_redis_read.max_idle").Int()
redis_read_max_active,_ := Get("default_redis_read.max_active").Int() redisReadMaxActive,_ := Get("default_redis_read.max_active").Int()
redis_write_max_idle,_ := Get("default_redis_write.max_idle").Int() redisWriteMaxIdle,_ := Get("default_redis_write.max_idle").Int()
redis_write_max_active,_ := Get("default_redis_write.max_active").Int() redisWriteMaxActive,_ := Get("default_redis_write.max_active").Int()
return map[string]RedisDatabase{ return map[string]RedisDatabase{
"search_r": { "search_r": {
Host: Get("default_redis_read.host").String(), Host: Get("default_redis_read.host").String(),
Password: Get("default_redis_read.password").String(), Password: Get("default_redis_read.password").String(),
MaxIdle: redis_read_max_idle, MaxIdle: redisReadMaxIdle,
MaxActive: redis_read_max_active, MaxActive: redisReadMaxActive,
}, },
"search_w": { "search_w": {
Host: Get("default_redis_write.host").String(), Host: Get("default_redis_write.host").String(),
Password: Get("default_redis_write.password").String(), Password: Get("default_redis_write.password").String(),
MaxIdle: redis_write_max_idle, MaxIdle: redisWriteMaxIdle,
MaxActive: redis_write_max_active, MaxActive: redisWriteMaxActive,
}, },
} }
} }
...@@ -2,99 +2,195 @@ package service ...@@ -2,99 +2,195 @@ package service
import ( import (
"fmt" "fmt"
"github.com/gin-gonic/gin"
"github.com/gomodule/redigo/redis" "github.com/gomodule/redigo/redis"
"github.com/iancoleman/orderedmap"
"github.com/syyongx/php2go" "github.com/syyongx/php2go"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"go_sku_server/model" "go_sku_server/model"
"go_sku_server/pkg/gredis" "go_sku_server/pkg/gredis"
"strings" "sort"
"sync" "sync"
) )
type LyService struct { type LyService struct {
} }
type Power struct {
UserId string `json:"user_id"`
Mobile string `json:"mobile"`
Email string `json:"email"`
Member string `json:"member"`
VerifyBlacklist string `json:"verify_blacklist"`
}
/* /*
联营数据详情 联营数据详情
*/ */
func (qs *LyService) LyGoodsDetail(goodsIds []string, wg *sync.WaitGroup) (results model.LyResponse) { func (ls *LyService) LyGoodsDetail(ctx *gin.Context, goodsIds []string, goodsRes *sync.Map, wg *sync.WaitGroup) (results model.LyResponse) {
redisConn := gredis.Conn("search_r") redisConn := gredis.Conn("search_r")
defer func() { defer func() {
wg.Done() wg.Done()
redisConn.Close() redisConn.Close()
}() }()
fast := ctx.Request.FormValue("power[fast]")
isNewCustomer := ctx.Request.FormValue("power[newCustomer]")
power := Power{
UserId: ctx.Request.FormValue("power[user_id]"),
Mobile: ctx.Request.FormValue("power[mobile]"),
Email: ctx.Request.FormValue("power[email]"),
Member: ctx.Request.FormValue("power[member]"),
VerifyBlacklist: ctx.Request.FormValue("power[verify_blacklist]"),
}
//批量获取商品详情 //批量获取商品详情
skuArr := gredis.HgetPi("search_r", "sku", goodsIds) skuArr := gredis.HgetPi("search_r", "sku", goodsIds)
//为了性能着想,这边也先去批量获取spu的信息 //为了性能着想,这边也先去批量获取spu的信息
spuList := qs.getSpuList(goodsIds) spuList := ls.getSpuList(goodsIds)
fmt.Println(spuList) for goodsId, skuStr := range skuArr {
for goodsId, info := range skuArr { //初始化有序map,拼接data 数据
A := orderedmap.New() //初始化有序map,拼接data 数据 //A := orderedmap.New()
A.Set("packing", "") sku := model.InitSkuData(skuStr)
spu := spuList[sku.SpuId]
//读取包装字段的缓存 //读取包装字段的缓存
if gjson.Get(info, "supplier_id").Int() == 7 { if sku.SupplierId == 7 {
//sku_raw_map哪里写入(成意写的) //sku_raw_map哪里写入(成意写的)
packing, err := redis.String(redisConn.Do("HGET", "SKU_RAW_MAP", goodsId)) packing, _ := redis.String(redisConn.Do("HGET", "sku_raw_map", goodsId))
if err == nil { sku.Packing = gjson.Get(packing, "pack").String()
A.Set("packing", gjson.Get(packing, "pack").String())
}
}
A.Set("goods_id", goodsId)
//去获取spu的信息
spuInfo := spuList[goodsId]
spuLargeImage := gjson.Get(spuInfo, "images_l").String()
A.Set("images_l", spuLargeImage)
if spuLargeImage != "" && php2go.Strlen(spuLargeImage) < 5 {
A.Set("images_l", "")
} }
sku = ls.GetGoodsImages(sku, spu)
pdf := gjson.Get(spuInfo, "pdf").String() //pdf
A.Set("pdf", pdf) pdf := gjson.Get(spu, "pdf").String()
spuLargeImage := gjson.Get(spu, "images_l").String()
if pdf == "" || (php2go.Strlen(spuLargeImage) < 5) { if pdf == "" || (php2go.Strlen(spuLargeImage) < 5) {
A.Set("pdf", "") sku.Pdf = ""
} else {
sku.Pdf = pdf
} }
//商品图片不存在用大图代替 //处理分类
goodsImage := gjson.Get(info, "goods_images").String() //fast的参数含义,为了节省开销性能的参数,传1就不会去分类这些参数
A.Set("goods_images", goodsImage) if fast != "1" {
if goodsImage == "" && spuLargeImage != "" { sku = ls.GetGoodsClass(sku, spu)
goodsImage = spuLargeImage
A.Set("goods_images", spuLargeImage)
} }
//加上是否是rocelec图片的判断,如果是的话,就将图片设置为空 //获取商品名称
if strings.Contains(goodsImage, "rocelec") { if sku.GoodsName == "" {
A.Set("goods_images", "") sku.GoodsName = gjson.Get(spu, "spu_name").String()
} }
goodsName := gjson.Get(info, "goods_name").String()
A.Set("goods_name", goodsName)
if goodsName == "" {
A.Set("goods_name", gjson.Get(spuInfo, "spu_name"))
}
//获取品牌名称 //获取品牌名称
brandId := gjson.Get(spuInfo, "brand_id").String() brandId := gjson.Get(spu, "brand_id").Int()
brandName, _ := redis.String(redisConn.Do("HGET", "brand", brandId)) brandName, _ := redis.String(redisConn.Do("HGET", "brand", brandId))
A.Set("brand_name", brandName) sku.BrandName = brandName
//todo 条件判断
//获取税务信息 //获取税务信息
if true {//仅提供价格和库存 if fast != "1" { //仅提供价格和库存
if sku.GoodsName != "" && brandId != 0 {
sku.ErpTax = ls.GetErpTax(sku.GoodsName, brandName)
}
sku.SupplierName = ls.GetPoolSupplierName(sku.SupplierId)
//获取属性
sku.Attrs = ls.GetSpuAttr(sku.SpuId)
}
//获取供应链标准品牌
//什么是供应链的标准品牌 供应链那边报关的时候要求他们的标准品牌,所以要吧自己的品牌映射上去
//继来那边对接的标准品牌(下单的时候)
sku.ScmBrand = ls.GetScmBrand(brandId)
//处理过期
if gjson.Get(skuStr, "is_expire").Int() != 0 {
sku.LadderPrice = nil
}
//处理活动
sku.AcType = 0
sku.AllowCoupon = 1
sku.BrandId = brandId
//活动标识
hasActivity := false
//******************************************************************************//
//判断是否有新客价权利
if isNewCustomer == "true" {
//获取新客价
sku = ls.GetActivityPrice(sku, "_NewCustomer", power)
if sku.AcType > 0 {
hasActivity = true
}
}
//获取活动价
if !hasActivity {
sku = ls.GetActivityPrice(sku, "", power)
if sku.AcType > 0 {
hasActivity = true
}
} }
//获取会员价
if !hasActivity && power.Member == "true" {
sku = ls.GetActivityPrice(sku, "_Member", power)
if sku.AcType > 0 {
hasActivity = true
}
}
//处理阶梯价数据
if len(sku.LadderPrice) > 0 {
//排序
sort.Sort(LadderPriceSorter(sku.LadderPrice))
//取出第一个阶梯价
purchases := sku.LadderPrice[0].Purchases
if purchases > sku.Moq {
sku.Moq = purchases
}
}
//获取系数
sku = ls.GetCoefficient(sku)
//仅提供价格和库存
if fast != "1" {
if sku.SupplierId != 0 {
sku.SuppExtendFee = ls.GetExtendFee(sku.SupplierId, sku.Canal)
}
//还要处理货期
delivery := ls.GetDelivery(sku.SupplierId, sku.Canal)
sku.CnDeliveryTime = delivery["cn_delivery_time"]
sku.HkDeliveryTime = delivery["hk_delivery_time"]
}
//处理是否可以购买
if sku.Mpq == 0 {
sku.Mpq = 1
}
//判断是否可以购买
sku.IsBuy = ls.GetIsBuy(sku)
//用spuinfo补全信息
sku = ls.CombineSup(sku, spu)
//最后一步,将sku的全部信息放到有序map里面
fmt.Println(hasActivity)
(*goodsRes).Store(goodsId, sku)
//(*goodsRes)[goodsId] = A //(*goodsRes)[goodsId] = A
} }
return return
} }
func (qs *LyService) getSpuList(goodsIds []string) (spuList map[string]string) { func (ls *LyService) getSpuList(goodsIds []string) (spuList map[string]string) {
redisConn := gredis.Conn("search_r") redisConn := gredis.Conn("search_r")
defer redisConn.Close() defer redisConn.Close()
//批量获取spu详情 //批量获取spu详情
spuList = gredis.HgetPi("search_r", "sku", goodsIds) spuList = gredis.HgetPi("search_r", "spu", goodsIds)
return return
} }
package service
import (
"encoding/json"
"github.com/gomodule/redigo/redis"
"github.com/ichunt2019/logger"
"github.com/syyongx/php2go"
"github.com/tidwall/gjson"
"go_sku_server/model"
"go_sku_server/pkg/common"
"go_sku_server/pkg/gredis"
"go_sku_server/pkg/mongo"
"gopkg.in/mgo.v2/bson"
"strings"
)
//获取图片信息
func (ls *LyService) GetGoodsImages(sku model.LySku, spu string) model.LySku {
//图片
spuLargeImage := gjson.Get(spu, "images_l").String()
sku.ImagesL = spuLargeImage
if spuLargeImage != "" && php2go.Strlen(spuLargeImage) < 5 {
sku.ImagesL = ""
}
//商品图片不存在用大图代替
if sku.GoodsImages == "" && spuLargeImage != "" {
sku.GoodsImages = spuLargeImage
}
//加上是否是rocelec图片的判断,如果是的话,就将图片设置为空
if strings.Contains(sku.GoodsImages, "rocelec") {
sku.GoodsImages = ""
}
return sku
}
//获取分类信息
func (ls *LyService) GetGoodsClass(sku model.LySku, spu string) model.LySku {
//仅提供价格和库存
spuClassId1 := gjson.Get(spu, "class_id1").String()
spuClassId2 := gjson.Get(spu, "class_id2").String()
spuClassId3 := gjson.Get(spu, "class_id3").String()
if spuClassId3 != "" {
sku.ClassName = ls.GetCacheClass(spuClassId3)
sku.ClassName3 = ls.GetCacheClass(spuClassId3)
sku.ClassName2 = ls.GetCacheClass(spuClassId2)
sku.ClassName1 = ls.GetCacheClass(spuClassId1)
} else {
sku.ClassName = "其它"
}
return sku
}
//获取税务信息,对接税务系统
func (ls *LyService) GetErpTax(goodsName, brandName string) map[string]interface{} {
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
key := php2go.Md5(strings.ToUpper(goodsName + brandName))
info, _ := redis.String(redisCon.Do("HGET", "tax_customs_info", key))
data := make(map[string]interface{})
data["tariffRate"] = gjson.Get(info, "tax_rate_low")
data["types"] = gjson.Get(info, "supervision_con")
return data
}
//获取联营供应商的名字
func (ls *LyService) GetPoolSupplierName(supplierId int64) (supplierName string) {
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
supplier, _ := redis.String(redisCon.Do("HGET", "supplier", supplierId))
return gjson.Get(supplier, "supplier_name").String()
}
//从缓存获取分类
func (ls *LyService) GetCacheClass(classId string) string {
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
className, _ := redis.String(redisCon.Do("HGET", "class", classId))
return className
}
type SpuAttr struct {
SpuId string `bson:"spu_id"`
AttrsExtend string `bson:"attrs_extend"`
Attrs string `bson:"attrs"`
}
//获取Spu的属性
func (ls *LyService) GetSpuAttr(spuId string) (attrsResult []map[string]string) {
var spuAttr SpuAttr
err := mongo.Conn("default").DB("ichunt").C("spu_attrs").Find(bson.M{"spu_id": spuId}).One(&spuAttr)
if err != nil {
logger.Error("%s", err)
}
attrs := make(map[string]string)
if spuAttr.Attrs != "" {
err = json.Unmarshal([]byte(spuAttr.Attrs), &attrs)
if err != nil {
logger.Error("%s", err)
}
}
for key, value := range attrs {
data := make(map[string]string)
data["attr_name"] = key
data["attr_value"] = value
attrsResult = append(attrsResult, data)
}
return
}
//H获取供应链标准品牌
func (ls *LyService) GetScmBrand(brandId int64) (scmBrand map[string]interface{}) {
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
scmBrandId, err := redis.Int(redisCon.Do("HGET", "pool_scm_brand_mapping", brandId))
if err != nil {
logger.Error("%s", err)
}
if scmBrandId != 0 {
scmBrandData, err := redis.String(redisCon.Do("HGET", "pool_scm_brand", scmBrandId))
if err != nil {
logger.Error("%s", err)
}
scmBrand = make(map[string]interface{})
scmBrand["erp_brand_name"] = gjson.Get(scmBrandData, "erp_brand_name").String()
scmBrand["erp_brand_id"] = gjson.Get(scmBrandData, "erp_brand_id").Int()
scmBrand["scm_brand_id"] = scmBrandId
}
return
}
type ExtendFee struct {
Cn struct {
Max interface{} `json:"max"`
Price interface{} `json:"price"`
} `json:"cn"`
Hk struct {
Max interface{} `json:"max"`
Price interface{} `json:"price"`
} `json:"hk"`
}
//获取附加费
func (ls *LyService) GetExtendFee(supplierId int64, canal string) interface{} {
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
if supplierId == 17 {
//为什么专卖的redis键会不一样,专卖的附加费管理在供应商系统,其它的在基石
value, _ := redis.String(redisCon.Do("HGET", "supp_extend_fee", "17"+canal))
//专卖的存了两种形式的数据,真是搞人心态
if strings.Contains(value, "cn") {
var extendFee ExtendFee
json.Unmarshal([]byte(value), &extendFee)
return extendFee
} else {
var extendFee []map[string]interface{}
json.Unmarshal([]byte(value), &extendFee)
return extendFee
}
} else {
value, _ := redis.String(redisCon.Do("HGET", "supp_extend_fee", supplierId))
var extendFee ExtendFee
json.Unmarshal([]byte(value), &extendFee)
return extendFee
}
}
//获取系数
func (ls *LyService) GetCoefficient(sku model.LySku) model.LySku {
if len(sku.LadderPrice) == 0 {
return sku
}
flag := 0
//专卖
originalLadderPrice := sku.LadderPrice
if sku.SupplierId == 17 {
ladderPrice := sku.LadderPrice
for key, price := range ladderPrice {
if price.Purchases == 0 {
continue
}
ladderPrice[key].PriceUs = common.MyRound(price.PriceUs, 4)
ladderPrice[key].PriceCn = common.MyRound(price.PriceCn, 4)
//联营或者专卖 同时 存在活动价格
if (sku.GoodsType == 1 || sku.GoodsType == 2) && sku.AcType > 1 && sku.Ratio > 0 {
acPrice := price.PriceCn
ladderPrice[key].PriceAc = common.MyRound(price.PriceCn*(sku.Ratio/100), 4)
//优惠价后等于0,就代表没有搞活动
if ladderPrice[key].PriceAc <= 0 {
sku.AcType = 0
}
//价格与原价一样
if acPrice == ladderPrice[key].PriceAc && key < 2 {
flag++
if flag >= 2 || (len(ladderPrice) < 2) {
sku.AcType = 0
}
}
}
}
} else {
//去获取系数
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
ratio, _ := redis.String(redisCon.Do("HGET", "pool_supplier_ratio", sku.SupplierId))
if ratio != "" {
logger.Error("%s", "系数获取异常,供应商:"+common.ToString(sku.SupplierId))
return sku
}
ratios := gjson.Parse(ratio).Array()
var defaultCoefficient, coefficient model.Coefficient
var hasDefault, hasCoefficient bool
//查找使用哪个系数
for _, ratio := range ratios {
ratioInfo := model.Coefficient{
Cn: ratio.Get("cn").Float(),
Hk: ratio.Get("hk").Float(),
ExtraRatio: ratio.Get("extra_ratio").Float(),
Ratio: ratio.Get("ratio").Float(),
}
isDefault := ratio.Get("is_default").Int()
if isDefault == 2 {
defaultCoefficient = ratioInfo
hasDefault = true
continue
}
goodsName := ratio.Get("goods_name").String()
brandName := ratio.Get("brand_name").String()
if goodsName == "" && brandName == "" {
continue
}
if brandName != "" && strings.Contains(brandName, sku.BrandName) {
coefficient = ratioInfo
hasCoefficient = true
break
}
//存在goods_name的对比吗,为什么,因为系数可以单独针对型号配置,所以要去判断型号
//http://footstone.ichunt.net/web/SavePoolCoefficient?id=1
if brandName != "" && strings.Contains(goodsName, sku.GoodsName) {
coefficient = ratioInfo
hasCoefficient = true
break
}
}
if !hasCoefficient && !hasDefault {
logger.Error("%s", "系数获取异常,供应商:"+common.ToString(sku.SupplierId))
return sku
}
if !hasCoefficient {
coefficient = defaultCoefficient
}
// 为何是固定的1.13,关税基本不会变,有变的话跟产品沟通手动修改即可
//$tax = config('website.tax');
tax := 1.13
for key, price := range sku.LadderPrice {
if price.Purchases == 0 {
continue
}
//根据系数处理美金
sku.LadderPrice[key].PriceUs = common.MyRound(price.PriceUs*coefficient.ExtraRatio*coefficient.Hk, 4)
//处理人民币
sku.LadderPrice[key].PriceCn = common.MyRound(price.PriceUs*coefficient.ExtraRatio*coefficient.Cn*coefficient.Ratio, 4)
//处理mouser的成本价
//mouser成本价是什么,斌哥同步过来的成本价
//price.CostPrice是专门针对贸泽(mouser)的
if sku.AcType == 2 && sku.SupplierId == 14 {
if price.CostPrice != 0 {
sku.LadderPrice[key].PriceAc = common.MyRound(price.CostPrice*coefficient.ExtraRatio*coefficient.Cn*coefficient.Ratio, 4)
sku.LadderPrice[key].PriceUs = common.MyRound(price.CostPrice*coefficient.ExtraRatio*coefficient.Hk, 4)
} else {
sku.LadderPrice[key].PriceAc = price.PriceCn
}
continue
}
//处理活动价和原价相同的情况
if (sku.GoodsType == 1 || sku.GoodsType == 2) && sku.AcType > 1 && sku.Ratio > 0 {
priceAc := common.MyRound(price.PriceCn*(sku.Ratio/100), 4)
sku.LadderPrice[key].PriceAc = priceAc
if priceAc <= 0 {
sku.AcType = 0
break
} else {
if sku.AcType == 4 {
sku.LadderPrice[key].PriceCn = priceAc
sku.AcType = 0
}
}
//为什么$kp < 2,如果第一阶梯或第二阶梯价格和活动价一样,就不输出活动价了
//活动价都是有样式的和平时不一样,如果价格一样,但是样子是活动价,客户会迷惑,所以不输出即可,保持原来的样式
if sku.LadderPrice[key].PriceCn == priceAc && key < 2 {
flag++
if flag >= 2 {
sku.AcType = 0
}
if len(sku.LadderPrice) > 1 {
if sku.LadderPrice[1].PriceCn == 0 {
sku.AcType = 0
}
}
}
}
}
//输出税费到前端
coefficient.Tax = tax
sku.Coefficient = coefficient
}
sku.Original = originalLadderPrice
return sku
}
//获取供应商货期
func (ls *LyService) GetDelivery(supplierId int64, canal string) (delivery map[string]string) {
delivery = make(map[string]string)
//info := make(map[string]string)
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
if canal != "" {
supplierRatio, _ := redis.String(redisCon.Do("HGET", "supp_ratio", canal))
if supplierRatio != "" {
delivery["cn_delivery"] = gjson.Get(supplierRatio, "cn_delivery_time").String()
delivery["hk_delivery"] = gjson.Get(supplierRatio, "us_delivery_time").String()
}
return
}
info, _ := redis.String(redisCon.Do("HGET", "SUPPLIER_REDIS_INFO_", supplierId))
cnDelivery := gjson.Get(info, "cn_delivery").String()
hkDelivery := gjson.Get(info, "hk_delivery").String()
if cnDelivery != "" || hkDelivery != "" {
delivery["cn_delivery"] = cnDelivery
delivery["hk_delivery"] = hkDelivery
return
}
return
}
//判断能否购买
func (ls *LyService) GetIsBuy(sku model.LySku) (isBuy int) {
if sku.GoodsStatus != 1 {
return
}
if sku.Moq > sku.Stock {
return
}
if len(sku.LadderPrice) == 0 {
return
}
if sku.Stock == 0 {
return
}
return 1
}
//合并spu的信息
func (ls *LyService) CombineSup(sku model.LySku, spuStr string) model.LySku {
var spu model.Spu
err := json.Unmarshal([]byte(spuStr), &spu)
if err != nil {
return sku
}
sku.ClassID1 = spu.ClassID1
sku.ClassID2 = spu.ClassID2
sku.SpuName = spu.SpuName
sku.SpuBrief = spu.SpuBrief
sku.Status = spu.Status
sku.Encap = spu.Encap
return sku
}
package service
import (
"github.com/gomodule/redigo/redis"
"github.com/syyongx/php2go"
"github.com/tidwall/gjson"
"go_sku_server/model"
"go_sku_server/pkg/common"
"go_sku_server/pkg/gredis"
"strings"
"time"
)
//获取联营活动价
func (ls *LyService) GetActivityPrice(sku model.LySku, suffix string, power Power) model.LySku {
//没价格,直接返回
if len(sku.LadderPrice) == 0 {
return sku
}
// 这个是针对贸泽的活动价?如果有成本价就是代表有活动,而且活动模块没法设置mouse的活动价
if suffix == "" && sku.SupplierId == 14 {
return getMouserActivityPrice(sku)
}
//先获取活动信息,针对不同供应商不同活动类型做活动吗,每个活动只能针对一个供应商
//比如有 Self_ActivityPrice_2_Discount,Self_ActivityPrice_1_NewCustomer
redisCon := gredis.Conn("default_r")
defer redisCon.Close()
supplierIdStr := common.ToString(sku.SupplierId)
activityInfo, _ := redis.String(redisCon.Do("HGET", "Self_ActivityPrice_"+supplierIdStr+suffix))
//找不到对应的活动价格信息,就直接返回空
if activityInfo == "" {
return sku
}
//判断是否在活动范围内
startTime := gjson.Get(activityInfo, "start_time").Int()
endTime := gjson.Get(activityInfo, "end_time").Int()
currentTime := time.Now().Unix()
if !(startTime < currentTime && endTime > currentTime) {
return sku
}
//获取redis里面存储的活动相关信息
brandIdArray := gjson.Get(activityInfo, "brand_id").Array()
var brandIds []string
for _, brandId := range brandIdArray {
brandIds = append(brandIds, brandId.String())
}
goodsNameArray := gjson.Get(activityInfo, "goods_name").Array()
var goodsNames []string
for _, goodsName := range goodsNameArray {
goodsNames = append(goodsNames, goodsName.String())
}
activityCanal := gjson.Get(activityInfo, "canal").String()
activityClassId := gjson.Get(activityInfo, "class_id").String()
//刚开始默认有活动
hasActivity := true
switch suffix {
//折扣价
case "_Discount":
//判断是否有参与折扣的品牌
if len(brandIds) > 0 {
//如果是不参与折扣的品牌
if php2go.InArray(sku.BrandName, brandIds) {
hasActivity = false
}
}
//判断是否有参与折扣的型号
if len(goodsNames) > 0 {
//如果是不参与折扣的型号
if php2go.InArray(sku.GoodsName, goodsNames) {
hasActivity = false
}
}
break
case "_NewCustomer":
//判断是否符合条件
activityGoodsId := gjson.Get(activityInfo, "goods_id").String()
if activityGoodsId != "" {
//为了用字符串匹配
activityGoodsId = activityGoodsId + ","
goodsIdStr := common.ToString(sku.GoodsId)
if !strings.Contains(activityGoodsId, goodsIdStr) {
hasActivity = false
}
} else {
if len(brandIds) > 0 {
}
//专卖
//canal:渠道标签 为啥要判断专卖类型,只有专卖才有渠道标签和内部编码
if activityCanal != "" && sku.GoodsType == 2 {
activityCanal = activityCanal + ","
if !strings.Contains(activityCanal, sku.Canal) {
hasActivity = false
}
}
//3和4是? 联营和专卖为啥不需要判断分类呢,因为它们的分类没什么用,所以不需要判断
if activityClassId != "" && (sku.GoodsType == 0 || sku.GoodsType == 3 || sku.GoodsType == 4) {
activityClassId = activityClassId + ","
if !strings.Contains(activityClassId, "classId2") {
hasActivity = false
}
}
}
break
default:
//除了新客价和折扣价,剩下的价格活动
if len(brandIds) > 0 {
if !php2go.InArray(sku.BrandId, brandIds) {
hasActivity = false
}
}
if activityCanal != "" && sku.GoodsType == 2 {
canalArr := gjson.Parse(activityCanal).Array()
var canals []string
for _, canal := range canalArr {
canals = append(canals, canal.String())
}
if !php2go.InArray(sku.Canal, canals) {
hasActivity = false
}
}
//处理会员价的可见名单
// 这里整块逻辑不是很懂,is_part,visible_roster都是什么,由请求方来决定要不要会员价
//visible_roster在http://cube.ichunt.net/web/SaveMemberPrice?id=120里面设置可见会员
//只是在针对某一部分特定的会员去设置的会员价
visibleRoster := gjson.Get(activityInfo, "visible_roster").String()
if suffix == "_Member" && gjson.Get(activityInfo, "is_part").Int() == 1 &&
visibleRoster != "" {
//为了用字符串匹配
visibleRoster = visibleRoster + ","
//提取出user_id、手机号、邮箱
userInfo := make(map[string]string)
userInfo["user_id"] = power.UserId
userInfo["mobile"] = power.Mobile
userInfo["email"] = power.Email
for _, value := range userInfo {
if value != "" {
hasActivity = false
continue
}
if !strings.Contains(visibleRoster, ","+value+",") {
hasActivity = true
continue
} else {
hasActivity = false
}
}
}
//处理黑名单,只有折扣活动才有黑名单,并且是下单页面
//tverify_blacklist是用来代表获取黑名单,由请求方决定
//是否验证黑名单,用于折扣活动提交订单页面与后台下单
blacklistType := gjson.Get(activityInfo, "blacklist_type").Int()
activityId := gjson.Get(activityInfo, "activity_id").String()
activityType := gjson.Get(activityInfo, "activity_type").Int()
if suffix == "" && blacklistType != 0 && hasActivity && activityId != "" && activityType == 2 &&
power.VerifyBlacklist == "true" {
//_1 是用来区分活动价和折扣价,活动和折扣价(折扣价有黑名单,活动价没有黑名单)
//blackList, _ := redis.String(redisCon.Do("HGET", "activity_roster", activityId+"_1"))
//拼接是为了方便判断是否包含在黑名单内
//blackList = "," + blackList + ","
//blacklistTypeList := make(map[int]string)
//blacklistTypeList = map[int]string{
// 1: "nvoice",
// 2: "special_invoice",
// 3: "user_id",
// 4: "mobile",
// 5: "email",
//}
//遍历黑名单类型
//黑名单就不显示折扣价吗,黑名单只针对折扣价
//如果在黑名单内
}
}
//判断是否有活动
if !hasActivity {
return sku
}
sku.Ratio = gjson.Get(activityInfo, "ratio").Float()
switch suffix {
//会员价
case "_Member":
sku.AcType = 3
break
//新客价
case "_NewCustomer":
sku.AcType = 5
break
//折扣价
case "_Discount":
sku.AcType = 4
break
//活动价
default:
sku.AcType = 2
//折扣活动
//这里为何多了个ac_type = 8,活动价的基础上有折扣价,如果有折扣价,就要输出改成折扣价,折扣价和活动价的样式不一样
if gjson.Get(activityInfo, "activity_type").Int() == 2 {
var allowNotLogin int64
allowNotLogin = gjson.Get(activityInfo, "allow_not_login").Int()
if allowNotLogin == 0 {
allowNotLogin = 2
}
sku.ActivityInfo = map[string]interface{}{
"activity_id": gjson.Get(activityInfo, "activity_ad").String(),
"sign_name": gjson.Get(activityInfo, "sign_name").String(),
"allow_not_login": allowNotLogin,
}
sku.AcType = 8
}
break
}
//是否允许使用优惠券
allCoupon := gjson.Get(activityInfo, "allow_coupon").Int()
if allCoupon == 0 {
allCoupon = 1
}
sku.AllowCoupon = int(allCoupon)
sku.ActivityEndTime = endTime
return sku
}
func getMouserActivityPrice(sku model.LySku) model.LySku {
//判断活动价
//mouser成本价添加时间为何要对比现在的时间 mouser的成本价格过期,过期就等于活动失效,斌哥会更新这个,根据贸泽给的接口
cpTime := sku.CpTime
twoDayTimeStamp := 60 * 60 * 48
if cpTime > 0 && ((cpTime + int64(twoDayTimeStamp)) > time.Now().Unix()) {
for _, price := range sku.LadderPrice {
// ladder_price字段有cost_price字段吗,贸泽的专属字段
if price.CostPrice != 0 {
sku.AcType = 2
return sku
}
}
}
return sku
}
//阶梯价格排序算法
type LadderPriceSorter []model.LadderPrice
func (a LadderPriceSorter) Len() int {
return len(a)
}
func (a LadderPriceSorter) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a LadderPriceSorter) Less(i, j int) bool {
return a[j].Purchases < a[i].Purchases
}
package main
import (
"fmt"
"github.com/syyongx/php2go"
)
func main() {
str := `{"cn":{"max":"10000","price":"20"},"hk":{"max":69000,"price":138}}`
var res interface{}
fmt.Println(php2go.JSONDecode([]byte(str), &res))
tem, _ := php2go.JSONEncode(res)
fmt.Println(string(tem))
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment