Commit 6313d9f2 authored by zhengyaoqiu's avatar zhengyaoqiu

feat(colorway): 加价率、运费、跨境运费等及其依赖

parent 6bc3863e
......@@ -3,8 +3,9 @@ module git.chillcy.com/golang/colorway
go 1.24.3
require (
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250627035541-7956996f27ce
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250703141544-f63c5883c3d1
git.chillcy.com/golang/chillcy/project/pc4 v0.0.0-20250630145511-385ed232051f
github.com/pkg/errors v0.9.1
github.com/zeromicro/go-zero v1.8.4
go.mongodb.org/mongo-driver v1.17.4
go.uber.org/multierr v1.11.0
......@@ -37,6 +38,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grafana/pyroscope-go v1.2.2 // indirect
......
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250627035541-7956996f27ce h1:JBhBnnNR7DCqi67fxfLC7ZIJJXJP4jMTtP8DeW9XcJQ=
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250627035541-7956996f27ce/go.mod h1:1N8ux+rPaW+/OT74EGSz2oX51NvsEK3H4nlBZ+5Xx0M=
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250703141544-f63c5883c3d1 h1:YKPXnj98Z+pQms4d9JetiHRgA4OmX9ksOBspauGXsPU=
git.chillcy.com/golang/chillcy/pkg v0.0.0-20250703141544-f63c5883c3d1/go.mod h1:1N8ux+rPaW+/OT74EGSz2oX51NvsEK3H4nlBZ+5Xx0M=
git.chillcy.com/golang/chillcy/project/pc4 v0.0.0-20250630145511-385ed232051f h1:08l02ihb9QCINdg2o202kclqEQK4gaqxYo0H7kz6/p8=
git.chillcy.com/golang/chillcy/project/pc4 v0.0.0-20250630145511-385ed232051f/go.mod h1:+oGrruo/MyXkrh5VPjDu/jvHN7tZGNkdZiKMJ/gIi4c=
github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI=
......@@ -61,9 +61,12 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
......
......@@ -2,23 +2,39 @@ package mongo
import (
"context"
siteGroupMarginConfigModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/SiteGroupMarginConfig"
brandDataModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/brand_data"
productModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/product"
siteComboMarginConfigModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/site_combo_margin_config"
siteFloatMarginConfigModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/site_float_margin_config"
sitePlatformPriceConfigModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/site_platform_price_config"
subjectModel "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/subject"
reflect2 "git.chillcy.com/golang/colorway/pkg/reflect"
"reflect"
)
const DatabaseColorWay = "color_way"
const DatabaseMpc = "mpc"
type Manager struct {
ProductModel productModel.ProductModel
SitePlatformPriceConfigModel sitePlatformPriceConfigModel.SitePlatformPriceConfigModel
SubjectModel subjectModel.SubjectModel
SiteComboMarginConfigModel siteComboMarginConfigModel.SiteComboMarginConfigModel
SiteFloatMarginConfigModel siteFloatMarginConfigModel.SiteFloatMarginConfigModel
BrandDataModel brandDataModel.BrandDataModel
SiteGroupMarginConfigModel siteGroupMarginConfigModel.SiteGroupMarginConfigModel
}
func NewManager(mongoUrl string) *Manager {
return &Manager{
ProductModel: productModel.NewProductModel(mongoUrl, DatabaseColorWay, productModel.Collection),
SitePlatformPriceConfigModel: sitePlatformPriceConfigModel.NewSitePlatformPriceConfigModel(mongoUrl, DatabaseColorWay, sitePlatformPriceConfigModel.Collection),
SitePlatformPriceConfigModel: sitePlatformPriceConfigModel.NewSitePlatformPriceConfigModel(mongoUrl, DatabaseMpc, sitePlatformPriceConfigModel.Collection),
SubjectModel: subjectModel.NewSubjectModel(mongoUrl, DatabaseMpc, subjectModel.Collection),
SiteComboMarginConfigModel: siteComboMarginConfigModel.NewSiteComboMarginConfigModel(mongoUrl, DatabaseMpc, siteComboMarginConfigModel.Collection),
SiteFloatMarginConfigModel: siteFloatMarginConfigModel.NewSiteFloatMarginConfigModel(mongoUrl, DatabaseMpc, siteFloatMarginConfigModel.Collection),
BrandDataModel: brandDataModel.NewBrandDataModel(mongoUrl, DatabaseMpc, brandDataModel.Collection),
SiteGroupMarginConfigModel: siteGroupMarginConfigModel.NewSiteGroupMarginConfigModel(mongoUrl, DatabaseMpc, brandDataModel.Collection),
}
}
......
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import (
"git.chillcy.com/golang/colorway/internal/pkg/database/mongo/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var _ SiteGroupMarginConfigModel = (*customSiteGroupMarginConfigModel)(nil)
type (
// SiteGroupMarginConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customSiteGroupMarginConfigModel.
SiteGroupMarginConfigModel interface {
siteGroupMarginConfigModel
cache.Cache[SiteGroupMarginConfig]
cache.ChangeStream[SiteGroupMarginConfig]
}
customSiteGroupMarginConfigModel struct {
*defaultSiteGroupMarginConfigModel
*cache.Base[SiteGroupMarginConfig]
}
)
// NewSiteGroupMarginConfigModel returns a model for the mongo.
func NewSiteGroupMarginConfigModel(url, db, collection string) SiteGroupMarginConfigModel {
conn := mon.MustNewModel(url, db, collection)
defaultModel := newDefaultSiteGroupMarginConfigModel(conn)
customModel := &customSiteGroupMarginConfigModel{
defaultSiteGroupMarginConfigModel: defaultModel,
}
customModel.Base = cache.NewBase[SiteGroupMarginConfig](defaultModel, customModel)
return customModel
}
func (receiver *customSiteGroupMarginConfigModel) DocumentEqual(a, b SiteGroupMarginConfig) bool {
return a.Id.Hex() == b.Id.Hex()
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/base"
"github.com/zeromicro/go-zero/core/stores/mon"
)
type siteGroupMarginConfigModel interface {
model.Model[SiteGroupMarginConfig]
}
type defaultSiteGroupMarginConfigModel struct {
conn *mon.Model
model.Base[SiteGroupMarginConfig]
}
func newDefaultSiteGroupMarginConfigModel(conn *mon.Model) *defaultSiteGroupMarginConfigModel {
return &defaultSiteGroupMarginConfigModel{
conn: conn,
Base: model.NewBase[SiteGroupMarginConfig](conn),
}
}
package model
import (
"git.chillcy.com/golang/chillcy/pkg/slice"
"git.chillcy.com/golang/colorway/pkg/types"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const Collection = "site_group_margin_config"
type SiteGroupMarginConfig struct {
Id *primitive.ObjectID `bson:"_id,omitempty"`
Seller types.Seller `bson:"seller"`
GroupName string `bson:"groupName"`
SiteIds []string `bson:"siteIds"`
Margin float64 `bson:"margin"`
Memos types.Memos `bson:"memos"`
Enable bool `bson:"enable"` // 是否启用
}
func (c *SiteGroupMarginConfig) IsMatch(site string) bool {
if !c.Enable {
return false
}
if len(c.SiteIds) > 0 && !slice.Contains(c.SiteIds, site) {
return false
}
return true
}
package model
import "github.com/zeromicro/go-zero/core/stores/mon"
var _ BrandDataModel = (*customBrandDataModel)(nil)
type (
// BrandDataModel is an interface to be customized, add more methods here,
// and implement the added methods in customBrandDataModel.
BrandDataModel interface {
brandDataModel
}
customBrandDataModel struct {
*defaultBrandDataModel
}
)
// NewBrandDataModel returns a model for the mongo.
func NewBrandDataModel(url, db, collection string) BrandDataModel {
conn := mon.MustNewModel(url, db, collection)
return &customBrandDataModel{
defaultBrandDataModel: newDefaultBrandDataModel(conn),
}
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/base"
"github.com/zeromicro/go-zero/core/stores/mon"
)
type brandDataModel interface {
model.Model[BrandData]
}
type defaultBrandDataModel struct {
conn *mon.Model
model.Base[BrandData]
}
func newDefaultBrandDataModel(conn *mon.Model) *defaultBrandDataModel {
return &defaultBrandDataModel{
conn: conn,
Base: model.NewBase[BrandData](conn),
}
}
package model
const Collection = "brand_data"
type BrandData struct {
Id string `bson:"_id"`
BrandName string `bson:"brandName"`
Count int `bson:"count"`
SearchWord string `bson:"searchWord"`
PriceRangeCounts []PriceRangeCount `bson:"priceRangeCounts"`
ProductSellCounts []ProductSellCount `bson:"productSellCounts"`
PlatformOrderCount map[string]PlatformOrderCount `bson:"platformOrderCount"` // key platform
PlatformPayAmount map[string]PlatformPayAmount `bson:"platformPayAmount"`
}
type BrandDataList []BrandData
type PriceRangeCount struct {
Min float64 `bson:"min"`
Max float64 `bson:"max"`
Count int `bson:"count"`
}
type PlatformPayAmount struct {
DayRange map[int]float64 `bson:"dayRange"`
}
type PlatformOrderCount struct {
DayRange map[int]int `bson:"dayRange"`
OrderCount int `json:"orderCount"`
}
type ProductSellCount struct {
Mid string `bson:"mid"`
Count int `bson:"count"`
}
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
......@@ -3,3 +3,13 @@ package model
//go:generate goctl model mongo --type Product --dir product --home ../templates --style go_zero
//go:generate goctl model mongo --type SitePlatformPriceConfig --dir site_platform_price_config --home ../templates --style go_zero
//go:generate goctl model mongo --type Subject --dir subject --home ../templates --style go_zero
//go:generate goctl model mongo --type SiteComboMarginConfig --dir site_combo_margin_config --home ../templates --style go_zero
//go:generate goctl model mongo --type SiteFloatMarginConfig --dir site_float_margin_config --home ../templates --style go_zero
//go:generate goctl model mongo --type BrandData --dir brand_data --home ../templates --style go_zero
//go:generate goctl model mongo --type SiteGroupMarginConfig --dir SiteGroupMarginConfig --home ../templates --style go_zero
package model
import (
"git.chillcy.com/golang/colorway/internal/pkg/database/mongo/types"
"git.chillcy.com/golang/chillcy/pkg/gender"
"git.chillcy.com/golang/colorway/pkg/types"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
......@@ -11,7 +12,8 @@ const Collection = "product"
type Product struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
StyleNumber string `bson:"styleNumber"`
StyleId string `bson:"styleId"` // 可以是分割形式出来的主款号,也可以是品牌官网同款组的 ID
StyleNumber string `bson:"styleNumber"` // 源款号
Title ProductTitle `bson:"title"`
Description string `bson:"description"`
Season string `bson:"season"`
......@@ -24,7 +26,7 @@ type Product struct {
Category ProductCategory `bson:"category"`
Compositions ProductCompositions `bson:"compositions"`
Fits []string `bson:"fits"`
Genders ProductGenders `bson:"genders"`
Genders gender.Genders `bson:"genders"`
Models []string `bson:"models"`
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
......@@ -32,18 +34,6 @@ type Product struct {
type Products []Product
type ProductGender string
type ProductGenders []ProductGender
const (
GenderMan ProductGender = "man"
GenderWoman ProductGender = "woman"
GenderBaby ProductGender = "baby"
GenderGirl ProductGender = "girl"
GenderBoy ProductGender = "boy"
)
type ProductComposition struct {
Part string `bson:"part"`
Material string `bson:"material"`
......@@ -66,8 +56,15 @@ func (receiver ProductCategory) GetIds() []string {
return ids
}
// Style 记录原始款号信息
type Style struct {
Number string `bson:"number"`
ColorCode string `bson:"colorCode"`
}
type ProductColor struct {
ColorCode string `bson:"colorCode"`
ColorId string `bson:"colorId"` // 可以是分割出来的色号,也可以是品牌官网同款组的唯一确定颜色的款号
ColorCode string `bson:"colorCode"` // 源色号
Id string `bson:"id"`
Name string `bson:"name"`
BasicId string `bson:"basicId"`
......@@ -88,6 +85,7 @@ type ProductColorSku struct {
Stock int `bson:"stock"`
Price float64 `bson:"price"`
Currency string `bson:"currency"`
SubjectIds []string `bson:"subjectIds"`
ProductColorSkuPlatformStoreSkus []ProductColorSkuPlatformStoreSkus `bson:"productColorSkuPlatformStoreSkus"`
}
......@@ -104,31 +102,27 @@ type ProductBrand struct {
}
type ProductColorSkuPlatformStoreSku struct {
Platform string `bson:"platform"` // 销售平台
Store string `bson:"store"` // 销售平台具体店铺
Qty int `bson:"qty"` // 库存
FixedQty *int `bson:"fixedQty,omitempty"` // 虚拟库存
Route string `bson:"route"` // 线路
Currency string `bson:"currency"` // 销售平台的币种
OriginCurrency string `bson:"originCurrency"` // 原始币种
Price float64 `bson:"price"` // 最终价格
FixPrice *float64 `bson:"fixPrice,omitempty"` // 固定价格
FixMargin *float64 `bson:"fixMargin,omitempty"` // 固定加价率(影响计价)
Rate float64 `bson:"rate"` // OriginCurrency -> Currency 的汇率
CnyRate float64 `bson:"cnyRate"` // Currency -> CNY 的汇率
Margin float64 `bson:"margin"` // 加价率
SubjectRate float64 `bson:"subjectRate"` // 专题系数
Subject *primitive.ObjectID `bson:"subject"` // 绑定的专题id
DiscountRate float64 `bson:"discountRate"` // 商家系数
TotalDiscount float64 `bson:"totalDiscount"` // 总折扣
TaxRate float64 `bson:"taxRate"` // 税率
Freight float64 `bson:"freight"` // 商家运费
Express float64 `bson:"express"` // 跨境费
ChangeRate *float64 `bson:"changeRate,omitempty"` // 价格变动率, 0.1表示涨价10%, -0.1表示降价10%
ChangeAt *time.Time `bson:"changeAt,omitempty"` // 价格变动时间,方便筛选
Memos types.Memos `bson:"memos,omitempty"` // 操作备注
// todo 有固定价格固定库存等操作就是有固定操作
IsFixed *bool `bson:"isFixed,omitempty"` // 是否有固定操作
Platform types.Platform `bson:"platform"` // 销售平台
Store types.Store `bson:"store"` // 销售平台具体店铺
Route types.Route `bson:"route"` // 线路
Currency string `bson:"currency"` // 销售平台的币种
OriginCurrency string `bson:"originCurrency"` // 原始币种
Price float64 `bson:"price"` // 最终价格
FixPrice *float64 `bson:"fixPrice,omitempty"` // 固定价格
FixMargin *float64 `bson:"fixMargin,omitempty"` // 固定加价率(影响计价)
Rate float64 `bson:"rate"` // OriginCurrency -> Currency 的汇率
CnyRate float64 `bson:"cnyRate"` // Currency -> CNY 的汇率
Margin float64 `bson:"margin"` // 加价率
SubjectRate float64 `bson:"subjectRate"` // 专题系数
Subject string `bson:"subject"` // 绑定的专题id
DiscountRate float64 `bson:"discountRate"` // 商家系数
TotalDiscount float64 `bson:"totalDiscount"` // 总折扣
TaxRate float64 `bson:"taxRate"` // 税率
Freight float64 `bson:"freight"` // 商家运费
Express float64 `bson:"express"` // 跨境费
ChangeRate *float64 `bson:"changeRate,omitempty"` // 价格变动率, 0.1表示涨价10%, -0.1表示降价10%
ChangeAt *time.Time `bson:"changeAt,omitempty"` // 价格变动时间,方便筛选
Memos types.Memos `bson:"memos,omitempty"` // 操作备注
}
type ProductColorSkuPlatformStoreSkus []ProductColorSkuPlatformStoreSku
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import (
"git.chillcy.com/golang/colorway/internal/pkg/database/mongo/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var _ SiteComboMarginConfigModel = (*customSiteComboMarginConfigModel)(nil)
type (
// SiteComboMarginConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customSiteComboMarginConfigModel.
SiteComboMarginConfigModel interface {
siteComboMarginConfigModel
cache.Cache[SiteComboMarginConfig]
cache.ChangeStream[SiteComboMarginConfig]
}
customSiteComboMarginConfigModel struct {
*defaultSiteComboMarginConfigModel
*cache.Base[SiteComboMarginConfig]
}
)
// NewSiteComboMarginConfigModel returns a model for the mongo.
func NewSiteComboMarginConfigModel(url, db, collection string) SiteComboMarginConfigModel {
conn := mon.MustNewModel(url, db, collection)
defaultModel := newDefaultSiteComboMarginConfigModel(conn)
customModel := &customSiteComboMarginConfigModel{
defaultSiteComboMarginConfigModel: defaultModel,
}
customModel.Base = cache.NewBase[SiteComboMarginConfig](defaultModel, customModel)
return customModel
}
func (receiver *customSiteComboMarginConfigModel) DocumentEqual(a, b SiteComboMarginConfig) bool {
return a.Id.Hex() == b.Id.Hex()
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/base"
"github.com/zeromicro/go-zero/core/stores/mon"
)
type siteComboMarginConfigModel interface {
model.Model[SiteComboMarginConfig]
}
type defaultSiteComboMarginConfigModel struct {
conn *mon.Model
model.Base[SiteComboMarginConfig]
}
func newDefaultSiteComboMarginConfigModel(conn *mon.Model) *defaultSiteComboMarginConfigModel {
return &defaultSiteComboMarginConfigModel{
conn: conn,
Base: model.NewBase[SiteComboMarginConfig](conn),
}
}
package model
import (
"git.chillcy.com/golang/chillcy/pkg/gender"
"git.chillcy.com/golang/chillcy/pkg/slice"
"git.chillcy.com/golang/colorway/pkg/types"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const Collection = "site_combo_margin_config"
type SiteComboMarginConfig struct {
Id primitive.ObjectID `bson:"_id,omitempty"`
Seller types.Seller `bson:"seller"`
SiteId string `bson:"siteId"`
Brands []string `bson:"brands"`
Genders gender.Genders `bson:"genders"`
Categories []string `bson:"categories"`
Margin float64 `bson:"margin"`
Memos types.Memos `bson:"memos"`
Enable bool `bson:"enable"` // 是否启用`
}
func (receiver SiteComboMarginConfig) IsGenderMatch(genders gender.Genders) bool {
if len(receiver.Genders) <= 0 {
return true
}
genders = slice.RemoveDuplicateItem(genders)
for _, g := range receiver.Genders {
if g == gender.GenderAdult {
v := slice.ContainsElems(genders, []gender.Gender{
gender.GenderMan,
gender.GenderWoman,
}) || onlyHave(genders, g)
if v {
return true
}
}
if g == gender.GenderChild {
v := slice.ContainsElems(genders, []gender.Gender{
gender.GenderBoy,
gender.GenderGirl,
}) || onlyHave(genders, g)
if v {
return true
}
}
if onlyHave(genders, g) {
return true
}
}
return false
}
func onlyHave(arr []gender.Gender, v gender.Gender) bool {
if len(arr) == 1 && arr[0] == v {
return true
}
return false
}
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import (
"git.chillcy.com/golang/colorway/internal/pkg/database/mongo/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var _ SiteFloatMarginConfigModel = (*customSiteFloatMarginConfigModel)(nil)
type (
// SiteFloatMarginConfigModel is an interface to be customized, add more methods here,
// and implement the added methods in customSiteFloatMarginConfigModel.
SiteFloatMarginConfigModel interface {
siteFloatMarginConfigModel
cache.Cache[SiteFloatMarginConfig]
cache.ChangeStream[SiteFloatMarginConfig]
}
customSiteFloatMarginConfigModel struct {
*defaultSiteFloatMarginConfigModel
*cache.Base[SiteFloatMarginConfig]
}
)
// NewSiteFloatMarginConfigModel returns a model for the mongo.
func NewSiteFloatMarginConfigModel(url, db, collection string) SiteFloatMarginConfigModel {
conn := mon.MustNewModel(url, db, collection)
defaultModel := newDefaultSiteFloatMarginConfigModel(conn)
customModel := &customSiteFloatMarginConfigModel{
defaultSiteFloatMarginConfigModel: defaultModel,
}
customModel.Base = cache.NewBase[SiteFloatMarginConfig](defaultModel, customModel)
return customModel
}
func (receiver *customSiteFloatMarginConfigModel) DocumentEqual(a, b SiteFloatMarginConfig) bool {
return a.Id.Hex() == b.Id.Hex()
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/base"
"github.com/zeromicro/go-zero/core/stores/mon"
)
type siteFloatMarginConfigModel interface {
model.Model[SiteFloatMarginConfig]
}
type defaultSiteFloatMarginConfigModel struct {
conn *mon.Model
model.Base[SiteFloatMarginConfig]
}
func newDefaultSiteFloatMarginConfigModel(conn *mon.Model) *defaultSiteFloatMarginConfigModel {
return &defaultSiteFloatMarginConfigModel{
conn: conn,
Base: model.NewBase[SiteFloatMarginConfig](conn),
}
}
package model
import (
"encoding/json"
"git.chillcy.com/golang/colorway/pkg/types"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const Collection = "site_float_margin_config"
type SiteFloatMarginConfig struct {
Id *primitive.ObjectID `bson:"_id,omitempty"`
Seller types.Seller `bson:"seller"`
Season string `bson:"season"`
Category string `bson:"category"`
Brand string `bson:"brand"`
Enable bool `bson:"enable"` // 是否启用
Memos types.Memos `bson:"memos"`
}
type ConditionRule struct {
Type string `bson:"type"`
Params []ConditionKv `bson:"params"`
}
func (cr ConditionRule) Get(k string) string {
for _, p := range cr.Params {
if p.Key == k {
return p.Value
}
}
return ""
}
const ConditionKeySeasonCO = "season_co" // CO经典款
const ConditionKeySeasonNow = "season_now" // 当季款
const ConditionKeySeasonOld = "season_old" // 过季款
const ConditionKeyBrandTop = "brand_top" // 头部品牌
const ConditionKeyBrandMiddle = "brand_middle" // 腰部品牌
const ConditionKeyBrandTail = "brand_tail" // 尾部品牌
const ConditionKeyCategoryClothing = "category_clothing" // 服装品类
const ConditionKeyCategoryShoes = "category_shoes" // 鞋靴品类
const ConditionKeyCategoryBags = "category_bag" // 包袋品类
const ConditionKeyCategoryAccessories = "category_accessory" // 配饰品类
type ConditionKv struct {
Key string `bson:"key"`
Value string `bson:"value"`
}
func (c *SiteFloatMarginConfig) Explain() ([]ConditionRule, error) {
rules := make([]ConditionRule, 0)
if c.Season != "" {
rule, err := convertToRule("season", c.Season)
if err != nil {
return nil, err
}
rules = append(rules, *rule)
}
if c.Category != "" {
rule, err := convertToRule("category", c.Category)
if err != nil {
return nil, err
}
rules = append(rules, *rule)
}
if c.Brand != "" {
rule, err := convertToRule("brand", c.Brand)
if err != nil {
return nil, err
}
rules = append(rules, *rule)
}
return rules, nil
}
func convertToRule(_type, content string) (*ConditionRule, error) {
var jsonContent map[string]interface{}
err := json.Unmarshal([]byte(content), &jsonContent)
if err != nil {
return nil, err
}
rule := ConditionRule{
Type: _type,
}
for key, value := range jsonContent {
rule.Params = append(rule.Params, ConditionKv{
Key: key,
Value: value.(string),
})
}
return &rule, nil
}
......@@ -29,7 +29,17 @@ type RoutePriceConfig struct {
ExpressConfig ExpressConfig `json:"expressConfig" bson:"expressConfig"` // 跨境快递配置,默认是0
}
func (rc *RoutePriceConfig) IsValid() bool {
func (mc MarginConfig) FormatLadders() {
if mc.MarginStyle == MarginStyleLadder {
for i := range mc.Ladders {
if i == len(mc.Ladders)-1 {
mc.Ladders[i].LastOne = true
}
}
}
}
func (rc RoutePriceConfig) IsValid() bool {
// 路线价格配置校验-加价率
if rc.MarginConfig.MarginStyle == MarginStyleFixed && (rc.MarginConfig.Margin <= 0 || rc.MarginConfig.Margin > 1) {
return false
......@@ -91,7 +101,14 @@ type MarginConfig struct {
Ladders []Ladder `json:"ladders" bson:"ladders"` // 阶梯加价,加价方式为阶梯加价时使用
}
func (mc *MarginConfig) IsValidLadders() bool {
func (l Ladder) IsMatch(price float64) bool {
if l.LastOne && l.Max == 0 {
return price >= l.Min
}
return price >= l.Min && price < l.Max
}
func (mc MarginConfig) IsValidLadders() bool {
if mc.MarginStyle == MarginStyleLadder {
if len(mc.Ladders) <= 0 {
return false
......
package model
import (
"errors"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var (
ErrNotFound = mon.ErrNotFound
ErrInvalidObjectId = errors.New("invalid objectId")
)
package model
import (
"git.chillcy.com/golang/colorway/internal/pkg/database/mongo/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
)
var _ SubjectModel = (*customSubjectModel)(nil)
type (
// SubjectModel is an interface to be customized, add more methods here,
// and implement the added methods in customSubjectModel.
SubjectModel interface {
subjectModel
cache.Cache[Subject]
cache.ChangeStream[Subject]
}
customSubjectModel struct {
*defaultSubjectModel
*cache.Base[Subject]
}
)
// NewSubjectModel returns a model for the mongo.
func NewSubjectModel(url, db, collection string) SubjectModel {
conn := mon.MustNewModel(url, db, collection)
defaultModel := newDefaultSubjectModel(conn)
customModel := &customSubjectModel{
defaultSubjectModel: defaultModel,
}
customModel.Base = cache.NewBase[Subject](defaultModel, customModel)
return customModel
}
func (receiver *customSubjectModel) DocumentEqual(a, b Subject) bool {
return a.Id.Hex() == b.Id.Hex()
}
// Code generated by goctl. DO NOT EDIT.
package model
import (
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/base"
"github.com/zeromicro/go-zero/core/stores/mon"
)
type subjectModel interface {
model.Model[Subject]
}
type defaultSubjectModel struct {
conn *mon.Model
model.Base[Subject]
}
func newDefaultSubjectModel(conn *mon.Model) *defaultSubjectModel {
return &defaultSubjectModel{
conn: conn,
Base: model.NewBase[Subject](conn),
}
}
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
const Collection = "subject"
type Subject struct {
Id primitive.ObjectID `bson:"_id,omitempty"` // 从pc3同步过来的专题ID
Title string `bson:"title"`
PriceRate float64 `bson:"priceRate"`
Platforms []Platform `bson:"platforms"`
StartAt *time.Time `bson:"startAt"`
ExpiredAt *time.Time `bson:"expiredAt"`
Created time.Time `bson:"created"`
Updated time.Time `bson:"updated"`
}
type Platform struct {
Name string `bson:"name" `
VoTag string `bson:"voTag" `
Count int `bson:"count" `
IsSync bool `bson:"isSync" `
ExpiredAt *time.Time `bson:"expiredAt" `
}
......@@ -11,8 +11,8 @@ type ColorSpu struct {
// 外键
// 多对一
Skus Skus `gorm:"foreignKey:ColorSpuStyleNumber,ColorSpuColorCode; references:CompleteSpuStyleNumber,ColorCode; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Images Images `gorm:"foreignKey:ColorSpuStyleNumber,ColorSpuColorCode; references:CompleteSpuStyleNumber,ColorCode; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Skus Skus `gorm:"foreignKey:ColorSpuStyleNumber,ColorSpuColorCode; references:CompleteSpuStyleNumber,ColorId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
Images Images `gorm:"foreignKey:ColorSpuStyleNumber,ColorSpuColorCode; references:CompleteSpuStyleNumber,ColorId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
}
type ColorSpus []ColorSpu
......
......@@ -16,13 +16,13 @@ type CompleteSpu struct {
// 外键
// 多对一
ColorSpus ColorSpus `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleNumber; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Compositions Compositions `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleNumber; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Models Models `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleNumber; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Fits Fits `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleNumber; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ColorSpus ColorSpus `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Compositions Compositions `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Models Models `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Fits Fits `gorm:"foreignKey:CompleteSpuStyleNumber; references:StyleId; constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
// 多对多
Genders Genders `gorm:"many2many:completespu_genders;foreignKey:StyleNumber; References:Code;"`
Categories Categories `gorm:"many2many:completespu_categories;foreignKey:StyleNumber; References:Code;"`
Genders Genders `gorm:"many2many:completespu_genders;foreignKey:StyleId; References:Code;"`
Categories Categories `gorm:"many2many:completespu_categories;foreignKey:StyleId; References:Code;"`
}
type CompleteSpus []CompleteSpu
......
......@@ -38,7 +38,7 @@ func upsertCompleteSpus(db *gorm.DB, completeSpus model.CompleteSpus) error {
return result.Error
}
// OnConflict 导致的更新操作不会回填 ID,即使外键 StyleNumber 存在,也会报错 WHERE conditions required,所以重新读取出来
// OnConflict 导致的更新操作不会回填 ID,即使外键 StyleId 存在,也会报错 WHERE conditions required,所以重新读取出来
styleNumbers := completeSpus.GetStyleNumbers()
var reloadedSpus []model.CompleteSpu
err := db.Where("style_number IN ?", styleNumbers).Find(&reloadedSpus).Error
......
......@@ -35,7 +35,7 @@ func (l *UploadLogic) Upload(in *colorway.ProductUploadRequest) (*colorway.Produ
var writeModels []mongo.WriteModel
for _, p := range ps {
filter := bson.M{
"style_number": p.StyleNumber,
"style_number": p.StyleId,
}
update := bson.D{
{"$set", p},
......
package cache
import (
"context"
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/brand_data"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"sync"
"time"
)
type BrandRank struct {
brandDataModel model.BrandDataModel
rwMutex *sync.RWMutex
topBrands []string
middleBrands []string
}
func NewBrandData(brandDataModel model.BrandDataModel) *BrandRank {
return &BrandRank{brandDataModel: brandDataModel, rwMutex: new(sync.RWMutex)}
}
func (receiver *BrandRank) Refresh(ctx context.Context) error {
opt := options.Find()
opt.SetProjection(bson.D{{"_id", 1}})
opt.SetSort(bson.D{{"platformPayAmount.all.dayRange.90", -1}})
opt.SetLimit(100)
brandDataList, _, err := receiver.brandDataModel.Find(ctx, bson.M{}, opt)
if err != nil {
return err
}
top := brandDataList[:30]
topIds := make([]string, 0)
for _, data := range top {
topIds = append(topIds, data.Id)
}
middleIds := make([]string, 0)
if len(brandDataList) > 30 {
middle := brandDataList[30:]
for _, data := range middle {
middleIds = append(middleIds, data.Id)
}
}
receiver.setBrandRankIds(topIds, middleIds)
return nil
}
func (receiver *BrandRank) setBrandRankIds(topBrands, middleBrands []string) {
receiver.rwMutex.Lock()
defer receiver.rwMutex.Unlock()
receiver.topBrands = topBrands
receiver.middleBrands = middleBrands
}
func (receiver *BrandRank) GetBrandRankIds() ([]string, []string) {
receiver.rwMutex.RLock()
defer receiver.rwMutex.RUnlock()
return receiver.topBrands, receiver.middleBrands
}
func (receiver *BrandRank) Interval() time.Duration {
return time.Hour
}
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"git.chillcy.com/golang/chillcy/project/pc4/pkg/rpc/client/source"
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/brand_data"
"github.com/zeromicro/go-zero/core/logc"
"go.uber.org/multierr"
"log"
......@@ -19,13 +20,17 @@ type Cache struct {
func InitCache(config Config) {
s := NewSource(config.Source)
bd := NewBrandData(config.BrandDataModel)
// 注册缓存刷新 Map
_cache = &Cache{
refreshMap: map[RefreshKey]Refresh{
RefreshKeySource: s,
RefreshKeySource: s,
RefreshKeyRankBrandIds: bd,
},
Source: s,
}
err := _cache.Notify(RefreshKeySource)
// 初始化第一次加载缓存
err := _cache.Notify(RefreshKeySource, RefreshKeyRankBrandIds)
if err != nil {
panic(err)
}
......@@ -68,11 +73,13 @@ func (receiver *Cache) startRefresh() {
type RefreshKey string
const (
RefreshKeySource = "source"
RefreshKeySource = "source"
RefreshKeyRankBrandIds = "rankBrandIds"
)
type Config struct {
Source source.Source
Source source.Source
BrandDataModel model.BrandDataModel
}
func GetCache() *Cache {
......
package convert
import (
"git.chillcy.com/golang/chillcy/pkg/gender"
"git.chillcy.com/golang/chillcy/pkg/slice"
"git.chillcy.com/golang/chillcy/project/pc4/pkg/rpc/pb/pc4"
model "git.chillcy.com/golang/colorway/internal/pkg/database/mongo/model/product"
......@@ -28,6 +29,7 @@ func (receiver *Product) Convert(designerProducts []*pc4.DesignerProduct) model.
for _, productAndSkus := range colorProduct.GetProductAndSkusList() {
product := productAndSkus.GetProduct()
once.Do(func() {
p.StyleId = styleNumber
p.StyleNumber = styleNumber
p.Title = model.ProductTitle{
En: product.GetTitleEn(),
......@@ -53,7 +55,7 @@ func (receiver *Product) Convert(designerProducts []*pc4.DesignerProduct) model.
}
p.Fits = product.GetDetail().GetFits()
for _, g := range product.GetGenders() {
p.Genders = append(p.Genders, model.ProductGender(g))
p.Genders = append(p.Genders, gender.Gender(g))
}
p.Models = product.GetDetail().GetModels()
})
......@@ -92,7 +94,7 @@ func (receiver *Product) Convert(designerProducts []*pc4.DesignerProduct) model.
}
}
}
p.Colors = buildProductColors(designerProduct.GetColorProducts(), designerProduct.GetDesignerId(), ws)
p.Colors = buildProductColors(designerProduct.GetColorProducts(), ws, designerProduct.GetDesignerId())
ps = append(ps, p)
}
return ps
......@@ -111,20 +113,21 @@ func getCategory(category *pc4.CategoryV2) model.ProductCategory {
return pc
}
func buildProductColors(colorProducts []*pc4.ColorProduct, styleNumber string, ws weightSelect) model.ProductColors {
func buildProductColors(colorProducts []*pc4.ColorProduct, ws weightSelect, styleNumber string) model.ProductColors {
var pcs model.ProductColors
for _, colorProduct := range colorProducts {
pcs = append(pcs, buildProductColor(colorProduct, styleNumber, ws))
pcs = append(pcs, buildProductColor(colorProduct, ws, styleNumber))
}
return pcs
}
func buildProductColor(colorProduct *pc4.ColorProduct, styleNumber string, ws weightSelect) model.ProductColor {
func buildProductColor(colorProduct *pc4.ColorProduct, ws weightSelect, styleNumber string) model.ProductColor {
pc := model.ProductColor{}
once := &sync.Once{}
for _, productAndSkus := range colorProduct.GetProductAndSkusList() {
product := productAndSkus.GetProduct()
once.Do(func() {
pc.ColorId = colorProduct.GetColorNumber()
pc.ColorCode = colorProduct.GetColorNumber()
pc.Id = product.GetColor().GetId()
pc.Name = product.GetColor().GetName()
......@@ -148,6 +151,7 @@ func buildProductColor(colorProduct *pc4.ColorProduct, styleNumber string, ws we
Stock: int(sku.GetStock()),
Price: sku.GetPriceDetail().GetNow(),
Currency: sku.GetPriceDetail().GetCurrency(),
SubjectIds: product.Subjects,
})
}
}
......
package priceRouteAdapter
import "go.mongodb.org/mongo-driver/bson/primitive"
import (
"git.chillcy.com/golang/colorway/pkg/types"
)
type RoutePriceDetail struct {
Route string `bson:"route"` // 线路
Currency string `bson:"currency"` // 销售平台的币种
OriginCurrency string `bson:"originCurrency"` // 原始币种
Price float64 `bson:"price"` // 最终价格
Rate float64 `bson:"rate"` // OriginCurrency -> Currency 的汇率
Margin float64 `bson:"margin"` // 加价率
SubjectRate float64 `bson:"subjectRate"` // 专题系数
Subject *primitive.ObjectID `bson:"subjectID"` // 绑定的专题id
DiscountRate float64 `bson:"discountRate"` // 商家系数
TotalDiscount float64 `bson:"totalDiscount"` // 总折扣
TaxRate float64 `bson:"taxRate"` // 税率
Freight float64 `bson:"freight"` // 商家运费
Express float64 `bson:"express"` // 跨境费
Route types.Route `bson:"route"` // 线路
Currency string `bson:"currency"` // 销售平台的币种
OriginCurrency string `bson:"originCurrency"` // 原始币种
Price float64 `bson:"price"` // 最终价格
Rate float64 `bson:"rate"` // OriginCurrency -> Currency 的汇率
Margin float64 `bson:"margin"` // 加价率
SubjectRate float64 `bson:"subjectRate"` // 专题系数
Subject string `bson:"subjectID"` // 绑定的专题id
DiscountRate float64 `bson:"discountRate"` // 商家系数
TotalDiscount float64 `bson:"totalDiscount"` // 总折扣
TaxRate float64 `bson:"taxRate"` // 税率
Freight float64 `bson:"freight"` // 商家运费
Express float64 `bson:"express"` // 跨境费
}
package rate
import (
"fmt"
"git.chillcy.com/golang/chillcy/pkg/sdk/rate"
"git.chillcy.com/golang/colorway/pkg/types"
)
type Rate struct {
rateClient *rate.Client
}
func (receiver *Rate) GetRate(store types.Store, from, to string) (float64, error) {
switch store {
case types.StoreTmall2cStore1, types.StoreJDStoreGongxiao:
return receiver.rateClient.Sell(from, to)
case types.StoreTmall2bHK, types.StoreTmall2bEUR, types.StoreTmall2bUS:
return receiver.rateClient.Net(from, to)
}
return 0, fmt.Errorf("未配置店铺汇率 %s", store)
}
......@@ -40,7 +40,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
},
}
cache.InitCache(cache.Config{
Source: svc.Pc4RpcService.Source,
Source: svc.Pc4RpcService.Source,
BrandDataModel: mongoManager.BrandDataModel,
})
svc.Cache = cache.GetCache()
svc.SpuConvert = convert.NewSpu(svc.Cache)
......
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 to comment