Commit e93734cc by wang

集成日志

parent b47ee119
......@@ -11,3 +11,6 @@ cmd.exe~
/conf/prod/*.ini
/go.mod
/conf
/logs
/mylogs
/doc/test
......@@ -24,9 +24,6 @@ func Boot(configPath string) (err error) {
panic(err)
return
}
if err = logger.SetUp(); err != nil {
panic(err)
return
}
logger.Loginit()
return
}
;总配置信息
[web]
port = 60005
port = 60015
mode = debug
cors_domain = http://bom.liexin.com
......@@ -14,4 +14,4 @@ SEARCH_API_MONITOR = 6d0fa85e01a02c39347d011ae973fd21b76c6c7ce582d3ea470c6b65a31
[spu_server]
api_domain = http://localhost:60015
api_domain = http://localhost:8005
......@@ -35,3 +35,92 @@ host = 192.168.2.232
database = ichuntcms
table_prefix =
type = mysql
[sku0]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_0
table_prefix =lie_
type = mysql
[sku_0]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_0
table_prefix =lie_
type = mysql
[sku_1]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_1
table_prefix =lie_
type = mysql
[sku_2]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_2
table_prefix =lie_
type = mysql
[sku_3]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_3
table_prefix =lie_
type = mysql
[sku_4]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_4
table_prefix =lie_
type = mysql
[sku_5]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_5
table_prefix =lie_
type = mysql
[sku_6]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_6
table_prefix =lie_
type = mysql
[sku_7]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_7
table_prefix =lie_
type = mysql
[sku_8]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_8
table_prefix =lie_
type = mysql
[sku_9]
user_name = spu
password = spu
host = 192.168.1.235
database = liexin_sku_9
table_prefix =lie_
type = mysql
......@@ -6,7 +6,6 @@ import (
"go_sku_server/framework/gin_"
"go_sku_server/pkg/common"
"go_sku_server/pkg/config"
"go_sku_server/pkg/logger"
"net/http"
)
......@@ -51,13 +50,10 @@ func Cors_Middleware() gin_.Middleware {
*/
func Error_Middleware() gin.HandlerFunc {
return func(ctx *gin.Context) {
defer func() {
if err:=recover(); err!=nil{
formDataStr:=common.GetRequestParam(ctx)
errMsg:=fmt.Sprintf("%s",err)
logger.Log("接收参数:"+formDataStr+"错误:"+errMsg,"savesku",1)
common.Output(ctx,500,errMsg,nil);
common.NResponse(errMsg,500).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
}
}()
ctx.Next()
......
......@@ -6,7 +6,6 @@ import (
"go_sku_server/model/saveModel"
"go_sku_server/pkg/common"
"go_sku_server/pkg/e"
"go_sku_server/pkg/logger"
"go_sku_server/service"
)
......@@ -41,40 +40,51 @@ func SaveSku(ctx *gin.Context) {
//参数验证
var lySaveRequest saveModel.LySaveRequest
if err := ctx.ShouldBindBodyWith(&lySaveRequest,binding.JSON); err != nil {
//加日志
formDataStr:=common.GetRequestParam(ctx)
logger.Log("接收参数:"+formDataStr+"errMsg:"+err.Error(),"savesku",1)
common.Output(ctx,10001,err.Error(),nil)
common.NResponse(err.Error()).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
return
}
//执行skuSave
LySave:=service.LySaveService{}
serviceErr:=LySave.SaveSku(lySaveRequest,ctx)
serviceErr,skuId:=LySave.SaveSku(lySaveRequest,ctx)
//错误处理
if(serviceErr!=nil){
if err,ok:=serviceErr.(*e.ApiError);ok{
common.Output(ctx,err.Code,err.ErrMsg,nil)
common.NResponse(err.Error(),err.Code).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
}else{
common.Output(ctx,10001,err.Error(),nil)
common.NResponse(err.Error(),err.Code).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
}
//加日志
formDataStr1:=common.GetRequestParam(ctx)
logger.Log("接收参数:"+formDataStr1+"errMsg:"+serviceErr.Error(),"savesku",1)
return
}else {//执行成功
common.Output(ctx, 0, "success", nil)
return
res:=saveModel.LySaveResponse{0,"ok",skuId}
common.NResponse(&res).OutPut(ctx)
}
return
}
//修改
func SkuEdit(ctx *gin.Context) {
//参数验证
var lyeditRequest saveModel.LyEditRequest
if err := ctx.ShouldBindBodyWith(&lyeditRequest,binding.JSON); err != nil {
common.NResponse(err.Error()).SetLogFilePre("editSku").OpenRecordReuquest(ctx).OutPut()
return
}
func SkuEdit(ctx *gin.Context) {
//执行skuSave
LySave:=service.LySaveService{}
serviceErr,skuId:=LySave.SkuEdit(lyeditRequest)
//错误处理
if(serviceErr!=nil){
if err,ok:=serviceErr.(*e.ApiError);ok{
common.NResponse(err.Error(),err.Code).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
}else{
common.NResponse(err.Error(),err.Code).SetLogFilePre("saveSku").OpenRecordReuquest(ctx).OutPut()
}
}else {//执行成功
res:=saveModel.LySaveResponse{0,"ok",skuId}
common.NResponse(&res).OutPut(ctx)
}
return
}
......
### 请求参数示例
batch_sn
spu_brief
goods_images
```json
{
"stock": 2055,
"pn": "maritex",
"is_api": 0,
"url": "https://en.maritex.com.pl/acoustics/audio_transducers/magnetic_buzzers_without_driving_circuit/cfd02-e.html",
"goods_name": "CFD02-E6",
"goods_sn": "CFD02-E",
"brand_name": "Changzhou EST ELECTRONICS Co.,Ltd.",
"is_error": 0,
"supplier_id": 17,
"canal": "L0010826",
"mpq": 1,
"moq": 1,
"pdf": "",
"hk_delivery_time": "5-7\u5de5\u4f5c\u65e5",
"cn_delivery_time": "6-12\u5de5\u4f5c\u65e5",
"ladder_price": [
{
"purchases": 1,
"price_cn": 0.2886,
"price_us": 0.2886
},
{
"purchases": 25,
"price_cn": 0.2662,
"price_us": 0.2662
}
],
"attrs":{
"0":{"attr_name":"标准包装","attr_value":"1"},
"2":{"attr_name":"包装","attr_value":"剪切带(CT)11"}
}
}
```
### 批次 redis Self_goods_batch 相关数据
```json
"[{"traceno":"00010486","pcs":"2950.0000","dc":"","goods_id":"10365","add_time":1578363429}]"
2) "[{"traceno":"00010489","pcs":"4500.0000","dc":"","goods_id":"10333","add_time":1578363429}]"
3) "[{"traceno":"00013255","pcs":"1350.0000","dc":0,"goods_id":"10643","add_time":1606109821,"dc_time":0}]"
4) "[{"traceno":"00011909","pcs":"2470.0000","dc":"","goods_id":"10288","add_time":1578363429},{"traceno":"00011910","pcs":"2500.0000","dc":"","goods_id":"10288","add_time":1578363429}]"
5) "[{"traceno":"00071835","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1529244995},{"traceno":"00071836","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1529244995},{"traceno":"00071837","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1529244995},{"traceno":"00071838","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1529244995},{"traceno":"00071839","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1529244995}]"
6) "[{"traceno":"00008706","pcs":"4000.0000","dc":"","goods_id":"11050","add_time":1578363429},{"traceno":"00008978","pcs":"4000.0000","dc":"","goods_id":"11050","add_time":1578363429}]"
7) "[{"traceno":"00071835","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1578240000},{"traceno":"00071836","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1578240000},{"traceno":"00071837","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1578240000},{"traceno":"00071838","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1578240000},{"traceno":"00071839","pcs":"100.0000","dc":"2002","goods_id":"95877","add_time":1578559395,"dc_time":1578240000}]"
8) "[{"traceno":"00008700","pcs":"9820.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00009108","pcs":"10000.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00009109","pcs":"10000.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00071756","pcs":"5.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00071758","pcs":"25.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00071764","pcs":"10.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00071766","pcs":"1.0000","dc":0,"goods_id":"11030","add_time":1579249375,"dc_time":0},{"traceno":"00071874","pcs":"400.0000","dc":"1809","goods_id":"11030","add_time":1579249375,"dc_time":1518969600},{"traceno":"00071876","pcs":"3600.0000","dc":"1810","goods_id":"11030","add_time":1579249375,"dc_time":1519574400},{"traceno":"00071871","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579249375,"dc_time":1514736000},{"traceno":"00071872","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579249375,"dc_time":1514736000},{"traceno":"00071873","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579249375,"dc_time":1514736000},{"traceno":"00071875","pcs":"4000.0000","dc":"1830","goods_id":"11030","add_time":1579249375,"dc_time":1531670400}]"
9) "[{"traceno":"00010485","pcs":"3000.0000","dc":"","goods_id":"10345","add_time":1578363429}]"
10) "[{"traceno":"00008700","pcs":"9820.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00009108","pcs":"10000.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00009109","pcs":"10000.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00071756","pcs":"5.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00071758","pcs":"25.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00071764","pcs":"10.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00071766","pcs":"1.0000","dc":0,"goods_id":"11030","add_time":1579164431,"dc_time":0},{"traceno":"00071874","pcs":"400.0000","dc":"1809","goods_id":"11030","add_time":1579164431,"dc_time":1518969600},{"traceno":"00071876","pcs":"3600.0000","dc":"1810","goods_id":"11030","add_time":1579164431,"dc_time":1519574400},{"traceno":"00071871","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579164431,"dc_time":1514736000},{"traceno":"00071872","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579164431,"dc_time":1514736000},{"traceno":"00071873","pcs":"4000.0000","dc":"1802","goods_id":"11030","add_time":1579164431,"dc_time":1514736000},{"traceno":"00071875","pcs":"4000.0000","dc":"1830","goods_id":"11030","add_time":1579164431,"dc_time":1531670400}]"
11) "[{"traceno":"00008673","pcs":"10000.0000","dc":"","goods_id":"11033","add_time":1578363429},{"traceno":"00009122","pcs":"10000.0000","dc":"","goods_id":"11033","add_time":1578363429},{"traceno":"00024542","pcs":"10000.0000","dc":"","goods_id":"11033","add_time":1578363429},{"traceno":"00024543","pcs":"10000.0000","dc":"","goods_id":"11033","add_time":1578363429}]"
12) "[{"traceno":"00008714","pcs":"4000.0000","dc":"","goods_id":"11051","add_time":1578363429},{"traceno":"00008977","pcs":"4000.0000","dc":"","goods_id":"11051","add_time":1578363429}]
```
......@@ -3,12 +3,13 @@ package main
import (
"fmt"
"github.com/tidwall/gjson"
"math"
"os"
"reflect"
"math"
)
func main() {
path,_:=os.Getwd()
fmt.Print(path)
return
......
......@@ -5,7 +5,7 @@ import (
"gopkg.in/olivere/elastic.v5"
)
const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
const json1 = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
const param1 = `{
"query": {
"bool": {
......
......@@ -22,9 +22,7 @@ type B struct {
func CopyStruct(a interface{}, b interface{}) {
sval := reflect.ValueOf(a).Elem()
dval := reflect.ValueOf(b).Elem()
for i := 0; i < sval.NumField(); i++ {
......@@ -35,17 +33,31 @@ func CopyStruct(a interface{}, b interface{}) {
if(dvalue.Kind()!=sval.Field(i).Kind()){
continue
}
value.IsZero()
if dvalue.IsValid() == false {
continue
}
dvalue.Set(value) //这里默认共同成员的类型一样,否则这个地方可能导致 panic,需要简单修改一下。
}
}
func zero() {
}
func main() {
a := &A{1, 1, "a", "b"}
a := &A{2, 2, "", "b"}
b:=&B{}
b:=&A{}
var c A
if(reflect.ValueOf(c).IsZero()){
fmt.Printf("零值")
}else{
fmt.Printf("不是零值")
}
return
CopyStruct(a,b)
......
......@@ -8,12 +8,15 @@ require (
github.com/elliotchance/orderedmap v1.3.0 // indirect
github.com/gin-contrib/cors v1.3.1 // indirect
github.com/gin-gonic/gin v1.6.3
github.com/go-delve/delve v1.5.0 // indirect
github.com/go-ini/ini v1.57.0
github.com/go-sql-driver/mysql v1.5.0
github.com/go-xorm/xorm v0.7.9
github.com/gogf/gf v1.14.5
github.com/gogo/protobuf v1.3.1 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/gomodule/redigo v2.0.1-0.20180401191855-9352ab68be13+incompatible
github.com/google/go-dap v0.4.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect
......@@ -21,19 +24,25 @@ require (
github.com/guonaihong/gout v0.1.3
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0
github.com/ichunt2019/go-rabbitmq v1.0.1
github.com/ichunt2019/log v0.0.0-20201210074003-5f1f31e70d4e
github.com/ichunt2019/logger v1.0.5
github.com/imroc/req v0.3.0
github.com/jasonlvhit/gocron v0.0.1 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect
github.com/micro/go-micro v1.16.0 // indirect
github.com/micro/go-micro/v2 v2.9.0
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
github.com/peterh/liner v1.2.1 // indirect
github.com/prometheus/client_golang v1.5.1 // indirect
github.com/prometheus/common v0.10.0 // indirect
github.com/prometheus/procfs v0.0.11 // indirect
github.com/russross/blackfriday v1.6.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/semihalev/gin-stats v0.0.0-20180505163755-30fdcbbd3533
github.com/sirupsen/logrus v1.5.0
github.com/sirupsen/logrus v1.7.0
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/cobra v1.1.1 // indirect
github.com/stretchr/testify v1.5.1 // indirect
github.com/syyongx/php2go v0.9.4
github.com/tidwall/gjson v1.6.1
......@@ -41,7 +50,10 @@ require (
github.com/uniplaces/carbon v0.1.6 // indirect
go.etcd.io/bbolt v1.3.4 // indirect
go.mongodb.org/mongo-driver v1.3.5 // indirect
go.starlark.net v0.0.0-20201204201740-42d4f566359b // indirect
go.uber.org/zap v1.14.1 // indirect
golang.org/x/arch v0.0.0-20201207015849-377592649dd6 // indirect
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361 // indirect
google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece // indirect
google.golang.org/grpc v1.29.1 // indirect
......@@ -49,6 +61,7 @@ require (
gopkg.in/ini.v1 v1.51.0 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/olivere/elastic.v5 v5.0.85
gopkg.in/yaml.v2 v2.4.0 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb // indirect
)
......
package saveModel
import (
"go_sku_server/model"
"go_sku_server/pkg/common"
)
/**
@author wangsong
修改联营sku 请求参数
*/
type LyEditRequest struct {
GoodsId string `json:"goods_id" form:"goods_id" binding:"required"`
BatchSn int `json:"batch_sn" form:"batch_sn" `//批次
Mpq int `json:"mpq" form:"mpq" binding:"required"`//标准包装量
Stock int `json:"stock" form:"stock" `//库存
HkDeliveryTime string `json:"hk_delivery_time" form:"hk_delivery_time" `//香港货期
CnDeliveryTime string `json:"cn_delivery_time" form:"cn_delivery_time" `//大陆货期
LadderPrice []model.LadderPrice `json:"ladder_price" form:"ladder_price" `//阶梯价钱
CpTime int `json:"cp_time" form:"cp_time" `//茂则成本添加时间
GoodsImages string `json:"goods_images" form:"goods_images" `//商品图片 所属spu
GoodsSn string `json:"goods_sn" form:"goods_sn" ` //供应商自己的唯一标识码
}
/**
将 LySaveRequest 的值赋值到 LySkuEntity(两个结构字段和类型不一样不会赋值)
*/
func (LR *LyEditRequest)ToLySkuEntity() LySkuEntity{
lySkuEntity:=LySkuEntity{}
common.CopyStruct(LR,&lySkuEntity)
return lySkuEntity
}
/**
将 LyEditRequest 的值赋值到 ToLySaveRequest
*/
func (LR *LyEditRequest)ToLySaveRequest() LySaveRequest{
LySaveRequest:=LySaveRequest{}
common.CopyStruct(LR,&LySaveRequest)
return LySaveRequest
}
package saveModel
import (
"github.com/gogf/gf/util/gconv"
"go_sku_server/model"
"go_sku_server/pkg/common"
)
/**
@author wangsong
联营sku实体-新增联营sku用到
......@@ -8,15 +14,17 @@ package saveModel
type LySkuEntity struct {
GoodsName string `json:"goods_name" form:"goods_name" binding:"required"`
BrandName string `json:"brand_name" form:"brand_name" binding:"required"`
//BrandName string `json:"brand_name" form:"brand_name" binding:"required"`
SupplierId int `json:"supplier_id" form:"supplier_id" binding:"required"`
Moq int `json:"moq" form:"moq" binding:"required"`//起订量
Mpq int `json:"mpq" form:"mpq" binding:"required"`//标准包装量
GoodsId string `json:"goods_id"`
SpuId string `json:"spu_id"`
GoodsType int `json:"goods_type"`//'0:自营 1:联营 2:专卖',
Encoded string `json:"encoded"`//供应商编码
Canal string `json:"canal" form:"canal" `//渠道开发员ID
Encoded int `json:"encoded"`//供应商编码
Canal string `json:"canal" form:"canal" `//供应商编码-渠道标签
BatchSn string `json:"batch_sn" form:"batch_sn" `//批次
Stock int `json:"stock" form:"stock" `//库存
HkDeliveryTime string `json:"hk_delivery_time" form:"hk_delivery_time" `//香港货期
......@@ -25,5 +33,29 @@ type LySkuEntity struct {
SinglePrice float64 `json:"single_price" form:"ladder_price" `//最低价
CpTime int `json:"cp_time" form:"cp_time" `//茂则成本添加时间
GoodsSn string `json:"goods_sn" form:"goods_sn" ` //供应商自己的唯一标识码
GoodsStatus int64 `json:"goods_status"`//sku状态 '商品状态 0:待审核 1:审核通过(上架)2:审核不通过 3:下架 4:删除'
CreateTime int `json:"create_time" xorm:"created"`
SaleTime int `json:"sale_time" xorm:"created"`
UpdateTime int `json:"update_time" xorm:"created"`
}
//将 LySkuEntity 的值赋值到 SkuRedisInfo(两个结构字段和类型不一样不会赋值)
func (LS *LySkuEntity) ToRedisSku() model.SkuRedisInfo{
skuRedisInfo:=model.SkuRedisInfo{}
common.CopyStruct(LS,&skuRedisInfo)
return skuRedisInfo
}
//将 LySkuEntity 的值赋值到 model.SkuMongo(两个结构字段和类型不一样不会赋值)
func (LS *LySkuEntity) ToMongoSku() model.SkuMongo{
skuMongo:=model.SkuMongo{}
common.CopyStruct(LS,&skuMongo)
skuMongo.SpuId=gconv.Int64(LS.SpuId)//spuID在mangoDB是int64位
skuMongo.GoodsId=gconv.Int64(LS.GoodsId)//spuID在mangoDB是int64位
return skuMongo
}
package saveModel
//请求spu_server save 接口数据
/**
@author wangsong
请求spu_server save 接口数据
*/
type LySpuRequest struct {
GoodsName string `json:"goods_name" form:"goods_name" binding:"required"`
......@@ -8,15 +12,15 @@ type LySpuRequest struct {
GoodsImages string `json:"goods_images" form:"goods_images" `//商品图片 所属spu
Encap string `json:"encap" form:"encap" ` //封装 所属spu
Pdf string `json:"pdf" form:"pdf" ` //PDF地址 所属spu
SpuBrief int `json:"spu_brief" form:"spu_brief" `//简短描述 所属spu
Attrs map[string]interface{} `json:"attrs" form:"attrs" ` //商品参数 所属spu
SpuBrief string `json:"spu_brief" form:"spu_brief" `//简短描述 所属spu
Attrs map[string]OneAttrs `json:"attrs" form:"attrs" ` //商品参数 所属spu
}
type LySpuResponse struct {
ErrorCode int `json:"error_code"`
ErrMsg string `json:"err_msg"`
Data interface{} `json:"data"`
Data ResponseData `json:"data"`
}
type ResponseData struct {
......
......@@ -2,7 +2,7 @@ package saveModel
import (
"go_sku_server/model"
"reflect"
"go_sku_server/pkg/common"
)
/**
@author wangsong
......@@ -28,55 +28,35 @@ type LySaveRequest struct {
Encap string `json:"encap" form:"encap" ` //封装 所属spu
Pdf string `json:"pdf" form:"pdf" ` //PDF地址 所属spu
SpuBrief int `json:"spu_brief" form:"spu_brief" `//简短描述 所属spu
Attrs map[string]interface{} `json:"attrs" form:"attrs" ` //商品参数 所属spu
Attrs map[string]OneAttrs `json:"attrs" form:"attrs" ` //商品参数 所属spu
}
//attr字段(老版)
type OneAttrs struct {
AttrName string `json:"attr_name"`
AttrValue string `json:"attr_value"`
}
/**
将 LySaveRequest 的值赋值到 LySkuEntity(两个结构字段和类型不一样不会赋值)
*/
func (LR *LySaveRequest)ToLySkuEntity() LySkuEntity{
lySkuEntity:=LySkuEntity{}
copyStruct(LR,&lySkuEntity)
common.CopyStruct(LR,&lySkuEntity)
return lySkuEntity
}
/**
将 LySaveRequest 的值赋值到 LySpuRequest(字段和类型不一样不会赋值)
*/
func (LR *LySaveRequest)ToLySpuRequest() LySpuRequest{
lySpuRequest:=LySpuRequest{}
copyStruct(LR,&lySpuRequest)
common.CopyStruct(LR,&lySpuRequest)
return lySpuRequest
}
//结构复制,内部方法,可能后续会封装到公共函数
func copyStruct(a interface{}, b interface{}) {
sval := reflect.ValueOf(a).Elem()
dval := reflect.ValueOf(b).Elem()
for i := 0; i < sval.NumField(); i++ {
value := sval.Field(i)
name := sval.Type().Field(i).Name
dvalue := dval.FieldByName(name)
if(dvalue.Kind()!=sval.Field(i).Kind()){
continue
}
if dvalue.IsValid() == false {
continue
}
dvalue.Set(value) //这里默认共同成员的类型一样,否则这个地方可能导致 panic,需要简单修改一下。
}
}
/*func (L * LySaveRequest)GetAttrsJson() map[string]interface{} {
if AttrsMap,ok:=L.Attrs.(map[string]interface{});ok{
......
package saveModel
/**
poolskuSave 返回是这样的格式
{
"errcode": 0,
"errmsg": "ok",
"goods_id": 1160699091498808475
}
*/
type LySaveResponse struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
GoodsId string `json:"goods_id"`
}
func ResponseSucess(GoodsId string) LySaveResponse {
return LySaveResponse{0,"ok",GoodsId}
}
func (L *LySaveResponse)GetErrorMsg() string {
return L.ErrMsg
}
func (L *LySaveResponse)GetErrorCode() int {
return L.ErrCode
}
func ResponseError(opts ...interface{}) LySaveResponse {
var ErrMsg string;
Code:=1001;
for num,opt:=range opts{
if(num>1){
break;
}
switch num {
case 0:
ErrMsg=opt.(string)
case 1:
Code=opt.(int)
break
}
}
return LySaveResponse{ErrCode: Code, ErrMsg: ErrMsg}
}
package model
//对应mongo SKU
type SkuMongo struct {
SpuId int64 `bson:"spu_id"`
GoodsId int64 `json:"goods_id" bson:"goods_id"`
SupplierId int `json:"supplier_id" bson:"supplier_id"`
Moq int `json:"moq" bson:"moq"`
Encoded int `json:"encoded" bson:"encoded"`
Canal string `json:"canal" bson:"canal"`
OldGoodsId int `json:"old_goods_id" bson:"old_goods_id"`//创建sku接口 不包含OldGoodsId
}
\ No newline at end of file
package model
/**
@author wangsong
redis hash sku 结构,主要是用作新增插入用
poolSkuSave 插入redis就是这些字段
*/
type SkuRedisInfo struct {
SpuId string `json:"spu_id"`
Encoded int `json:"encoded"`//供应商编码
Moq int `json:"moq" form:"moq" binding:"required"`//起订量
Mpq int `json:"mpq" form:"mpq" binding:"required"`//标准包装量
OldGoodsId int64 `json:"old_goods_id"`//老商品ID
GoodsType int `json:"goods_type"`//'0:自营 1:联营 2:专卖',
GoodsStatus int64 `json:"goods_status"`//sku状态 '商品状态 0:待审核 1:审核通过(上架)2:审核不通过 3:下架 4:删除'
BatchSn string `json:"batch_sn" form:"batch_sn" `//批次
Stock int `json:"stock" form:"stock" `//库存
HkDeliveryTime string `json:"hk_delivery_time" form:"hk_delivery_time" `//香港货期
CnDeliveryTime string `json:"cn_delivery_time" form:"cn_delivery_time" `//大陆货期
LadderPrice interface{} `json:"ladder_price" form:"ladder_price" `//阶梯价钱 用 string json化会出现斜划线,所以用interface{}
UpdateTime int `json:"update_time" xorm:"created"`
GoodsImages string `json:"goods_images" form:"goods_images" `//商品图片 所属spu
Canal string `json:"canal" form:"canal" `//渠道开发员ID
SupplierId int `json:"supplier_id" form:"supplier_id" binding:"required"`
CpTime int `json:"cp_time" form:"cp_time" `//茂则成本添加时间
}
\ No newline at end of file
package model
//基石供应商表实体(暂时只放用到的字段)
//基石供应商表DB实体(暂时只放用到的字段)
type SupplierEntity struct {
SupplierId int `json:"supplier_id"`
TypeId int `json:"type_id" `
......@@ -8,8 +8,8 @@ type SupplierEntity struct {
SupplierName string `json:"supplier_name" `
}
//联营供应商表实体(暂时只放用到的字段)
//联营供应商表DB实体(暂时只放用到的字段)
type PoolSupplierEntity struct {
SupplierCode string `json:"supplier_code"`//供应商编码
ChannelUid int `json:"channel_uid" `//渠道开发员
ChannelUid int `json:"channel_uid" `//渠道开发员ID
}
......@@ -10,6 +10,7 @@ import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gogf/gf/util/gconv"
"github.com/syyongx/php2go"
"github.com/tidwall/gjson"
"go_sku_server/pkg/config"
......@@ -88,6 +89,115 @@ func GetRequestParam(ctx *gin.Context) string{
/**
结构复制,从struct1 复制到 struct2,字段类型不一样,那么就不复制那个字段
@param Starus 说明
1,如果struct1 字段值为零值就不覆盖struct2对应的字段值(默认),
2,struct1字段 覆盖struct2 字段的值
3,struct2 字段为零值,才让struct1 的字段赋值
*/
func CopyStruct(struct1 interface{}, struct2 interface{},Status ...int) {
statusType:=1;//statusType 默认参数
for num,opt:=range Status{
if(num>0){//只接受一个参数
break;
}
switch num {
case 0:
if(opt==2){
statusType=2
}
break
}
}
sval := reflect.ValueOf(struct1).Elem()
dval := reflect.ValueOf(struct2).Elem()
for i := 0; i < sval.NumField(); i++ {
value := sval.Field(i)
if(statusType==1){ //如果struct1 字段值为零值就不覆盖struct2对应的字段值
if(value.IsZero()){
continue
}
}
name := sval.Type().Field(i).Name
dvalue := dval.FieldByName(name)
if(statusType==3){//struct2字段为零值,才让struct1 的字段赋值,不是零值就跳过此字段的赋值
if(dvalue.IsZero()==false){
continue
}
}
if(dvalue.Kind()!=sval.Field(i).Kind()){//类型不一样不复制
continue
}
if dvalue.IsValid() == false { //dvalue.IsValid() 与 dvalue.IsZero() 不一样,如果返回fasle是无效的值
continue
}
dvalue.Set(value) //这里默认共同成员的类型一样,否则这个地方可能导致 panic,需要简单修改一下。
}
}
/**
@author wangsong
合并map,都有值以map1为主,字段类型以map1为主
*/
func MergeMap(map1 map[string]interface{},map2 map[string]interface{}) map[string]interface{} {
var newMap map[string]interface{}
newMap=map1//以map1为主,就先将map1给到newMap
//先算mp1
for key,_:= range map1{
if(!reflect.ValueOf(map1[key]).IsZero()){//如果不为空,就以取map1的值
s:=reflect.ValueOf(map1[key])
if(s.Kind()==reflect.String){ //string
newMap[key]=gconv.String(map1[key])
}else{
newMap[key]=gconv.Int(map1[key]) //int
}
delete(map2, key)//删一个重复的map2的key
}else{//没有数据,取mp2的值,类型要是map1字段的类型
if _, ok := map2[key]; ok { //map1的key在map2是否存在,不存在就不处理
if(!reflect.ValueOf(map2[key]).IsZero()){ //map2不能为0值才处理
m1 :=reflect.ValueOf(map1[key])
if(m1.Kind()==reflect.String){ //string
newMap[key]=gconv.String(map2[key])
}else{
newMap[key]=gconv.Int(map2[key]) //int
}
}
delete(map2, key)//删一个重复的map2的key
}
}
}
//处理map2,重复的被删了,剩下的直接添加
for key,value:= range map2{
s:=reflect.ValueOf(value)
if(s.Kind()==reflect.String){ //string
newMap[key]=gconv.String(value)
}else{
newMap[key]=gconv.Int(value) //int
}
}
return newMap
}
/*
输出header
*/
......
package common
import (
"fmt"
"github.com/gin-gonic/gin"
"go_sku_server/pkg/logger"
"reflect"
)
/**
@author wangsong
输出工具,输出json 和输出日志(链式调用)
*/
//接口
type NewOutPut interface {
GetErrorCode() int
GetErrorMsg() string
}
//输出类
type NewResponse struct {
LogDrive *logDrive
OutPutData NewOutPut
ctx *gin.Context //gin http
}
//日志类
type logDrive struct {
openLog bool //开启记录log
LogfilePre string //文件前缀
isRecordReuquest bool //记录请求参数
logContent string //日志内容,会与ErrorMesg一起记录
}
//内部默认输出结构
type defaultOutPutDate struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
Data interface{} `json:"data"`
}
//入口
func NResponse( opt...interface{}) *NewResponse {
newResponse:=&NewResponse{}
newResponse.createOutPutData(opt)
log:=&logDrive{}
newResponse.LogDrive=log
newResponse.LogDrive.LogfilePre="defaltLog"
return newResponse
}
//设置输出对象
func (NR *NewResponse) SetOutPutData(newOutPut NewOutPut) *NewResponse{
NR.OutPutData=newOutPut
return NR
}
//设置日志内容
func (NR *NewResponse) SetLogContent(logStr string) *NewResponse{
NR.LogDrive.logContent=logStr
NR.LogDrive.openLog=true
return NR
}
//设置日志文件前缀
func (NR *NewResponse) SetLogFilePre(filePre string) *NewResponse{
NR.LogDrive.openLog=true
NR.LogDrive.LogfilePre=filePre
return NR
}
/**
开启日志记录参数
ctx 可以不传,传必须是ctx gin.Context
*/
func (NR *NewResponse) OpenRecordReuquest(ctx...interface{}) *NewResponse{
NR.setjudgeCtx(ctx)
NR.LogDrive.openLog=true
NR.LogDrive.isRecordReuquest=true
return NR
}
//设置 http ctx
func (NR *NewResponse) SetCtx(ctx *gin.Context) *NewResponse{
NR.ctx=ctx
return NR
}
//开启日志
func (NR *NewResponse) OpenLog() *NewResponse{
NR.LogDrive.openLog=true
return NR
}
//输出到前端
/**
ctx gin.Context 只处理一个
*/
func (NR *NewResponse) OutPut(ctx ...interface{}) {
NR.setjudgeCtx(ctx)
NR.logHandle()//日志处理
if(reflect.ValueOf(NR.OutPutData).IsZero()==true){//没有输出对象,就用默认的
NR.OutPutData=&defaultOutPutDate{0,"ok",nil}
}
NR.ctx.JSONP(200,NR.OutPutData)
}
//仅输出日志(目前是存文件)
func (NR *NewResponse) OutPutLog() {
NR.OpenLog()
NR.logHandle()//日志处理
}
//内部,日志处理(后续要改善 输出日志渠道 文件、oss、数据库,或者第三方)
func (NR *NewResponse) logHandle() {
if(NR.LogDrive.openLog){
errMsg:=""
formDataStr1:=""
if(NR.OutPutData!=nil){
if(NR.OutPutData.GetErrorCode()!=0){
errMsg="errMsg:"
errMsg+=NR.OutPutData.GetErrorMsg()
}
}
if(NR.LogDrive.isRecordReuquest){
if(reflect.ValueOf(NR.ctx).IsZero()!=true){
formDataStr1="请求过来的参数:"
formDataStr1+=GetRequestParam(NR.ctx)
}
}
logstr:=errMsg+formDataStr1+NR.LogDrive.logContent
logger.Log(logstr,NR.LogDrive.LogfilePre,1)
}
}
func (L *defaultOutPutDate)GetErrorMsg() string {
return L.ErrMsg
}
func (L *defaultOutPutDate)GetErrorCode() int {
return L.ErrCode
}
/**
创建 输出对象
如果 第一个参数是结构,输出对象就是此结构(就是自定义输出对象)
否则输出对象就是 defaultOutPutDate;第一个参数 是msg 第二个是code ,第三个是data
*/
func (NR *NewResponse )createOutPutData(opt []interface{}) {
if(len(opt)>0){
errMsg:="ok"
errCode:=0
var data interface{}
//第一个参数是结构,输出对象就是此结构
valueR:=reflect.ValueOf(opt[0])
if(valueR.Kind()==reflect.Ptr ){
a:=valueR.Elem().Kind()
fmt.Print(a)
if(valueR.Elem().Kind()==reflect.Struct){
if newOutPut,ok:=opt[0].(NewOutPut);ok{
NR.OutPutData=newOutPut
}else{
panic("If it is a structure, it must inherit the interface newoutput")
}
return
}
}
//否则就是默认的结构 defaultOutPutDate 第一个参数 是msg 第二个是code ,第三个是data
errMsg=opt[0].(string)
errCode=100010
if(len(opt)>=2){
errCode=opt[1].(int)
}
if(len(opt)>=3){
data=opt[2]
}
NR.OutPutData=&defaultOutPutDate{errCode,errMsg,data}
}
}
/**
NR.ctx 没有赋值就取opt[0]
如果opt有参数,必须是*gin.Context,否则pannic
*/
func (NR *NewResponse ) setjudgeCtx(opt []interface{}) {
if(len(opt)>0){
if(reflect.ValueOf(NR.ctx).IsZero()){
if ctx,ok:=opt[0].(*gin.Context);ok{
NR.SetCtx(ctx)
}
}else{
panic("NewResponse.ctx No value ,Should be*gin.Context")
}
}
}
\ No newline at end of file
package common
import (
"fmt"
"github.com/syyongx/php2go"
"time"
)
/**
构造SPU和SKU的ID
*/
func StructureNumber(SpuType string) (string) {
var Prefix int; //前缀数字1代表 sku,2代表spu
var db int; //数据库0-9
var table int; //表0-9
random6:=php2go.Rand(100000,999999)//随机6位数
time:=time.Now().Unix();//时间戳
if(SpuType=="sku"){
Prefix=1;
db=Rand(0,9)
table=Rand(0,9)
}else{
Prefix=2;
db=0;
table=(Rand(0,9));
}
spuId:=fmt.Sprintf("%d%d%d%d%d",Prefix,time,random6,db,table)
//retugconv.Int(spuIdS)
return spuId
}
/**
解析SPU和SKU
*/
func ResolveSpu(SpuId string) (db string,table string) {
var Prefix string; //前缀数字1代表 sku,2代表spu
var dbCode string; //数据库0-9
var tableCode string; //表0-9
Prefix=SpuId[0:1]
dbCode=SpuId[len(SpuId)-2:len(SpuId)-1]
tableCode=SpuId[len(SpuId)-1:len(SpuId)]
if(Prefix=="1"){
dbCode="sku_"+dbCode
tableCode="lie_sku_"+tableCode
}else if(Prefix=="2"){
dbCode="spu"
tableCode="lie_spu_"+tableCode
}
return dbCode,tableCode
}
\ No newline at end of file
......@@ -41,5 +41,76 @@ func BuildDatabaseList() (DatabaseList map[string]BaseDatabase) {
Database: Get("liexin_data.database").String(),
Prefix: Get("liexin_data.table_prefix").String(),
},
"sku_0": {
UserName: Get("sku_0.user_name").String(),
Password: Get("sku_0.password").String(),
Host: Get("sku_0.host").String(),
Database: Get("sku_0.database").String(),
Prefix: Get("sku_0.table_prefix").String(),
},
"sku_1": {
UserName: Get("sku_1.user_name").String(),
Password: Get("sku_1.password").String(),
Host: Get("sku_1.host").String(),
Database: Get("sku_1.database").String(),
Prefix: Get("sku_1.table_prefix").String(),
},
"sku_2": {
UserName: Get("sku_2.user_name").String(),
Password: Get("sku_2.password").String(),
Host: Get("sku_2.host").String(),
Database: Get("sku_2.database").String(),
Prefix: Get("sku_2.table_prefix").String(),
},
"sku_3": {
UserName: Get("sku_3.user_name").String(),
Password: Get("sku_3.password").String(),
Host: Get("sku_3.host").String(),
Database: Get("sku_3.database").String(),
Prefix: Get("sku_3.table_prefix").String(),
},
"sku_4": {
UserName: Get("sku_4.user_name").String(),
Password: Get("sku_4.password").String(),
Host: Get("sku_4.host").String(),
Database: Get("sku_4.database").String(),
Prefix: Get("sku_4.table_prefix").String(),
},
"sku_5": {
UserName: Get("sku_5.user_name").String(),
Password: Get("sku_5.password").String(),
Host: Get("sku_5.host").String(),
Database: Get("sku_5.database").String(),
Prefix: Get("sku_5.table_prefix").String(),
},
"sku_6": {
UserName: Get("sku_6.user_name").String(),
Password: Get("sku_6.password").String(),
Host: Get("sku_6.host").String(),
Database: Get("sku_6.database").String(),
Prefix: Get("sku_6.table_prefix").String(),
},
"sku_7": {
UserName: Get("sku_7.user_name").String(),
Password: Get("sku_7.password").String(),
Host: Get("sku_7.host").String(),
Database: Get("sku_7.database").String(),
Prefix: Get("sku_7.table_prefix").String(),
},
"sku_8": {
UserName: Get("sku_8.user_name").String(),
Password: Get("sku_8.password").String(),
Host: Get("sku_8.host").String(),
Database: Get("sku_8.database").String(),
Prefix: Get("sku_8.table_prefix").String(),
},
"sku_9": {
UserName: Get("sku_9.user_name").String(),
Password: Get("sku_9.password").String(),
Host: Get("sku_9.host").String(),
Database: Get("sku_9.database").String(),
Prefix: Get("sku_9.table_prefix").String(),
},
}
}
......@@ -21,7 +21,6 @@ func NewApiError(opts ...interface{}) * ApiError{
for num,opt:=range opts{
if(num>1){
break;
}
switch num {
......
package logger
import (
"github.com/ichunt2019/logger"
"fmt"
"github.com/ichunt2019/log"
"go_sku_server/pkg/config"
"strings"
"sync"
)
const (
LogLevelDebug = iota
LogLevelTrace
LogLevelInfo
LogLevelWarn
LogLevelError
LogLevelFatal
)
var (
logD map[string]logger.LogInterface
)
var once sync.Once
func Loginit() {
once.Do(func() {
fmt.Print("日志初始化开始")
configs:=config.GetSectionValues("log_config")
logD=make(map[string]logger.LogInterface)
for _,configOne:=range configs{
sliceConfig:=strings.Split(configOne, ",")
log:=getLog(sliceConfig[0],sliceConfig[1],"0")
logD[sliceConfig[0]]=log
}
})
}
/**
github.com/ichunt2019/log 参数说明
log_chan_size 最高5协程处理日志
log_path 日志路径 默认为logs
open_sync 开启同步(本项目不需要同步模式,允许使用 wait方法阻塞直至日志完全存入文件,一般用于一次性处理脚本)
*/
/**
初始化 log(github.com/ichunt2019/log)
*/
/**
@param path 路径 比如sku_save 即文件夹是 sku 文件名类似 是save_2020-12-10.log
@param msg 错误文本
@Level 默认是 logger.LogLevelInfo
示例
*/
func SyncInsert(path string,msg string,Levels ...int) {
log:=getLog(path,"10","1")
level:=LogLevelInfo
if(len(Levels)>0){
level=Levels[0]
}
switch level {
case LogLevelDebug:
log.Debug(msg)
case LogLevelTrace:
log.Trace(msg)
case LogLevelInfo:
log.Info(msg)
case LogLevelWarn:
log.Warn(msg)
case LogLevelFatal:
log.Fatal(msg)
case LogLevelError:
log.Error(msg)
default:
log.Info(msg)
}
log.SyncWait()
}
//入口
func Select(logFiled string) logger.LogInterface {
log, ok := logD[logFiled]
if(!ok){
panic("log配置:"+logFiled+"不存在")
}
if log,ok:=log.(logger.LogInterface);ok{
return log
}
panic("type not logger.LogInterface")
}
//内部方法,获取log
func getLog(path string,chan_size string,openSync string) logger.LogInterface {
logConfig := make(map[string]string)
logConfig["log_chan_size"]="10"
slicePath:=strings.Split(path, "_")
if(slicePath[0]=="" || slicePath[1]==""){
panic("配置文件出错:文件/路径配置出错;提示:第一个参数格式应为A_B")
}
logConfig["log_path"] = "logs/"+slicePath[0]
logConfig["log_name"] = slicePath[1]
if(openSync=="1"){
logConfig["open_sync"] = "1"
}
if(chan_size!=""){
logConfig["log_chan_size"]=chan_size
}
log,err:= logger.InitLogger("file", logConfig)
if err != nil {
panic("初始化log包出错:")
}
log.Init()
return log
}
func SetUp() (err error) {
logConfig := make(map[string]string)
logConfig["log_path"] = "logs"
logConfig["log_chan_size"] = "5"
err = logger.InitLogger("file", logConfig)
//err = logger.InitLogger("file", logConfig)
if err != nil {
return err
}
logger.Init()
return
}
......@@ -24,8 +24,6 @@ func checkFileIsExist(filename string) bool {
}
return exist
}
/*
@param writeString 写入文件字符串
@param file_pre 附加文件前缀
......
......@@ -25,6 +25,7 @@ func InitRouter() *gin.Engine {
//自营SaveSku
r.POST("SaveSku",controller.Error_Middleware(),controller.SaveSku)
r.POST("SkuEdit",controller.Error_Middleware(),controller.SkuEdit)
return r
}
......@@ -4,14 +4,18 @@ import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gogf/gf/util/gconv"
"github.com/syyongx/php2go"
"go_sku_server/model"
"go_sku_server/model/saveModel"
"go_sku_server/pkg/common"
"go_sku_server/pkg/config"
"go_sku_server/pkg/e"
"github.com/guonaihong/gout"
"go_sku_server/pkg/mysql"
"reflect"
"sort"
"time"
)
type LySaveService struct {
......@@ -26,7 +30,6 @@ sku基本数据增加和修改
SupplierId int `json:"supplier_id" binding:"required"`
Moq int `json:"moq" binding:"required"`//起订量
Mpq int `json:"mpq" binding:"required"`//标准包装量
Canal int `json:"canal" `//渠道标签
BatchSn int `json:"batch_sn" `//批次
Stock int `json:"stock" `//库存
......@@ -41,39 +44,58 @@ sku基本数据增加和修改
SpuBrief int `json:"spu_brief" `
Attrs int `json:"attrs" `
*/
func (S *LySaveService)SaveSku(lySaveRequest saveModel.LySaveRequest,ctx *gin.Context) error {
var skuCache SkuCacheService
func (S *LySaveService)SaveSku(lySaveRequest saveModel.LySaveRequest,ctx *gin.Context) (error,string) {
lySkuEntity:=lySaveRequest.ToLySkuEntity()//sku实体
//供应商处理(供应商相关验证,验证通过 将saveSku所需参数 赋值给 &lySkuEntity)
//供应商处理(处理后,将[新增/修改sku]所需供应商相关字段 赋值给 &lySkuEntity)
err:=S.supplierHandle(lySaveRequest.SupplierId,lySkuEntity.Canal,&lySkuEntity)
if(err!=nil){
return err
return e.NewApiError("供应商处理失败"+err.Error()),""
}
//阶梯价格处理(验证阶梯价格,验证通过将 saveSku 所需参数赋值给 &lySkuEntity )
//阶梯价格处理
err=S.ladderPriceHandle(lySaveRequest.LadderPrice,&lySkuEntity)
if(err!=nil){
return err
return e.NewApiError("阶梯价格处理失败"+err.Error()),""
}
//上下架状态处理
S.statusHandle(&lySkuEntity)
//spu处理(请求spu_server saveSpu接口,将spuId赋值给 &lySkuEntity)
lySpuRequest:=lySaveRequest.ToLySpuRequest()
err=S.spuHandle(lySpuRequest,&lySkuEntity)
if(err!=nil){
return err
return err,""
}
return nil
//mongoDb 获取sku 唯一信息
err,mongoSkuInfo:=skuCache.MongoGetOnlySkuInfo(lySkuEntity.SpuId,lySkuEntity.SupplierId,lySkuEntity.Moq,lySkuEntity.Encoded,lySkuEntity.Canal)
if(err!=nil){
return e.NewApiError("mongo 获取sku唯一信息失败"+err.Error()),""
}
if(mongoSkuInfo.GoodsId!=0){//更新
}
lySkuEntity.GoodsId=gconv.String(mongoSkuInfo.GoodsId)
err:=S.update(lySkuEntity,lySaveRequest)
if(err!=nil){
return e.NewApiError("skuSave 修改sku失败"+err.Error()),""
}
return nil,lySkuEntity.GoodsId
}else{//插入sku
err,skuId:=S.insert(lySkuEntity,lySaveRequest)
if(err!=nil){
return e.NewApiError("skuSave insert sku失败"+err.Error()),""
}
return nil, skuId
}
}
/**
新增sku 供应商处理流程(内部方法)
供应商处理流程(内部方法)
1.判断供应商是否存在,是否被禁用
2.供应商为专卖,参数 cannal是必传的
3.得到 新增sku所需的 TypeId 和 SupplierCode
2.供应商为专卖,参数 cannal(供应商编码)是必传的
3.得到 新增sku所需的 TypeId 和 Encoded(渠道员内部编码)
*/
func (S *LySaveService) supplierHandle(SupplierId int,Canal string,lySkuEntity *saveModel.LySkuEntity) (error) {
......@@ -106,36 +128,40 @@ func (S *LySaveService) supplierHandle(SupplierId int,Canal string,lySkuEntity *
errmsg:=fmt.Sprintf("没有获取到渠道%s的内部编码",Canal)
return e.NewApiError(errmsg)
}
lySkuEntity.Encoded=poolSupplierInfo.SupplierCode//渠道编码赋值给sku
lySkuEntity.Encoded=poolSupplierInfo.ChannelUid//渠道编码赋值给sku
}
lySkuEntity.GoodsType=supplierInfo.TypeId
return nil
}
/**
阶梯价格处理
1.对阶梯价格排序
2.获取 ladderPrice 最便宜的价格
2.获取 ladderPrice
3.获取最便宜的价格
*/
func (S *LySaveService) ladderPriceHandle(ladderPrice []model.LadderPrice,lySkuEntity *saveModel.LySkuEntity) error {
num:=len(ladderPrice)
if(len(ladderPrice)>0){
sort.Sort(LadderPriceSorter(ladderPrice))
lySkuEntity.SinglePrice=0
if(ladderPrice[0].PriceUs>=0){
if(len(ladderPrice)>0){//有传阶梯价
//获取最便宜的价格
sort.Sort(LadderPriceSorter(ladderPrice))//按照购买数量,小到大排序,数量越大优惠越多,所以[num-1]是最便宜的
if(ladderPrice[num-1].PriceUs>=0){//如果有最低美元价,就直接读最低美元价
lySkuEntity.SinglePrice=ladderPrice[num-1].PriceUs//获取最便宜的价钱
}else{
php2go.Round(ladderPrice[num-1].PriceCn/6.8)
}
}else{//没有美元价,就将最低人民币折算成美元
lySkuEntity.SinglePrice=php2go.Round(ladderPrice[num-1].PriceCn/6.8)
}
//将阶梯json字符串给到sku实体里,sku只需要字符串阶梯 存数据库
priceBytes,err:=json.Marshal(ladderPrice)
if(err!=nil){
return e.NewApiError("阶梯价格json化报错"+err.Error())
}else{
lySkuEntity.LadderPrice=string(priceBytes)
} //状态处理
}
return nil
}
......@@ -144,17 +170,16 @@ func (S *LySaveService) ladderPriceHandle(ladderPrice []model.LadderPrice,lySkuE
/**
spu处理(内部方法)
1.调用spu_server saveSpu接口,获取到spuId
返回参数
| 参数 | 示例值 | 参数描述 |
| :-------- | :----- | :---- |
| error_code | 10001 | 错误码 0代表成功响应 |
| err_msg | | 错误提示 |
| errorcode | 10001 | 错误码 0代表成功响应 |
| errmsg | | 错误提示 |
| data | | 返回的data |
*/
func (S *LySaveService) spuHandle(lySpuRequest saveModel.LySpuRequest,lySkuEntity *saveModel.LySkuEntity) (error) {
lySpuResponse:=saveModel.LySpuResponse{}
j,_:=json.Marshal(lySpuRequest)
m:=make(map[string]interface{})
......@@ -168,16 +193,238 @@ func (S *LySaveService) spuHandle(lySpuRequest saveModel.LySpuRequest,lySkuEntit
return e.NewApiError("调用spu server saveSpu接口报错"+err.Error())
}
if(lySpuResponse.ErrorCode==0){
//lySkuEntity.SpuId=lySpuResponse.Data
lySkuEntity.SpuId=lySpuResponse.Data.SpuId
}else{
return e.NewApiError("spu Throw out"+lySpuResponse.ErrMsg)
}
return nil
}
/**
上下架状态处理
处理所需字段
moq 起订量
stock 库存
ladder_price 阶梯价
处理流程
满足 字段 moq stock ladder_price都有值 ,并且 moq > stock ; 那么 sku状态 就是 审核通过(status=1)
否则 就是下架状态(status=3)
*/
func (S *LySaveService) statusHandle(lySkuEntity *saveModel.LySkuEntity) {
lySkuEntity.GoodsStatus=1
if(lySkuEntity.LadderPrice==""){
lySkuEntity.GoodsStatus=3//下架
}
if(lySkuEntity.Moq==0 || lySkuEntity.Stock==0 || lySkuEntity.Moq>lySkuEntity.Stock){
lySkuEntity.GoodsStatus=3//下架
}
}
//更新
func (S *LySaveService) update(lySkuEntity saveModel.LySkuEntity,lySaveRequest saveModel.LySaveRequest)error{
db,table:=common.ResolveSpu(lySkuEntity.GoodsId)//解析skuID,返回对应的表和库,应该在生成skuID的时候返回表和库
//修改数据库
affected, err := mysql.Conn(db).Table(table).Where("goods_id=?",lySkuEntity.GoodsId).Update(lySkuEntity)
if (err != nil) {
return e.NewApiError("修改sku mysql数据失败 msg:"+err.Error())
}
if(affected<=0){//没有什么可以修改的,直接完成就好了
fmt.Println("没什么可以修改的")
return nil
}else{
err=S.skuCacheSave(false,lySkuEntity.GoodsId,lySkuEntity,lySaveRequest)
if (err != nil) {
return e.NewApiError("缓存处理失败"+err.Error())
}
}
return nil
}
//插入
func (S *LySaveService) insert(lySkuEntity saveModel.LySkuEntity,lySaveRequest saveModel.LySaveRequest) (error,string) {
skuId:=common.StructureNumber("sku")//生成skuID
lySkuEntity.GoodsId=skuId
db,table:=common.ResolveSpu(lySkuEntity.GoodsId)//解析skuID,返回对应的表和库,应该在生成skuID的时候返回表和库
//插入到数据库
_, err := mysql.Conn(db).Table(table).Insert(lySkuEntity);
if (err != nil) {
return e.NewApiError("sku插入数据库失败"+err.Error()),""
}
err=S.skuCacheSave(true,skuId,lySkuEntity,lySaveRequest)
if(err!=nil){
return e.NewApiError("缓存处理失败"+err.Error()),""
}
func (S *LySaveService)SkuEdit() {
return nil,skuId
}
/**
更新完sku mysql数据库后,需要对sku相关的 mongo 和redis进行处理
1.更新 redis skuinfo (1.新增直接插入,2.修改需要将老的redis sku数据合并新的)
2.插入mongoDB sku唯一(修改不需要动)
3.推送(就是插入redis list update_list_sku)
*/
func (S *LySaveService) skuCacheSave(isAdd bool,skuId string,lySkuEntity saveModel.LySkuEntity,lySaveRequest saveModel.LySaveRequest)error{
//插入redis,redis修改和新增代码量有点大,单独封装一个函数
err:=S.saveRedisSkuInfo(isAdd,skuId,lySkuEntity,lySaveRequest)
if(err!=nil){
return e.NewApiError("插入redis失败"+err.Error())
}
if(isAdd){
//插入到mongo
skuMongo:=lySkuEntity.ToMongoSku()
err=skuCache.MongoInsertOnlySkuInfo(skuMongo)
if(err!=nil){
return e.NewApiError("插入redis失败"+err.Error())
}
}
//实时推送(插入到 redis list update_list_sku )
err=skuCache.RedisPushEsList(skuId)
if(err!=nil){
return e.NewApiError("实时推送失败"+err.Error())
}
return nil
}
/**
修改redis hash key为 sku的数据(其实就是插入)
为什么要合并?:有其他地方会存这个redis,会出现 len不是固定的,里面的字段类型也会不一样,要分开处理
1.新增
新增,比较简单,就直接组装SkuRedis结构就行
2.修改
读取之前(老的)的redis数据,跟新的redisSku合并
合并规则:需要修改的,覆盖之前的,不需要修改的保持原样
*/
func (S *LySaveService) saveRedisSkuInfo(isAdd bool,skuId string,lySkuEntity saveModel.LySkuEntity,lySaveRequest saveModel.LySaveRequest) error {
redisSkuInfo:=lySkuEntity.ToRedisSku()//组装需要更新的redisSku数据
redisSkuInfo.GoodsImages=lySaveRequest.GoodsImages
redisSkuInfo.Canal=lySaveRequest.Canal
redisSkuInfo.UpdateTime=int(time.Now().Unix())
redisSkuInfo.LadderPrice=lySaveRequest.LadderPrice//LadderPrice 如果已经是字符串,json处理会有斜划线,所以再赋值一次
if(isAdd){
oldByte,err:=json.Marshal(redisSkuInfo)
if(err!=nil){
return nil
}
return skuCache.RedisInsertSkuInfo(skuId,string(oldByte))
}else{
//将老的redis的数据转成map
var oldSkuInfoMap map[string]interface{}
oldSkuInfoStr,err:=skuCache.RedisGetSkuInfo(skuId)//获取老的sku数据
json.Unmarshal([]byte(oldSkuInfoStr),&oldSkuInfoMap)
if(err!=nil){
return nil
}
//is_expire 给清理掉
if _, ok := oldSkuInfoMap["is_expire"];ok{
delete(oldSkuInfoMap,"is_expire")
}
//合并,得到新的map
err,newMap:=S.structMerageMap(redisSkuInfo,oldSkuInfoMap)
if(err!=nil){
return e.NewApiError("结构和map合并失败"+err.Error())
}
//转化成json字符串
newMapbytes,err:=json.Marshal(newMap)
if(err!=nil){
return err
}
//插入redisSku
err=skuCache.RedisInsertSkuInfo(skuId,string(newMapbytes))
if(err!=nil){
return nil
}
}
return nil
}
/**
struct 跟map Map合并,返回一个新的map(后续可以整理成公共函数)
*/
func (S *LySaveService) structMerageMap(redisSkuInfo model.SkuRedisInfo,oldSkuInfoMap map[string]interface{})(error,map[string]interface{}) {
//将新的redisSku数据struct 和 老的redis的数据map 合并成map并转换成json返回
GetValue:= func(fieldValue reflect.Value) interface{}{
switch fieldValue.Kind() {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int, reflect.Int64:
return fieldValue.Int()
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint, reflect.Uint64:
return fieldValue.Uint()
case reflect.Float32, reflect.Float64:
return fieldValue.Float()
case reflect.String:
return fieldValue.String()
case reflect.Bool:
return fieldValue.Bool()
default:
return "other"
//case reflect.Slice,:
}
}
//组装需要更新的redisSku数据 struct
var newMap =make(map[string]interface{})
v:=reflect.ValueOf(redisSkuInfo)
t:=reflect.TypeOf(redisSkuInfo)
for i:=0;i<v.NumField();i++ {
name:=t.Field(i).Tag.Get("json")
fieldValue:=v.Field(i)
//name:=v.Type().Name()
_, ok := oldSkuInfoMap[name];
if(v.Field(i).IsZero() && ok){// struct 有些字段为0值,还是要用老的redis的数据
newMap[name]=oldSkuInfoMap[name]
}else{
if(name=="ladder_price"){
newMap[name]=redisSkuInfo.LadderPrice //ladder_price 单独处理
}else{
mapValue:=GetValue(fieldValue)
newMap[name]=mapValue
}
}
delete(oldSkuInfoMap,name)//删除老的数据已经合并的字段
}
//将老数据独有的字段,放进newMap
if(len(oldSkuInfoMap)>0){
for oldk,oldv:=range oldSkuInfoMap{
newMap[oldk]=oldv
}
}
return nil,newMap
}
/**
修改
先写的SkuSave ,SkuEdit 基本是调用 SkuSave 之前写好的方法
*/
func (S *LySaveService)SkuEdit(lyEditRequest saveModel.LyEditRequest) (error,string){
lySkuEntity:=lyEditRequest.ToLySkuEntity()//sku实体
lySkuEntity.GoodsId=lyEditRequest.GoodsId
lySaveRequest:=lyEditRequest.ToLySaveRequest()//转换成lySaveRequest 因为公用 savesku封装的的方法,公用方法需要传lySaveRequest(后续参数改成接口)
//阶梯价格处理
err:=S.ladderPriceHandle(lySaveRequest.LadderPrice,&lySkuEntity)
if(err!=nil){
return e.NewApiError("SkuEdit 阶梯价格处理失败"+err.Error()),""
}
oldRedisStr,err:=skuCache.RedisGetSkuInfo(lyEditRequest.GoodsId)
if(err!=nil){
return e.NewApiError("修改sku:查询redis sku失败"+err.Error()),""
}
if(oldRedisStr==""){//判断是否存在
return e.NewApiError("sku不存在,skuID:"+lyEditRequest.GoodsId+err.Error()),""
}
err=S.update(lySkuEntity,lySaveRequest)
if(err!=nil){
return e.NewApiError("SkuEdit 修改sku失败"+err.Error()),""
}
return nil,lySkuEntity.GoodsId
}
\ No newline at end of file
package service
import (
"github.com/gogf/gf/util/gconv"
"github.com/gomodule/redigo/redis"
"go_sku_server/model"
"go_sku_server/pkg/gredis"
"go_sku_server/pkg/mongo"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type SkuCacheService struct {
}
/**
mongoDB 根据 spuId supplierId moq encoded canal 获取sku信息
*/
func (spuCacheService *SkuCacheService) MongoGetOnlySkuInfo(spuId string,supplierId int,moq int,encoded int,canal string)(error, model.SkuMongo){
var skuMongo model.SkuMongo
mongodb := mongo.Conn("default")
defer func() {
mongodb.Close()
}()
query:=bson.M{
"spu_id":gconv.Int64(spuId),
"supplier_id":supplierId,
"moq":moq,
"encoded":encoded,
"canal":canal,
}
err := mongodb.DB("ichunt").C("sku").Find(query).One(&skuMongo)
if err != nil {
if(err == mgo.ErrNotFound){
return nil,skuMongo
}
return err,skuMongo
}
return err,skuMongo
}
/**
mongo 插入sku
*/
func (spuCacheService *SkuCacheService) MongoInsertOnlySkuInfo(onlySkuInfo model.SkuMongo)(error){
mongoConn := mongo.Conn("default");
defer mongoConn.Close()
Mongo:=mongoConn.DB("ichunt").C("sku")
err:=Mongo.Insert(onlySkuInfo)
return err
}
/**
将单条sku数据压入redis
*/
func (spuCacheService *SkuCacheService)RedisInsertSkuInfo(skuId string,skuInfo string) error {
redisWriteConn := gredis.Conn("search_w")
defer redisWriteConn.Close()
_,err:=redisWriteConn.Do("HSet","sku",skuId,skuInfo)
return err;
}
/**
将skuID压入redis队列(list)(消费后将压入ES)
*/
func (spuCacheService *SkuCacheService)RedisPushEsList(skuId string) error {
redisWriteConn := gredis.Conn("search_w")
defer redisWriteConn.Close()
push_name:="update_list_sku";
_,err:=redisWriteConn.Do("Rpush",push_name,skuId)
return err
}
/**
获取sku redis单条信息
*/
func (spuCacheService *SkuCacheService)RedisGetSkuInfo(skuId string) (string,error) {
redisReadConn := gredis.Conn("search_r")
defer redisReadConn.Close()
skuInfoString,err:=redis.String(redisReadConn.Do("Hget","sku",skuId))
return skuInfoString,err
}
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