Commit 5e4bd169 by hcy

控制商品购买按钮

parent 465ee58b
......@@ -7,6 +7,7 @@ import (
"go_sku_server/boot"
"go_sku_server/pkg/config"
"go_sku_server/routes"
service2 "go_sku_server/service"
)
func main() {
......@@ -26,11 +27,20 @@ func main() {
web.Handler(r),
web.Address(":"+port),
)
service2.Supplier.GetSupplierForbidMap()
////初始化禁用规则
//go func() {
// for true {
// service2.Supplier.GetSupplierForbidMap()
// time.Sleep(3600 * time.Second)
// }
//}()
if err := service.Init(); err != nil {
panic(err)
}
if err := service.Run(); err != nil {
panic(err)
}
}
......@@ -92,6 +92,7 @@ type LySku struct {
Tariff float64 `json:"tariff"`
TariffFormat string `json:"tariff_format"`
AbilityLevel int `json:"ability_level"`
LabelOp int `json:"label_op"`
BrandPack string `json:"brand_pack"`
OnwayStock int `json:"onway_stock"`
}
......
package model
// 供应商禁用信息map
type SupplierForbidMap map[string]ForbidInfo
// 供应商禁止信息,会转换一次
type ForbidInfo struct {
SupplierId int `json:"supplier_id"` // 供应商id
StandardBrandIds []int // 禁止标准品牌列表
Eccns []string // 禁止eccn列表
GoodsNames []string // 禁止型号列表
SkuIds []string // 禁止sku_ids
SpuIds []string // 禁止spu_ids
ClassId1 []string //
ClassId2 []string //
EccnNo []string // 白名单 eccn
}
// 供应商禁止信息, redis中存储的
type RedisForbidInfo struct {
SupplierId int `json:"supplier_id"` // 供应商id
StandardBrandId string `json:"standard_brand_id"` // 禁止标准品牌,多个用,分割 8,130
Eccn string `json:"eccn"` // 禁止eccn ,多个用,分割 %3A001%,%3A292%
GoodsName string `json:"goods_name"` // 禁止型号,多个用 € 分割
SkuId string `json:"sku_id"` // 禁止sku_id多个用 € 分割
SpuId string `json:"spu_id"` // 禁止spu_id多个用 € 分割
ClassId1 string `json:"class_id1"`
ClassId2 string `json:"class_id2"`
EccnNo string `json:"eccn_no"` // 白名单 eccn
}
......@@ -27,6 +27,49 @@ import (
"github.com/tidwall/gjson"
)
func GetMd5KeyUpper(str string) string {
lowerStr := strings.ToUpper(str)
// 创建 MD5 散列对象
hash := md5.New()
// 计算字符串的 MD5 散列值
hash.Write([]byte(lowerStr))
// 获取计算后的 MD5 散列值
hashed := hash.Sum(nil)
// 将散列值转换为十六进制字符串表示
md5Str := hex.EncodeToString(hashed)
return md5Str
}
// 判断是否在字符串数组切片中
func InStringArray(needle string, haystack []string) bool {
for _, item := range haystack {
if item == needle {
return true
}
}
return false
}
func InIntArray(target int, arr []int) bool {
sort.Ints(arr)
index := sort.SearchInts(arr, target)
return index < len(arr) && arr[index] == target
}
// ReplaceSpecialCharts 替换特殊字符
func ReplaceSpecialCharts(str string) string {
reg := regexp.MustCompile(`[^A-Za-z0-9]+`)
return reg.ReplaceAllString(str, "")
}
func GetUpperAndTrimStr(str string) string {
// 使用 Fields 方法将字符串拆分为单词,并重新组合
words := strings.Fields(str)
filteredStr := strings.Join(words, "")
upperStr := strings.ToUpper(filteredStr)
return upperStr
}
/*
gjson 判断某值是否存在 map
@param json string 分析json字符串
......
......@@ -19,6 +19,51 @@ import (
type ActivityService struct {
}
/*
控制前端3.0购买 加入购物车 联系销售等按钮
https://www.tapd.cn/tapd_fe/20225591/story/detail/1120225591001012052
todo 1 加入购物车、立即购买 :
6项条件须同时满足
是否属于网站屏蔽范围:不属于
商品状态:上架
商品是否过期:否
库存数量:不为空,且,>0,且,≥起订量
商品价格:不为空,且,>0(人民币、美金价格至少有一个满足)
履约程度:强履约
todo 2 加入询价池、立即询价
6项条件须同时满足
是否属于网站屏蔽范围:不属于
商品状态:上架
商品是否过期:否
库存数量:不为空,且,>0,且,≥起订量
商品价格:不为空,且,>0(人民币、美金价格至少有一个满足)
履约程度:强履约
todo 3 联系销售
规则1 且 规则2 不符合
*/
func (as *ActivityService) GetLabelOp(sku model.LySku) (op int) {
var taxCheck map[string]map[string]string
if sku.SupplierId == 7 {
taxCheck = Supplier.GetTaxMap([]string{sku.GoodsName}, "3C目录内")
}
forbidStatus, _ := Supplier.GetSkuForbidStatus(sku.SupplierId, sku.StandardBrand.StandardBrandId, sku.GoodsName, sku.GoodsId, sku.Eccn, sku.SpuId, sku.Canal, gconv.String(sku.ClassID1), gconv.String(sku.ClassID2), taxCheck)
if sku.GoodsStatus == 1 && sku.IsExpire == 0 && forbidStatus == 0 && sku.Stock > 0 && sku.LadderPrice != nil {
if sku.AbilityLevel == 2 {
return 1 //可购买
} else {
return 2 //立即询价
}
} else {
return 3 //联系销售
}
}
// 获取活动信息,目前是包括促销活动(系数打折)以及满赠活动
func (as *ActivityService) GetActivityData(checkData model.ActivityCheckData) (priceActivity model.PriceActivity, giftActivity model.GiftActivity) {
supplierId := checkData.SupplierId
......
......@@ -73,6 +73,7 @@ func (ls *LyService) LyGoodsDetail(ctx context.Context, params RequestParams, go
skuArr := gredis.Hmget("default_r", "sku", goodsIds)
//为了性能着想,这边也先去批量获取spu的信息
var spuService SpuService
var activityService ActivityService
spuList := spuService.getSpuList(skuArr)
GoodsRes := sync.Map{}
......@@ -327,6 +328,8 @@ func (ls *LyService) LyGoodsDetail(ctx context.Context, params RequestParams, go
if has {
sku.Stock = int64(limitStock)
}
//计算按钮
sku.LabelOp = activityService.GetLabelOp(sku)
//最后一步,将sku的全部信息放到有序map里面
GoodsRes.Store(goodsId, sku)
//(*goodsRes)[goodsId] = A
......
......@@ -2,6 +2,7 @@ package service
import (
"context"
"github.com/gogf/gf/util/gconv"
"go_sku_server/model"
"go_sku_server/pkg/common"
"go_sku_server/pkg/gredis"
......@@ -126,10 +127,15 @@ func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams
spuId := gjson.Get(info, "spu_id").Int()
var standardBrand model.StandardBrand
var brandId int64
var spuClassId1 int64
var spuClassId2 int64
var brandName string
var activityService ActivityService
if spuId != 0 {
spuStr, _ := gredis.String(redisConnSpu.Do("HGET", "spu", spuId))
brandId = gjson.Get(spuStr, "brand_id").Int()
spuClassId1 = gjson.Get(spuStr, "class_id1").Int()
spuClassId2 = gjson.Get(spuStr, "class_id2").Int()
brandName, _ = gredis.String(redisConn.Do("HGET", "brand", brandId))
var ly LyService
standardBrand = ly.GetStandardBrand(brandId)
......@@ -353,6 +359,20 @@ func (qs *ZiyingService) ZyGoodsDetail(ctx context.Context, params RequestParams
A.Set("canal", "L0003270") //自营写死编码
//todo 计算购买按钮
nowstock, _ := A.Get("stock")
var lySku = model.LySku{
GoodsId: goodsId,
Stock: gconv.Int64(nowstock),
AbilityLevel: 2,
StandardBrand: standardBrand,
GoodsName: gjson.Get(info, "goods_name").String(),
SpuId: gconv.String(spuId),
ClassID1: gconv.Int(spuClassId1),
ClassID2: gconv.Int(spuClassId2),
}
A.Set("label_op", activityService.GetLabelOp(lySku))
//最后写入sync map
(GoodsRes).Store(goodsId, A)
}
......
package service
import (
"encoding/json"
"fmt"
"github.com/gogf/gf/util/gconv"
"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"
)
type sSupplier struct{}
var (
Supplier = &sSupplier{}
)
type EccnMatchRule int
const (
EccnStartWith EccnMatchRule = iota
EccnEndWith
EccnContain
EccnExactMatch
)
var supplierForbidMap model.SupplierForbidMap
// 获取供应商禁用信息
func (s *sSupplier) GetSupplierForbidMap() {
var (
redisConn = gredis.Conn("search_w")
)
defer redisConn.Close()
supplierForbidMapT := model.SupplierForbidMap{}
ratioAll, _ := redis.Values(redisConn.Do("hgetall", "forbid_search_supplier"))
var retioArr []string
err := redis.ScanSlice(ratioAll, &retioArr)
if err != nil || len(retioArr) == 0 {
fmt.Println("查询系数失败")
return
}
for i := 0; i < len(ratioAll); i += 2 {
supplierId := ratioAll[i]
forbidJson := ratioAll[i+1]
var forbid model.RedisForbidInfo
if err := json.Unmarshal([]byte(gconv.String(forbidJson)), &forbid); err != nil {
continue
}
var standardBrandIds []int
if len(forbid.StandardBrandId) > 0 {
for _, standardBrandId := range php2go.Explode(",", forbid.StandardBrandId) {
standardBrandIds = append(standardBrandIds, gconv.Int(standardBrandId))
}
}
var goodsNames []string
if len(forbid.GoodsName) > 0 {
for _, goodsName := range php2go.Explode("€", forbid.GoodsName) {
goodsNames = append(goodsNames, common.GetUpperAndTrimStr(common.ReplaceSpecialCharts(goodsName)))
}
}
var skuIds []string
if len(forbid.SkuId) > 0 {
for _, skuId := range php2go.Explode("€", forbid.SkuId) {
skuIds = append(skuIds, skuId)
}
}
var spuIds []string
if len(forbid.SpuId) > 0 {
for _, spuId := range php2go.Explode("€", forbid.SpuId) {
spuIds = append(spuIds, spuId)
}
}
supplierIdStr := gconv.String(supplierId)
/*
供应商编码规则
11) "17_L0000038"
12) "{\"supplier_id\":17,\"supplier_code\":\"L0000038\",\"standard_brand_id\":\"1\",\"eccn\":\"\",\"goods_name\":\"\",\"sku_id\":\"\",\"spu_id\":\"\"}"
*/
ClassId1 := []string{}
if forbid.ClassId1 != "" {
ClassId1 = php2go.Explode(",", forbid.ClassId1)
}
ClassId2 := []string{}
if forbid.ClassId2 != "" {
ClassId2 = php2go.Explode(",", forbid.ClassId2)
}
EccnNo := []string{}
if forbid.EccnNo != "" {
EccnNo = php2go.Explode(",", forbid.EccnNo)
}
Eccn := []string{}
if forbid.Eccn != "" {
Eccn = php2go.Explode("€", forbid.Eccn)
}
if php2go.Stripos(supplierIdStr, "_", 0) > 0 {
canalArr := php2go.Explode("_", supplierIdStr)
supplierForbidMapT[canalArr[1]] = model.ForbidInfo{
SupplierId: forbid.SupplierId,
StandardBrandIds: standardBrandIds,
Eccns: Eccn,
GoodsNames: goodsNames,
SkuIds: skuIds,
SpuIds: spuIds,
ClassId1: ClassId1,
ClassId2: ClassId2,
EccnNo: EccnNo,
}
} else {
/*
1) "14"
2) "{\"supplier_id\":14,\"supplier_code\":\"\",\"standard_brand_id\":\"\",\"eccn\":\"%98%,98A,%99%\",\"goods_name\":\"\",\"sku_id\":\"\",\"spu_id\":\"\",\"class_id1\":\"1,2\",\"class_id2\":\"\",\"eccn_no\":\"99A,33J\"}"
*/
supplierForbidMapT[supplierIdStr] = model.ForbidInfo{
SupplierId: forbid.SupplierId,
StandardBrandIds: standardBrandIds,
Eccns: Eccn,
GoodsNames: goodsNames,
SkuIds: skuIds,
SpuIds: spuIds,
ClassId1: ClassId1,
ClassId2: ClassId2,
EccnNo: EccnNo,
}
}
}
supplierForbidMap = supplierForbidMapT
}
/*
获取供应商sku禁止状态
taxCheck 税务检测
*/
func (s *sSupplier) GetSkuForbidStatus(supplier_id int64, standardBrandId int, goodsName, skuId, eccn, spuId, canal, classId1, classId2 string, taxCheck map[string]map[string]string) (int, string) {
// 默认0, sku未禁止,1表示sku禁止
var forbidStatus = 0
//todo 在关税系统中,只关注型号,和品牌 无关,只要是型号属于3C目录内,不管啥品牌都不能在DGK渠道展示
if supplier_id == 7 && len(taxCheck) > 0 {
_, ok := taxCheck[goodsName]
if ok {
return 1, "关税禁用"
}
}
msg := "" //禁用说明
// 全局屏蔽检查 (supplierForbidMap[0])
globalForbidInfo, globalOk := supplierForbidMap["0"]
if globalOk {
// 应用全局规则
if common.InIntArray(standardBrandId, globalForbidInfo.StandardBrandIds) ||
common.InStringArray(skuId, globalForbidInfo.SkuIds) ||
common.InStringArray(spuId, globalForbidInfo.SpuIds) ||
common.InStringArray(classId1, globalForbidInfo.ClassId1) ||
common.InStringArray(classId2, globalForbidInfo.ClassId2) ||
common.InStringArray(goodsName, globalForbidInfo.GoodsNames) {
forbidStatus = 1
msg = "全局spu-sku-goods_name禁用"
}
// 检查全局 ECCN 规则
if len(globalForbidInfo.Eccns) > 0 {
for _, eccnRule := range globalForbidInfo.Eccns {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
forbidStatus = 1
msg = "全局eccn禁用"
break
}
}
}
// 适用于 supplier_id 为 14 (mouser) 的额外条件,白名单
if len(globalForbidInfo.EccnNo) > 0 {
checkHas := false
for _, eccnRule := range globalForbidInfo.EccnNo {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
checkHas = true
break
}
}
if !checkHas {
forbidStatus = 1
msg = "全局白名单 " + eccn + " 禁用"
}
}
}
// 检查供应商特定规则
supForbidInfo, ok := supplierForbidMap[gconv.String(supplier_id)]
if ok {
// 应用供应商特定规则
if common.InIntArray(standardBrandId, supForbidInfo.StandardBrandIds) ||
common.InStringArray(skuId, supForbidInfo.SkuIds) ||
common.InStringArray(spuId, supForbidInfo.SpuIds) ||
common.InStringArray(classId1, supForbidInfo.ClassId1) ||
common.InStringArray(classId2, supForbidInfo.ClassId2) ||
common.InStringArray(goodsName, supForbidInfo.GoodsNames) {
forbidStatus = 1
msg = "指定供应商n条件禁用"
}
// 检查供应商特定 ECCN 规则
if len(supForbidInfo.Eccns) > 0 {
for _, eccnRule := range supForbidInfo.Eccns {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
forbidStatus = 1
msg = "指定eccn禁用"
break
}
}
}
// 适用于 supplier_id 为 14 (mouser) 的额外条件,白名单
if len(supForbidInfo.EccnNo) > 0 {
checkHas := false
for _, eccnRule := range supForbidInfo.EccnNo {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
checkHas = true
break
}
}
if !checkHas {
forbidStatus = 1
msg = "指定供应商白名单 " + eccn + " 禁用"
}
}
}
//检查编码特殊规则
if canal != "" {
supForbidInfo, ok := supplierForbidMap[canal]
if ok {
// 应用供应商特定规则
if common.InIntArray(standardBrandId, supForbidInfo.StandardBrandIds) ||
common.InStringArray(skuId, supForbidInfo.SkuIds) ||
common.InStringArray(spuId, supForbidInfo.SpuIds) ||
common.InStringArray(classId1, supForbidInfo.ClassId1) ||
common.InStringArray(classId2, supForbidInfo.ClassId2) ||
common.InStringArray(goodsName, supForbidInfo.GoodsNames) {
forbidStatus = 1
msg = "专卖渠道供应商 spu-sku-goods_name禁用"
}
// 检查供应商特定 ECCN 规则
if len(supForbidInfo.Eccns) > 0 {
for _, eccnRule := range supForbidInfo.Eccns {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
forbidStatus = 1
msg = "专卖渠道供应商 eccn禁用"
break
}
}
}
// 适用于 supplier_id 为 14 (mouser) 的额外条件,白名单
if len(supForbidInfo.EccnNo) > 0 {
checkHas := false
for _, eccnRule := range supForbidInfo.EccnNo {
rule := Supplier.GetEccnMatchRule(eccnRule)
if Supplier.GetEccnMatchPattern(eccn, eccnRule, rule) {
checkHas = true
break
}
}
if !checkHas {
forbidStatus = 1
msg = "指定供应商编码白名单 " + eccn + " 禁用"
}
}
}
}
return forbidStatus, msg
}
// 获取供应商eccn匹配规则
func (s *sSupplier) GetEccnMatchRule(keyword string) EccnMatchRule {
if strings.HasPrefix(keyword, "%") && strings.HasSuffix(keyword, "%") {
return EccnContain
} else if strings.HasPrefix(keyword, "%") {
return EccnEndWith
} else if strings.HasSuffix(keyword, "%") {
return EccnStartWith
} else {
return EccnExactMatch
}
}
// 判断供应商eccn匹配情况
func (s *sSupplier) GetEccnMatchPattern(text, keyword string, rule EccnMatchRule) bool {
switch rule {
case EccnStartWith:
return strings.HasPrefix(text, strings.TrimPrefix(keyword, "%"))
case EccnEndWith:
return strings.HasSuffix(text, strings.TrimSuffix(keyword, "%"))
case EccnContain:
return strings.Contains(text, strings.Trim(keyword, "%"))
case EccnExactMatch:
return text == keyword
default:
return false
}
}
// 批量获取税率数据
func (s *sSupplier) GetTaxMap(goods_names []string, goods_property string) map[string]map[string]string {
var (
redisConn = gredis.Conn("search_w")
)
defer redisConn.Close()
var tMap = map[string]map[string]string{}
if len(goods_names) > 0 {
tmd5 := make([]string, 0)
for _, goods_name := range goods_names {
tmd5 = append(tmd5, common.GetMd5KeyUpper(goods_name))
}
redisList := gredis.Hmget("search_r", "tax_customs_info_v2", tmd5) //批量获取商品详情
for i, goods_name := range redisList {
goodsTagRedis := gconv.String(redisList[i])
if goodsTagRedis == "" {
continue
}
goods_property_now := gjson.Get(goodsTagRedis, "goods_property").String()
if goods_property != "" {
if goods_property_now == goods_property {
tMap[goods_name] = map[string]string{
"goods_property": goods_property_now,
}
}
} else {
tMap[goods_name] = map[string]string{
"goods_property": goods_property_now,
}
}
}
}
return tMap
}
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