refactor: 重构资产实体和DTO结构类型
将gjson.Json类型替换为具体的结构体和map类型,修正DAO层链式调用,启用SKU元数据校验逻辑
This commit is contained in:
37
config.yml
37
config.yml
@@ -17,8 +17,8 @@ rate:
|
||||
database:
|
||||
default:
|
||||
- type: "pgsql"
|
||||
host: "116.204.74.41"
|
||||
port: "15432"
|
||||
host: "localhost"
|
||||
port: "5432"
|
||||
user: "postgres"
|
||||
pass: "123456"
|
||||
name: "assets"
|
||||
@@ -34,8 +34,8 @@ database:
|
||||
deletedAt: "deleted_at" # (可选)软删除时间字段名称
|
||||
timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性,为true时CreatedAt/UpdatedAt/DeletedAt都将失效
|
||||
- type: "pgsql"
|
||||
host: "116.204.74.41"
|
||||
port: "15432"
|
||||
host: "localhost"
|
||||
port: "5432"
|
||||
user: "postgres"
|
||||
pass: "123456"
|
||||
name: "assets"
|
||||
@@ -52,8 +52,8 @@ database:
|
||||
timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性,为true时CreatedAt/UpdatedAt/DeletedAt都将失效
|
||||
tenant-1:
|
||||
- type: "pgsql" # 使用自定义驱动,自动赋值创建人/修改人/租户ID
|
||||
host: "116.204.74.41"
|
||||
port: "15432"
|
||||
host: "localhost"
|
||||
port: "5432"
|
||||
user: "postgres"
|
||||
pass: "123456"
|
||||
name: "tenant"
|
||||
@@ -72,7 +72,7 @@ database:
|
||||
redis:
|
||||
# 集群模式配置方法
|
||||
default:
|
||||
address: 116.204.74.41:6379
|
||||
address: localhost:6379
|
||||
db: 0
|
||||
idleTimeout: "60s"
|
||||
maxConnLifetime: "90s"
|
||||
@@ -82,7 +82,7 @@ redis:
|
||||
writeTimeout: "30s"
|
||||
maxActive: 100
|
||||
test:
|
||||
address: 116.204.74.41:6379
|
||||
address: localhost:6379
|
||||
db: 1
|
||||
idleTimeout: "60s"
|
||||
maxConnLifetime: "90s"
|
||||
@@ -93,18 +93,31 @@ redis:
|
||||
maxActive: 100
|
||||
|
||||
consul:
|
||||
address: 116.204.74.41:8500
|
||||
address: localhost:8500
|
||||
|
||||
jaeger:
|
||||
addr: 116.204.74.41:4318
|
||||
addr: localhost:4318
|
||||
|
||||
nats:
|
||||
default:
|
||||
url: "nats://116.204.74.41:4222"
|
||||
url: "nats://localhost:4222"
|
||||
|
||||
# 文件上传服务地址,与oss模块minio中的endpoint一致
|
||||
filePrefix: "116.204.74.41:9000"
|
||||
|
||||
cache:
|
||||
localTTL: 60
|
||||
redisTTL: 300
|
||||
redisTTL: 300
|
||||
|
||||
gmq:
|
||||
redis:
|
||||
primary:
|
||||
addr: "localhost"
|
||||
port: "6379"
|
||||
db: 0
|
||||
username: ""
|
||||
password: ""
|
||||
poolSize: 10
|
||||
minIdleConn: 5
|
||||
maxActiveConn: 10
|
||||
maxRetries: 30
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
package consts
|
||||
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
// AssetSkuStatus SKU状态枚举
|
||||
|
||||
type AssetSkuStatusType *int
|
||||
var (
|
||||
AssetSkuStatusDisable = newAssetSkuStatus(gconv.PtrInt8(0), "disable")
|
||||
AssetSkuStatusEnable = newAssetSkuStatus(gconv.PtrInt8(1), "enable")
|
||||
)
|
||||
|
||||
type AssetSkuStatus struct {
|
||||
Status AssetSkuStatusType
|
||||
type AssetSkuStatus *int8
|
||||
|
||||
type assetSkuStatus struct {
|
||||
code AssetSkuStatus
|
||||
desc string
|
||||
}
|
||||
|
||||
func (s assetSkuStatus) Code() AssetSkuStatus {
|
||||
return s.code
|
||||
}
|
||||
func (s assetSkuStatus) Desc() string {
|
||||
return s.desc
|
||||
}
|
||||
|
||||
func newAssetSkuStatus(code AssetSkuStatus, desc string) assetSkuStatus {
|
||||
return assetSkuStatus{code: code, desc: desc}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
package consts
|
||||
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
// AssetStatus 资产状态枚举
|
||||
|
||||
type AssetStatusType *int
|
||||
var (
|
||||
AssetStatusDisable = newAssetStatus(gconv.PtrInt8(0), "disable")
|
||||
AssetStatusEnable = newAssetStatus(gconv.PtrInt8(1), "enable")
|
||||
)
|
||||
|
||||
type AssetStatus struct {
|
||||
Status AssetStatusType
|
||||
type AssetStatus *int8
|
||||
|
||||
type assetStatus struct {
|
||||
code AssetStatus
|
||||
desc string
|
||||
}
|
||||
|
||||
func (s assetStatus) Code() AssetStatus {
|
||||
return s.code
|
||||
}
|
||||
func (s assetStatus) Desc() string {
|
||||
return s.desc
|
||||
}
|
||||
|
||||
func newAssetStatus(code AssetStatus, desc string) assetStatus {
|
||||
return assetStatus{code: code, desc: desc}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
package consts
|
||||
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
// CategoryStatus 分类状态枚举
|
||||
|
||||
type CategoryStatusType *int
|
||||
var (
|
||||
CategoryStatusDisable = newCategoryStatus(gconv.PtrInt8(0), "disable")
|
||||
CategoryStatusEnable = newCategoryStatus(gconv.PtrInt8(1), "enable")
|
||||
)
|
||||
|
||||
type CategoryStatus struct {
|
||||
Status CategoryStatusType
|
||||
type CategoryStatus *int8
|
||||
|
||||
type categoryStatus struct {
|
||||
code CategoryStatus
|
||||
desc string
|
||||
}
|
||||
|
||||
//var CategoryStatusVal = CategoryStatus{
|
||||
// CategoryStatusActive: gconv.PtrInt(1),
|
||||
// CategoryStatusInactive: gconv.PtrInt(0),
|
||||
//}
|
||||
func (s categoryStatus) Code() CategoryStatus {
|
||||
return s.code
|
||||
}
|
||||
func (s categoryStatus) Desc() string {
|
||||
return s.desc
|
||||
}
|
||||
|
||||
func newCategoryStatus(code CategoryStatus, desc string) categoryStatus {
|
||||
return categoryStatus{code: code, desc: desc}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@ package public
|
||||
|
||||
// MongoDB集合名称常量
|
||||
const (
|
||||
AssetCollection = "assets_asset" // 资产集合
|
||||
CategoryCollection = "assets_category" // 分类集合
|
||||
AssetCollection = "assets_asset" // 资产集合
|
||||
AssetSkuCollection = "assets_asset_sku" // SKU集合
|
||||
StockDetailsCollection = "assets_stock_details" // 库存明细集合
|
||||
StockBatchCollection = "assets_stock_batch" // 库存批次集合
|
||||
PrivateCategoryCollection = "private_category" // 私域分类集合
|
||||
StockDetailsCollection = "stock_details" // 库存明细集合
|
||||
StockBatchCollection = "stock_batch" // 库存批次集合
|
||||
PrivateStockCollection = "private_stock" // 私域库存批次集合
|
||||
PurchaseOrderCollection = "purchase_order" // 采购订单主表集合(统一模式)
|
||||
PurchaseOrderItemCollection = "purchase_order_item" // 采购订单明细集合
|
||||
PurchaseBidCollection = "purchase_bid" // 采购投标单集合(供应商抢单参与记录)
|
||||
AssetSkuCollection = "asset_sku" // SKU集合
|
||||
PrivateSkuCollection = "private_sku" // 私域sku集合
|
||||
SupplierCollection = "supplier" // 供应商集合
|
||||
ExpiryMessageCollection = "expiry_message" // 临期消息集合(兼容旧数据)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package public
|
||||
|
||||
const StockDetailLockKey = "stock:lock:skuId-%s"
|
||||
const StockDetailLockKey = "stock:lock:skuId-%v"
|
||||
|
||||
// 消费者配置(从 Redis Stream 消费请求)
|
||||
const StockDetailQueueName = "assets:stock:detail:request:stream" // 请求 Stream 键名(与发消息的key一致)
|
||||
const StockDetailGroupName = "assets:stock:detail:consumer:group" // 消费者组名
|
||||
const StockDetailConsumerName = "message-consumer-1" // 消费者名称(唯一标识)
|
||||
const StockDetailPrefetchCount = 1 // 批处理大小(每次读取1条)
|
||||
const StockDetailAutoAck = false // ACK是否自动确认(true自动确认,false不确认)
|
||||
const StockDetailQueueName = "assets:stock:stream" // 请求 Stream 键名(与发消息的key一致)
|
||||
const StockDetailConsumerName = "assets-stock-consumer" // 消费者名称(唯一标识)
|
||||
const StockDetailPrefetchCount = 1 // 批处理大小(每次读取1条)
|
||||
const StockDetailAutoAck = false // ACK是否自动确认(true自动确认,false不确认)
|
||||
|
||||
// 业务自增序列号前缀 Redis Key
|
||||
const (
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
package stock
|
||||
|
||||
// BatchStatus 批次状态枚举
|
||||
type BatchStatus int
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
const (
|
||||
BatchStatusActive BatchStatus = 1 // 活跃
|
||||
BatchStatusExpiring BatchStatus = 2 // 临期
|
||||
BatchStatusExpired BatchStatus = 3 // 过期
|
||||
BatchStatusSoldOut BatchStatus = 4 // 售罄
|
||||
// BatchStatus 批次状态枚举
|
||||
|
||||
var (
|
||||
BatchStatusActive = newBatchStatus(gconv.PtrInt8(1), "活跃")
|
||||
BatchStatusExpiring = newBatchStatus(gconv.PtrInt8(2), "临期")
|
||||
BatchStatusExpired = newBatchStatus(gconv.PtrInt8(3), "过期")
|
||||
BatchStatusSoldOut = newBatchStatus(gconv.PtrInt8(4), "售罄")
|
||||
)
|
||||
|
||||
// GetAllBatchStatuses 获取所有批次状态
|
||||
func GetAllBatchStatuses() []BatchStatus {
|
||||
return []BatchStatus{
|
||||
BatchStatusActive,
|
||||
BatchStatusExpiring,
|
||||
BatchStatusExpired,
|
||||
BatchStatusSoldOut,
|
||||
}
|
||||
type BatchStatus *int8
|
||||
|
||||
type batchStatus struct {
|
||||
code BatchStatus
|
||||
desc string
|
||||
}
|
||||
|
||||
func (s batchStatus) Code() BatchStatus {
|
||||
return s.code
|
||||
}
|
||||
func (s batchStatus) Desc() string {
|
||||
return s.desc
|
||||
}
|
||||
|
||||
func newBatchStatus(code BatchStatus, desc string) batchStatus {
|
||||
return batchStatus{code: code, desc: desc}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
package stock
|
||||
|
||||
// StockStatus 库存状态枚举
|
||||
type StockStatus int
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
const (
|
||||
StockStatusAvailable StockStatus = 1 // 可用,未分配渠道
|
||||
StockStatusSold StockStatus = 2 // 已售出
|
||||
StockStatusReserved StockStatus = 3 // 预留
|
||||
StockStatusLocked StockStatus = 4 // 锁定
|
||||
// StockStatus 库存状态枚举
|
||||
|
||||
var (
|
||||
StockStatusAvailable = newStockStatus(gconv.PtrInt8(1), "可用,未分配渠道")
|
||||
StockStatusSold = newStockStatus(gconv.PtrInt8(2), "已售出")
|
||||
StockStatusReserved = newStockStatus(gconv.PtrInt8(3), "预留")
|
||||
StockStatusLocked = newStockStatus(gconv.PtrInt8(4), "锁定")
|
||||
)
|
||||
|
||||
// GetAllStockStatuses 获取所有库存状态
|
||||
func GetAllStockStatuses() []StockStatus {
|
||||
return []StockStatus{
|
||||
StockStatusAvailable,
|
||||
StockStatusSold,
|
||||
StockStatusReserved,
|
||||
StockStatusLocked,
|
||||
}
|
||||
type StockStatus *int8
|
||||
|
||||
type stockStatus struct {
|
||||
code StockStatus
|
||||
desc string
|
||||
}
|
||||
|
||||
func (s stockStatus) Code() StockStatus {
|
||||
return s.code
|
||||
}
|
||||
func (s stockStatus) Desc() string {
|
||||
return s.desc
|
||||
}
|
||||
|
||||
func newStockStatus(code StockStatus, desc string) stockStatus {
|
||||
return stockStatus{code: code, desc: desc}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,6 @@
|
||||
// 注意:Update/Delete返回*beans.ResponseEmpty,直接return
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type stockBatchController struct{}
|
||||
|
||||
var StockBatch = new(stockBatchController)
|
||||
@@ -19,24 +11,24 @@ var StockBatch = new(stockBatchController)
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *stockBatchController) CreateBatch(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
|
||||
return service.StockBatch.Create(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockBatchController) UpdateBatch(ctx context.Context, req *dto.UpdateBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.StockBatch.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *stockBatchController) DeleteBatch(ctx context.Context, req *dto.DeleteBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
err = service.StockBatch.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *stockBatchController) GetBatch(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
|
||||
return service.StockBatch.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockBatchController) ListBatches(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
|
||||
return service.StockBatch.List(ctx, req)
|
||||
}
|
||||
//func (c *stockBatchController) CreateBatch(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
|
||||
// return service.StockBatch.Create(ctx, req)
|
||||
//}
|
||||
//
|
||||
//func (c *stockBatchController) UpdateBatch(ctx context.Context, req *dto.UpdateBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
// err = service.StockBatch.Update(ctx, req)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (c *stockBatchController) DeleteBatch(ctx context.Context, req *dto.DeleteBatchReq) (res *beans.ResponseEmpty, err error) {
|
||||
// err = service.StockBatch.Delete(ctx, req)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (c *stockBatchController) GetBatch(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
|
||||
// return service.StockBatch.GetOne(ctx, req)
|
||||
//}
|
||||
//
|
||||
//func (c *stockBatchController) ListBatches(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
|
||||
// return service.StockBatch.List(ctx, req)
|
||||
//}
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
// 注意:只读接口,无写操作
|
||||
package controller
|
||||
|
||||
import (
|
||||
dto "assets/model/dto/stock"
|
||||
service "assets/service/stock"
|
||||
"context"
|
||||
)
|
||||
|
||||
type stockDetails struct{}
|
||||
|
||||
// StockDetails 库存控制器
|
||||
@@ -18,10 +12,10 @@ var StockDetails = new(stockDetails)
|
||||
func init() {
|
||||
}
|
||||
|
||||
func (c *stockDetails) GetStockDetails(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
|
||||
return service.StockDetails.GetOne(ctx, req)
|
||||
}
|
||||
|
||||
func (c *stockDetails) ListStockDetails(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
|
||||
return service.StockDetails.List(ctx, req)
|
||||
}
|
||||
//func (c *stockDetails) GetStockDetails(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
|
||||
// return service.StockDetails.GetOne(ctx, req)
|
||||
//}
|
||||
//
|
||||
//func (c *stockDetails) ListStockDetails(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
|
||||
// return service.StockDetails.List(ctx, req)
|
||||
//}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int6
|
||||
if err = gconv.Struct(req, &res); err != nil {
|
||||
return
|
||||
}
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Data(&res).Insert()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Data(&res).Insert()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int6
|
||||
|
||||
// Update 更新资产
|
||||
func (d *assetDao) Update(ctx context.Context, req *dto.UpdateAssetReq) (rows int64, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).OmitEmpty().Where(entity.AssetCol.Id, req.Id).Update()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Data(&req).OmitEmpty().Where(entity.AssetCol.Id, req.Id).Update()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (d *assetDao) Delete(ctx context.Context, req *dto.DeleteAssetReq) (rows in
|
||||
|
||||
// GetOne 获取单个资产
|
||||
func (d *assetDao) GetOne(ctx context.Context, req *dto.GetAssetReq, fields ...string) (res *entity.Asset, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where(entity.AssetCol.Id, req.Id).Fields(fields).One()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Where(entity.AssetCol.Id, req.Id).Fields(fields).One()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (id i
|
||||
if err = gconv.Struct(req, &res); err != nil {
|
||||
return
|
||||
}
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Ctx(ctx).Data(&res).Insert()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Data(&res).Insert()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -32,7 +32,7 @@ func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (id i
|
||||
|
||||
// Update 更新SKU
|
||||
func (d *assetSku) Update(ctx context.Context, req *dto.UpdateAssetSkuReq) (rows int64, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Ctx(ctx).OmitEmpty().Where(entity.AssetCol.Id, req.Id).Update()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Data(&req).OmitEmpty().Where(entity.AssetCol.Id, req.Id).Update()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (d *assetSku) Delete(ctx context.Context, req *dto.DeleteAssetSkuReq) (rows
|
||||
|
||||
// GetOne 获取单个SKU
|
||||
func (d *assetSku) GetOne(ctx context.Context, req *dto.GetAssetSkuReq, fields ...string) (res *entity.AssetSku, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Ctx(ctx).Where(entity.AssetCol.Id, req.Id).Fields(fields).One()
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Where(entity.AssetCol.Id, req.Id).Fields(fields).One()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -104,8 +104,10 @@ func (d *assetSku) buildListFilter(ctx context.Context, req *dto.ListAssetSkuReq
|
||||
}
|
||||
model.Where(entity.AssetSkuCol.Id, req.Id)
|
||||
model.Where(entity.AssetSkuCol.Status, req.Status)
|
||||
model.WhereGT(entity.AssetSkuCol.Price, req.MinPrice)
|
||||
model.WhereLT(entity.AssetSkuCol.Price, req.MaxPrice)
|
||||
if req.MinPrice > 0 && req.MaxPrice > 0 {
|
||||
model.WhereGT(entity.AssetSkuCol.Price, req.MinPrice)
|
||||
model.WhereLT(entity.AssetSkuCol.Price, req.MaxPrice)
|
||||
}
|
||||
model.OmitEmptyWhere()
|
||||
return model
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import (
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var StockBatch = new(stockBatch)
|
||||
@@ -21,58 +22,48 @@ type stockBatch struct {
|
||||
}
|
||||
|
||||
// Insert 插入
|
||||
func (d *stockBatch) Insert(ctx context.Context, req *dto.CreateBatchReq) (ids []interface{}, err error) {
|
||||
var result *entity.StockBatch
|
||||
if err = utils.Struct(req, &result); err != nil {
|
||||
func (d *stockBatch) Insert(ctx context.Context, req *dto.CreateSockBatchReq) (id int64, err error) {
|
||||
var res *entity.StockBatch
|
||||
if err = gconv.Struct(req, &res); err != nil {
|
||||
return
|
||||
}
|
||||
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// Update 更新批次数量(使用$inc原子操作,并发安全)
|
||||
func (d *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) (err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
update := bson.M{
|
||||
"$inc": bson.M{
|
||||
"batchQty": req.BatchQty,
|
||||
"availableQty": req.AvailableQty,
|
||||
},
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.StockBatchCollection).Data(&res).Insert()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = mongo.DB().Update(ctx, filter, update, public.StockBatchCollection)
|
||||
return
|
||||
return r.LastInsertId()
|
||||
}
|
||||
|
||||
// GetOne 根据批次号查询(使用NoCache跳过缓存,确保获取最新数据)
|
||||
func (d *stockBatch) GetOne(ctx context.Context, batchNo string) (res *entity.StockBatch, err error) {
|
||||
filter := bson.M{"batchNo": batchNo}
|
||||
err = mongo.DB().NoCache().FindOne(ctx, filter, &res, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetOneById 根据ID查询批次
|
||||
func (d *stockBatch) GetOneById(ctx context.Context, req *dto.GetBatchReq) (res *entity.StockBatch, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.StockBatchCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteFake 软删除批次
|
||||
func (d *stockBatch) DeleteFake(ctx context.Context, req *dto.DeleteBatchReq) error {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
_, err := mongo.DB().DeleteSoft(ctx, filter, public.StockBatchCollection)
|
||||
return err
|
||||
}
|
||||
|
||||
// List 查询批次列表
|
||||
func (d *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res []entity.StockBatch, total int64, err error) {
|
||||
filter := bson.M{}
|
||||
if req.AssetId != nil {
|
||||
filter["assetId"] = req.AssetId
|
||||
func (d *stockBatch) Update(ctx context.Context, req *dto.UpdateSockBatchReq) (rows int64, err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.StockBatchCollection).OmitEmpty().Where(entity.StockBatchCol.Id, req.Id)
|
||||
model.Data(entity.StockBatchCol.BatchQty, &gdb.Counter{
|
||||
Field: entity.StockBatchCol.BatchQty,
|
||||
Value: gconv.Float64(req.BatchQty),
|
||||
})
|
||||
model.Data(entity.StockBatchCol.AvailableQty, &gdb.Counter{
|
||||
Field: entity.StockBatchCol.AvailableQty,
|
||||
Value: gconv.Float64(req.AvailableQty),
|
||||
})
|
||||
r, err := model.Update()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if req.AssetSkuId != nil {
|
||||
filter["assetSkuId"] = req.AssetSkuId
|
||||
return r.RowsAffected()
|
||||
}
|
||||
|
||||
// One 根据批次号查询(使用NoCache跳过缓存,确保获取最新数据)
|
||||
func (d *stockBatch) One(ctx context.Context, req *dto.GetSockBatchReq, fields ...string) (res *entity.StockBatch, err error) {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.StockBatchCollection)
|
||||
if !g.IsEmpty(req.Id) {
|
||||
model.Where(entity.StockBatchCol.Id, req.Id)
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.StockBatchCollection, req.Page, req.OrderBy)
|
||||
if !g.IsEmpty(req.BatchNo) {
|
||||
model.Where(entity.StockBatchCol.BatchNo, req.BatchNo)
|
||||
}
|
||||
r, err := model.Fields(fields).One()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = r.Struct(&res)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,15 +6,13 @@ package dao
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/db/mongo"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"gitea.com/red-future/common/db/gfdb"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
var StockDetails = new(stockDetails)
|
||||
@@ -23,58 +21,52 @@ type stockDetails struct {
|
||||
}
|
||||
|
||||
// BatchInsert 批量插入库存
|
||||
func (d *stockDetails) BatchInsert(ctx context.Context, stockInterfaces []interface{}) (ids []interface{}, err error) {
|
||||
ids, err = mongo.DB().Insert(ctx, stockInterfaces, public.StockDetailsCollection)
|
||||
func (d *stockDetails) BatchInsert(ctx context.Context, req []*dto.CreateSockDetailsReq) (rows int64, err error) {
|
||||
var res []*entity.StockDetails
|
||||
if err = gconv.Structs(req, &res); err != nil {
|
||||
return
|
||||
}
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.StockDetailsCollection).Data(res).Save()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return r.RowsAffected()
|
||||
}
|
||||
|
||||
func (d *stockDetails) Delete(ctx context.Context, req []dto.DeleteSockDetailsReq) (rows int64, err error) {
|
||||
r, err := gfdb.DB(ctx).Model(ctx, public.StockDetailsCollection).Where(entity.StockDetailsCol.Id, &req).Delete()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return r.RowsAffected()
|
||||
}
|
||||
|
||||
func (d *stockDetails) Count(ctx context.Context, req *dto.GetSockDetailsReq) (count int, err error) {
|
||||
return d.buildListFilter(ctx, req).Count()
|
||||
}
|
||||
|
||||
func (d *stockDetails) List(ctx context.Context, req *dto.GetSockDetailsReq, fields ...string) (res []entity.StockDetails, total int, err error) {
|
||||
model := d.buildListFilter(ctx, req)
|
||||
model.Fields(fields)
|
||||
model.OrderDesc(entity.StockDetailsCol.CreatedAt)
|
||||
if req.Page != nil {
|
||||
model.Page(int(req.Page.PageNum), int(req.Page.PageSize))
|
||||
}
|
||||
r, total, err := model.AllAndCount(false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = r.Structs(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteManyByIds 根据ID批量删除库存
|
||||
func (d *stockDetails) DeleteManyByIds(ctx context.Context, allStockIds []*bson.ObjectID) (count int64, err error) {
|
||||
if len(allStockIds) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
filter := bson.M{"_id": bson.M{"$in": allStockIds}}
|
||||
count, err = mongo.DB().Delete(ctx, filter, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// GetStockCountBySkuId 获取库存数根据SKU ID
|
||||
func (d *stockDetails) GetStockCountBySkuId(ctx context.Context, assetSkuId int64) (total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter := bson.M{}
|
||||
filter["assetSkuId"] = assetSkuId
|
||||
filter["status"] = stock.StockStatusAvailable
|
||||
// 检查总数
|
||||
total, err = mongo.DB().NoCache().Count(ctx, filter, public.StockDetailsCollection)
|
||||
|
||||
return total, err
|
||||
}
|
||||
|
||||
// GetOneById 根据ID查询库存明细
|
||||
func (d *stockDetails) GetOneById(ctx context.Context, req *dto.GetStockDetailsReq) (res *entity.StockDetails, err error) {
|
||||
filter := bson.M{"_id": req.Id}
|
||||
err = mongo.DB().FindOne(ctx, filter, &res, public.StockDetailsCollection)
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取SKU列表
|
||||
func (d *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res []entity.StockDetails, total int64, err error) {
|
||||
// 构建查询过滤条件
|
||||
filter := bson.M{}
|
||||
if !g.IsEmpty(req.AssetId) {
|
||||
filter["assetId"] = req.AssetId
|
||||
}
|
||||
if !g.IsEmpty(req.AssetSkuId) {
|
||||
filter["assetSkuId"] = req.AssetSkuId
|
||||
}
|
||||
if !g.IsEmpty(req.Status) {
|
||||
filter["status"] = req.Status
|
||||
}
|
||||
// 排序处理
|
||||
req.OrderBy = []beans.OrderBy{
|
||||
{Field: "sort", Order: beans.Asc},
|
||||
{Field: "createdAt", Order: beans.Desc},
|
||||
}
|
||||
total, err = mongo.DB().Find(ctx, filter, &res, public.StockDetailsCollection, req.Page, req.OrderBy)
|
||||
return
|
||||
// buildListFilter 构建列表查询的过滤条件
|
||||
func (d *stockDetails) buildListFilter(ctx context.Context, req *dto.GetSockDetailsReq) *gdb.Model {
|
||||
model := gfdb.DB(ctx).Model(ctx, public.StockDetailsCollection).Model
|
||||
model.Where(entity.StockDetailsCol.Id, req.Id)
|
||||
model.Where(entity.StockDetailsCol.AssetId, req.AssetId)
|
||||
model.Where(entity.StockDetailsCol.AssetSkuId, req.AssetSkuId)
|
||||
model.Where(entity.StockDetailsCol.Status, req.Status)
|
||||
model.OmitEmptyWhere()
|
||||
return model
|
||||
}
|
||||
|
||||
51
go.mod
51
go.mod
@@ -4,14 +4,17 @@ go 1.25.7
|
||||
|
||||
require (
|
||||
gitea.com/red-future/common v0.0.4
|
||||
github.com/bjang03/gmq v0.0.0-20251219093200-000000000000
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.10.0
|
||||
github.com/gogf/gf/v2 v2.10.0
|
||||
github.com/redis/go-redis/v9 v9.12.1
|
||||
github.com/xuri/excelize/v2 v2.10.0
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.1
|
||||
github.com/redis/go-redis/v9 v9.18.0
|
||||
github.com/xuri/excelize/v2 v2.10.1
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0
|
||||
)
|
||||
|
||||
//replace gitea.com/red-future/common v0.0.4 => ../common
|
||||
replace gitea.com/red-future/common v0.0.4 => ../common
|
||||
|
||||
replace github.com/bjang03/gmq => ../gmq
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
@@ -25,11 +28,15 @@ require (
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.1 // indirect
|
||||
github.com/gogf/gf/contrib/registry/consul/v2 v2.9.5 // indirect
|
||||
@@ -54,33 +61,39 @@ require (
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/serf v0.10.1 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/compress v1.18.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
|
||||
github.com/klauspost/crc32 v1.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.10 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/minio/crc64nvme v1.1.0 // indirect
|
||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.97 // indirect
|
||||
github.com/minio/minio-go/v7 v7.0.99 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/nats-io/nats.go v1.49.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.15 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/olekukonko/tablewriter v1.1.0 // indirect
|
||||
github.com/philhofer/fwd v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.6 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.6 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.1 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.2 // indirect
|
||||
github.com/tiger1103/gfast-token v1.0.10 // indirect
|
||||
github.com/tinylib/msgp v1.3.0 // indirect
|
||||
github.com/tinylib/msgp v1.6.1 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/scram v1.2.0 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
@@ -94,12 +107,14 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||
golang.org/x/crypto v0.44.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250808145144-a408d31f581a // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
|
||||
60
go.sum
60
go.sum
@@ -63,8 +63,12 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
|
||||
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
@@ -76,6 +80,12 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
@@ -189,6 +199,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
@@ -203,6 +215,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||
@@ -230,10 +244,14 @@ github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/minio/crc64nvme v1.1.0 h1:e/tAguZ+4cw32D+IO/8GSf5UVr9y+3eJcxZI2WOO/7Q=
|
||||
github.com/minio/crc64nvme v1.1.0/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
|
||||
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.97 h1:lqhREPyfgHTB/ciX8k2r8k0D93WaFqxbJX36UZq5occ=
|
||||
github.com/minio/minio-go/v7 v7.0.97/go.mod h1:re5VXuo0pwEtoNLsNuSr0RrLfT/MBtohwdaSmPPSRSk=
|
||||
github.com/minio/minio-go/v7 v7.0.99 h1:2vH/byrwUkIpFQFOilvTfaUpvAX3fEFhEzO+DR3DlCE=
|
||||
github.com/minio/minio-go/v7 v7.0.99/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
|
||||
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
@@ -243,6 +261,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE=
|
||||
github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw=
|
||||
github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4=
|
||||
github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
@@ -275,13 +299,21 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
||||
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg=
|
||||
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
|
||||
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
|
||||
github.com/richardlehane/mscfb v1.0.6/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
||||
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg=
|
||||
github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
@@ -294,6 +326,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
@@ -307,21 +341,29 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
|
||||
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
|
||||
github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||
github.com/tiger1103/gfast-token v1.0.10 h1:fNiBE/Dq5iTHvTGlCx3DmXa2o4hr0NtumFpffZ39k6s=
|
||||
github.com/tiger1103/gfast-token v1.0.10/go.mod h1:a/21mxmj7zFeNvjhZSC0XpEAFHfb1aT2k6DXnufFU1s=
|
||||
github.com/tinylib/msgp v1.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww=
|
||||
github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
|
||||
github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY=
|
||||
github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
|
||||
github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
|
||||
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.10.0 h1:8aKsP7JD39iKLc6dH5Tw3dgV3sPRh8uRVXu/fMstfW4=
|
||||
github.com/xuri/excelize/v2 v2.10.0/go.mod h1:SC5TzhQkaOsTWpANfm+7bJCldzcnU/jrhqkTi/iBHBU=
|
||||
github.com/xuri/excelize/v2 v2.10.1 h1:V62UlqopMqha3kOpnlHy2CcRVw1V8E63jFoWUmMzxN0=
|
||||
github.com/xuri/excelize/v2 v2.10.1/go.mod h1:iG5tARpgaEeIhTqt3/fgXCGoBRt4hNXgCp3tfXKoOIc=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
@@ -331,6 +373,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.1 h1:hGDMngUao03OVQ6sgV5csk+RWOIkF+CuLsTPobNMGNI=
|
||||
go.mongodb.org/mongo-driver/v2 v2.4.1/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
@@ -351,8 +395,12 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
@@ -361,6 +409,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250808145144-a408d31f581a h1:Y+7uR/b1Mw2iSXZ3G//1haIiSElDQZ8KWh0h+sZPG90=
|
||||
golang.org/x/exp v0.0.0-20250808145144-a408d31f581a/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg=
|
||||
@@ -391,6 +441,9 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -402,6 +455,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -431,6 +486,9 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -441,6 +499,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
||||
21
main.go
21
main.go
@@ -1,11 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
assetController "assets/controller/asset"
|
||||
enumController "assets/controller/enum"
|
||||
procurementController "assets/controller/procurement"
|
||||
stockController "assets/controller/stock"
|
||||
syncController "assets/controller/sync"
|
||||
stockService "assets/service/stock"
|
||||
"context"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -13,10 +15,11 @@ import (
|
||||
|
||||
"gitea.com/red-future/common/http"
|
||||
"gitea.com/red-future/common/jaeger"
|
||||
|
||||
_ "gitea.com/red-future/common/swagger"
|
||||
gmq "github.com/bjang03/gmq/core/gmq"
|
||||
"github.com/bjang03/gmq/mq"
|
||||
"github.com/bjang03/gmq/types"
|
||||
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
@@ -86,6 +89,20 @@ func main() {
|
||||
// })
|
||||
//}
|
||||
|
||||
gmq.Init("config.yml")
|
||||
err := gmq.GetGmq("primary").GmqSubscribe(ctx, &mq.RedisSubMessage{
|
||||
SubMessage: types.SubMessage{
|
||||
Topic: public.StockDetailQueueName,
|
||||
ConsumerName: public.StockDetailConsumerName,
|
||||
AutoAck: public.StockDetailAutoAck,
|
||||
FetchCount: public.StockDetailPrefetchCount,
|
||||
HandleFunc: stockService.StockManage.AddStock,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 监听退出信号
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"assets/consts/stock"
|
||||
"assets/model/config"
|
||||
enumDto "assets/model/dto/enum"
|
||||
entity "assets/model/entity/asset"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@@ -15,18 +16,18 @@ import (
|
||||
type CreateAssetReq struct {
|
||||
g.Meta `path:"/createAsset" method:"post" tags:"资产管理" summary:"创建资产" dc:"创建新的资产"`
|
||||
// 基础信息
|
||||
Name string `json:"name" v:"required" dc:"资产名称"`
|
||||
Description string `json:"description" dc:"资产描述"`
|
||||
Type consts.AssetType `json:"type" v:"required" dc:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `json:"categoryId" v:"required" dc:"分类ID"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
ImageURL string `json:"imageUrl" dc:"主图URL"`
|
||||
Images []string `json:"images" dc:"图片列表"`
|
||||
Status consts.AssetStatusType `json:"status" dc:"状态:1/0" d:"1"`
|
||||
UnlimitedStock bool `json:"unlimitedStock" dc:"是否无库存限制"`
|
||||
StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式" d:"2"`
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"`
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty" dc:"下线时间(格式:2006-01-02 15:04:05)"`
|
||||
Name string `json:"name" v:"required" dc:"资产名称"`
|
||||
Description string `json:"description" dc:"资产描述"`
|
||||
Type consts.AssetType `json:"type" v:"required" dc:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `json:"categoryId" v:"required" dc:"分类ID"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
ImageURL string `json:"imageUrl" dc:"主图URL"`
|
||||
Images []string `json:"images" dc:"图片列表"`
|
||||
Status consts.AssetStatus `json:"status" dc:"状态:1/0" d:"1"`
|
||||
UnlimitedStock bool `json:"unlimitedStock" dc:"是否无库存限制"`
|
||||
StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式" d:"2"`
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"`
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty" dc:"下线时间(格式:2006-01-02 15:04:05)"`
|
||||
// 类型专用配置 - 实物资产配置
|
||||
PhysicalAssetConfig *config.PhysicalAssetConfig `json:"physicalAssetConfig"`
|
||||
// 类型专用配置 - 服务资产配置
|
||||
@@ -52,7 +53,7 @@ type ListAssetReq struct {
|
||||
Type consts.AssetType `json:"type" dc:"资产类型"`
|
||||
CategoryId int64 `json:"categoryId" dc:"分类ID"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
Status consts.AssetStatusType `json:"status" dc:"状态"`
|
||||
Status consts.AssetStatus `json:"status" dc:"状态"`
|
||||
TenantModuleType beans.TenantModuleType `json:"tenantModuleType" dc:"租户模块类型"`
|
||||
Keyword string `json:"keyword" dc:"关键词搜索"`
|
||||
}
|
||||
@@ -64,18 +65,18 @@ type ListAssetRes struct {
|
||||
}
|
||||
|
||||
type AssetItem struct {
|
||||
Id int64 `json:"id"` // 资产ID
|
||||
Name string `json:"name"` // 资产名称
|
||||
Type consts.AssetType `json:"type"` // 资产类型:physical实物/virtual虚拟/service服务
|
||||
TypeName string `json:"typeName"` // 资产类型:physical实物/virtual虚拟/service服务
|
||||
CategoryId int64 `json:"categoryId"` // 分类ID
|
||||
UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制
|
||||
Status consts.AssetStatusType `json:"status"` // 资产状态:active启用/inactive停用
|
||||
BasePrice int `json:"basePrice"` // 基础价格(分为单位)
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty"` // 上线时间
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty"` // 下线时间
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
Id int64 `json:"id,string"` // 资产ID
|
||||
Name string `json:"name"` // 资产名称
|
||||
Type consts.AssetType `json:"type"` // 资产类型:physical实物/virtual虚拟/service服务
|
||||
TypeName string `json:"typeName"` // 资产类型:physical实物/virtual虚拟/service服务
|
||||
CategoryId int64 `json:"categoryId,string"` // 分类ID
|
||||
UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制
|
||||
Status consts.AssetStatus `json:"status"` // 资产状态:active启用/inactive停用
|
||||
BasePrice int `json:"basePrice"` // 基础价格(分为单位)
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty"` // 上线时间
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty"` // 下线时间
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
// GetAssetReq 获取资产详情请求
|
||||
@@ -86,7 +87,7 @@ type GetAssetReq struct {
|
||||
|
||||
// GetAssetRes 获取资产详情响应
|
||||
type GetAssetRes struct {
|
||||
*AssetItem
|
||||
*entity.Asset
|
||||
CategoryName string `json:"categoryName" dc:"分类名称"`
|
||||
ImgAddressPrefix string `json:"imgAddressPrefix"`
|
||||
}
|
||||
@@ -99,7 +100,7 @@ type GetAssetAndSkuReq struct {
|
||||
|
||||
// GetAssetAndSkuRes 获取资产详情响应
|
||||
type GetAssetAndSkuRes struct {
|
||||
*AssetItem
|
||||
*entity.Asset
|
||||
Skus []AssetSkuItem `json:"skus" dc:"SKU列表"`
|
||||
TenantModuleType []enumDto.KeyValue `json:"tenantModuleType" dc:"租户模块类型"`
|
||||
ImgAddressPrefix string `json:"imgAddressPrefix"`
|
||||
@@ -108,16 +109,16 @@ type GetAssetAndSkuRes struct {
|
||||
// UpdateAssetReq 更新资产请求
|
||||
type UpdateAssetReq struct {
|
||||
g.Meta `path:"/updateAsset" method:"put" tags:"资产管理" summary:"更新资产" dc:"更新资产信息"`
|
||||
Id int64 `json:"id" v:"required" dc:"资产ID"`
|
||||
Name string `json:"name" dc:"资产名称"`
|
||||
Description string `json:"description" dc:"资产描述"`
|
||||
Type consts.AssetType `json:"type" dc:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `json:"categoryId" dc:"分类ID"`
|
||||
ImageURL string `json:"imageUrl" dc:"主图URL"`
|
||||
Images []string `json:"images" dc:"图片列表"`
|
||||
Status consts.AssetStatusType `json:"status,omitempty" dc:"状态:1/0"`
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"`
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty" dc:"下线时间(格式:2006-01-02 15:04:05)"`
|
||||
Id int64 `json:"id" v:"required" dc:"资产ID"`
|
||||
Name string `json:"name" dc:"资产名称"`
|
||||
Description string `json:"description" dc:"资产描述"`
|
||||
Type consts.AssetType `json:"type" dc:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `json:"categoryId" dc:"分类ID"`
|
||||
ImageURL string `json:"imageUrl" dc:"主图URL"`
|
||||
Images []string `json:"images" dc:"图片列表"`
|
||||
Status consts.AssetStatus `json:"status,omitempty" dc:"状态:1/0"`
|
||||
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"`
|
||||
OfflineTime *gtime.Time `json:"offlineTime,omitempty" dc:"下线时间(格式:2006-01-02 15:04:05)"`
|
||||
// 类型专用配置 - 实物资产配置
|
||||
PhysicalAssetConfig *config.PhysicalAssetConfig `json:"physicalAssetConfig"`
|
||||
// 类型专用配置 - 服务资产配置
|
||||
@@ -131,8 +132,8 @@ type UpdateAssetReq struct {
|
||||
// UpdateAssetStatusReq 更新资产状态请求
|
||||
type UpdateAssetStatusReq struct {
|
||||
g.Meta `path:"/updateAssetStatus" method:"put" tags:"资产管理" summary:"更新资产状态" dc:"更新资产状态"`
|
||||
Id int64 `json:"id" v:"required" dc:"资产ID"`
|
||||
Status consts.AssetStatusType `json:"status" v:"required|in:1,0" dc:"状态:1启用/0停用"`
|
||||
Id int64 `json:"id" v:"required" dc:"资产ID"`
|
||||
Status consts.AssetStatus `json:"status" v:"required|in:1,0" dc:"状态:1启用/0停用"`
|
||||
}
|
||||
|
||||
// DeleteAssetReq 删除资产请求
|
||||
|
||||
@@ -23,7 +23,7 @@ type CreateAssetSkuReq struct {
|
||||
ImageURL string `json:"imageUrl" v:"required" dc:"SKU主图"`
|
||||
Price int `json:"price" v:"required|min:0" dc:"价格(分为单位)"`
|
||||
Sort int `json:"sort" v:"required|min:0" dc:"排序"`
|
||||
Status consts.AssetSkuStatusType `json:"status" v:"required|in:1,0" dc:"状态"`
|
||||
Status consts.AssetSkuStatus `json:"status" v:"required|in:1,0" dc:"状态"`
|
||||
UnlimitedStock bool `json:"unlimitedStock" v:"required" dc:"是否无库存限制"`
|
||||
StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式"`
|
||||
CategoryId int64 `json:"categoryId" dc:"分类ID"`
|
||||
@@ -49,7 +49,7 @@ type UpdateAssetSkuReq struct {
|
||||
Price int `json:"price" dc:"价格(分为单位)"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
Stock int `json:"stock" dc:"库存数量"`
|
||||
Status consts.AssetSkuStatusType `json:"status" dc:"状态"`
|
||||
Status consts.AssetSkuStatus `json:"status" dc:"状态"`
|
||||
}
|
||||
|
||||
// DeleteAssetSkuReq 删除SKU请求
|
||||
@@ -86,13 +86,13 @@ type GetAssetSkuRes struct {
|
||||
type ListAssetSkuReq struct {
|
||||
g.Meta `path:"/listAssetSkus" method:"get" tags:"SKU管理" summary:"获取SKU列表" dc:"分页查询SKU列表,支持多条件筛选"`
|
||||
*beans.Page
|
||||
Id int64 `json:"id" dc:"SKU ID"`
|
||||
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
|
||||
Status consts.AssetSkuStatusType `json:"status" dc:"状态"`
|
||||
Keyword string `json:"keyword" dc:"关键词搜索"`
|
||||
MinPrice int `json:"minPrice" dc:"最低价格"`
|
||||
MaxPrice int `json:"maxPrice" dc:"最高价格"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
Id int64 `json:"id" dc:"SKU ID"`
|
||||
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
|
||||
Status consts.AssetSkuStatus `json:"status" dc:"状态"`
|
||||
Keyword string `json:"keyword" dc:"关键词搜索"`
|
||||
MinPrice int `json:"minPrice" dc:"最低价格"`
|
||||
MaxPrice int `json:"maxPrice" dc:"最高价格"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
}
|
||||
|
||||
// ListAssetSkuRes 获取SKU列表响应
|
||||
@@ -102,8 +102,8 @@ type ListAssetSkuRes struct {
|
||||
}
|
||||
|
||||
type AssetSkuItem struct {
|
||||
Id int64 `json:"id"` // SKU ID
|
||||
AssetId int64 `json:"assetId"`
|
||||
Id int64 `json:"id,string"` // SKU ID
|
||||
AssetId int64 `json:"assetId,string"`
|
||||
AssetName string `json:"assetName"` // 资产名称
|
||||
SkuName string `json:"skuName"` // SKU名称
|
||||
SpecsCount int `json:"specsCount"` // 规格数量
|
||||
@@ -113,8 +113,9 @@ type AssetSkuItem struct {
|
||||
UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制
|
||||
Stock int `json:"stock"` // 库存数量
|
||||
Sort int `json:"sort"` // 排序
|
||||
Status consts.AssetSkuStatusType `json:"status"` // 状态:active/inactive/disabled
|
||||
Status consts.AssetSkuStatus `json:"status"` // 状态:active/inactive/disabled
|
||||
StockMode stock.StockMode `json:"stockMode"` // 库存管理模式:1-明细模式 2-批次模式
|
||||
ImageURL string `json:"imageUrl"` // SKU主图
|
||||
CreatedAt *gtime.Time `json:"createdAt"` // 创建时间
|
||||
UpdatedAt *gtime.Time `json:"updatedAt"` // 更新时间
|
||||
}
|
||||
|
||||
@@ -12,15 +12,15 @@ import (
|
||||
// CreateCategoryReq 创建分类请求
|
||||
type CreateCategoryReq struct {
|
||||
g.Meta `path:"/createCategory" method:"post" tags:"分类管理" summary:"创建分类" dc:"创建新的分类"`
|
||||
Name string `json:"name" v:"required" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
Status consts.CategoryStatusType `json:"status" v:"in:1,0" default:"1" dc:"状态:1启用0禁用"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
Name string `json:"name" v:"required" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
Status consts.CategoryStatus `json:"status" v:"in:1,0" default:"1" dc:"状态:1启用0禁用"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
}
|
||||
|
||||
// CreateCategoryRes 创建分类响应
|
||||
@@ -31,21 +31,21 @@ type CreateCategoryRes struct {
|
||||
// UpdateCategoryReq 更新分类请求
|
||||
type UpdateCategoryReq struct {
|
||||
g.Meta `path:"/updateCategory" method:"put" tags:"分类管理" summary:"更新分类" dc:"更新分类信息"`
|
||||
Id int64 `json:"id" v:"required" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
Status consts.CategoryStatusType `json:"status" dc:"状态:1启用0禁用"`
|
||||
Id int64 `json:"id" v:"required" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
Status consts.CategoryStatus `json:"status" dc:"状态:1启用0禁用"`
|
||||
}
|
||||
|
||||
// UpdateCategoryStatusReq 更新分类状态请求
|
||||
type UpdateCategoryStatusReq struct {
|
||||
g.Meta `path:"/updateCategoryStatus" method:"put" tags:"分类管理" summary:"更新分类状态" dc:"更新分类状态"`
|
||||
Id int64 `json:"id" v:"required" dc:"分类ID"`
|
||||
Status consts.CategoryStatusType `json:"status" v:"in:1,0" dc:"状态:1启用0禁用"`
|
||||
Id int64 `json:"id" v:"required" dc:"分类ID"`
|
||||
Status consts.CategoryStatus `json:"status" v:"in:1,0" dc:"状态:1启用0禁用"`
|
||||
}
|
||||
|
||||
// DeleteCategoryReq 删除分类请求
|
||||
@@ -67,26 +67,26 @@ type GetCategoryTreeRes struct {
|
||||
|
||||
// CategoryTreeNode 分类树节点
|
||||
type CategoryTreeNode struct {
|
||||
Id int64 `json:"id,string" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
Type string `json:"type" dc:"分类类型"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Status consts.CategoryStatusType `json:"status" dc:"状态"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
Children []*CategoryTreeNode `json:"children" dc:"子分类"`
|
||||
Id int64 `json:"id,string" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
Type string `json:"type" dc:"分类类型"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Status consts.CategoryStatus `json:"status" dc:"状态"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
Children []*CategoryTreeNode `json:"children" dc:"子分类"`
|
||||
}
|
||||
|
||||
// ListCategoryReq 获取分类列表请求
|
||||
type ListCategoryReq struct {
|
||||
g.Meta `path:"/listCategories" method:"get" tags:"分类管理" summary:"获取分类列表" dc:"获取分类列表"`
|
||||
*beans.Page
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
Status consts.CategoryStatusType `json:"status" dc:"状态:1启用0禁用"`
|
||||
Keyword string `json:"keyword" dc:"关键词搜索"`
|
||||
ParentId int64 `json:"parentId" dc:"父分类ID"`
|
||||
Status consts.CategoryStatus `json:"status" dc:"状态:1启用0禁用"`
|
||||
Keyword string `json:"keyword" dc:"关键词搜索"`
|
||||
}
|
||||
|
||||
// ListCategoryRes 获取分类列表响应
|
||||
@@ -103,18 +103,18 @@ type GetCategoryReq struct {
|
||||
|
||||
// GetCategoryRes 获取分类详情响应
|
||||
type GetCategoryRes struct {
|
||||
Id int64 `json:"id,string" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId,string" dc:"父分类ID"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
Status consts.CategoryStatusType `json:"status" dc:"状态:1启用0禁用"`
|
||||
Creator string `json:"creator" dc:"创建人"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
Updater string `json:"updater" dc:"更新人"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
Id int64 `json:"id,string" dc:"分类ID"`
|
||||
Name string `json:"name" dc:"分类名称"`
|
||||
ParentId int64 `json:"parentId,string" dc:"父分类ID"`
|
||||
Path string `json:"path" dc:"分类路径"`
|
||||
Level int `json:"level" dc:"分类层级"`
|
||||
IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"`
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
Image string `json:"image" dc:"分类图片"`
|
||||
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
|
||||
Status consts.CategoryStatus `json:"status" dc:"状态:1启用0禁用"`
|
||||
Creator string `json:"creator" dc:"创建人"`
|
||||
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
||||
Updater string `json:"updater" dc:"更新人"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
|
||||
}
|
||||
|
||||
@@ -3,24 +3,11 @@ package dto
|
||||
import (
|
||||
"assets/consts/stock"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
// CommonResp 通用响应
|
||||
type CommonResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Message string `json:"message"` // 消息
|
||||
}
|
||||
|
||||
// --- 批次管理API相关结构 ---
|
||||
|
||||
// CreateBatchReq 创建批次请求
|
||||
type CreateBatchReq struct {
|
||||
g.Meta `path:"/createBatch" method:"post" tags:"库存批次管理" summary:"创建批次" dc:"创建新的库存批次"`
|
||||
|
||||
// CreateSockBatchReq 创建批次请求
|
||||
type CreateSockBatchReq struct {
|
||||
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
|
||||
AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"SKU ID"`
|
||||
BatchNo string `json:"batchNo" v:"required" dc:"批次号"`
|
||||
@@ -33,58 +20,13 @@ type CreateBatchReq struct {
|
||||
ExpiryWarningDate *gtime.Time `json:"expiryWarningDate" dc:"临期预警时间(格式:2006-01-02)"`
|
||||
}
|
||||
|
||||
// CreateBatchRes 创建批次响应
|
||||
type CreateBatchRes struct {
|
||||
Id *bson.ObjectID `json:"id"` // 批次ID
|
||||
}
|
||||
|
||||
// UpdateBatchReq 更新批次请求
|
||||
type UpdateBatchReq struct {
|
||||
g.Meta `path:"/updateBatch" method:"put" tags:"库存批次管理" summary:"更新批次" dc:"更新批次信息"`
|
||||
|
||||
type UpdateSockBatchReq struct {
|
||||
Id int64 `json:"id" v:"required" dc:"批次ID"`
|
||||
BatchQty int `json:"batchQty" v:"required|min:1" dc:"批次数量"`
|
||||
AvailableQty int `json:"availableQty" v:"required|min:1" dc:"可用数量"`
|
||||
}
|
||||
|
||||
// DeleteBatchReq 删除批次请求
|
||||
type DeleteBatchReq struct {
|
||||
g.Meta `path:"/deleteBatch" method:"delete" tags:"库存批次管理" summary:"删除批次" dc:"删除批次"`
|
||||
Id *bson.ObjectID `json:"id" v:"required" dc:"批次ID"`
|
||||
}
|
||||
|
||||
// GetBatchReq 获取批次详情请求
|
||||
type GetBatchReq struct {
|
||||
g.Meta `path:"/getBatch" method:"get" tags:"库存批次管理" summary:"获取批次详情" dc:"获取批次详情"`
|
||||
Id *bson.ObjectID `json:"id" v:"required" dc:"批次ID"`
|
||||
}
|
||||
|
||||
// GetBatchRes 获取批次详情响应
|
||||
type GetBatchRes struct {
|
||||
Id *bson.ObjectID `json:"id"`
|
||||
AssetId *bson.ObjectID `json:"assetId"`
|
||||
AssetSkuId *bson.ObjectID `json:"assetSkuId"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
BatchQty int `json:"batchQty"`
|
||||
AvailableQty int `json:"availableQty"`
|
||||
Metadata []map[string]interface{} `json:"metadata"`
|
||||
Status stock.BatchStatus `json:"status"`
|
||||
ProductionDate *gtime.Time `json:"productionDate"`
|
||||
ExpiryDate *gtime.Time `json:"expiryDate"`
|
||||
ExpiryWarningDate *gtime.Time `json:"expiryWarningDate"`
|
||||
}
|
||||
|
||||
// ListBatchReq 获取批次列表请求
|
||||
type ListBatchReq struct {
|
||||
g.Meta `path:"/listBatches" method:"get" tags:"库存批次管理" summary:"获取批次列表" dc:"分页查询批次列表"`
|
||||
*beans.Page
|
||||
OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"`
|
||||
AssetId *bson.ObjectID `json:"assetId" dc:"资产ID"`
|
||||
AssetSkuId *bson.ObjectID `json:"assetSkuId" dc:"SKU ID"`
|
||||
}
|
||||
|
||||
// ListBatchRes 获取批次列表响应
|
||||
type ListBatchRes struct {
|
||||
List []GetBatchRes `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
type GetSockBatchReq struct {
|
||||
Id int64 `json:"id" v:"required" dc:"批次ID"`
|
||||
BatchNo string `json:"batchNo" dc:"批次号"`
|
||||
}
|
||||
|
||||
@@ -4,64 +4,25 @@ import (
|
||||
"assets/consts/stock"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
// GetStockDetailsReq 获取库存明细详情请求
|
||||
type GetStockDetailsReq struct {
|
||||
g.Meta `path:"/getStockDetails" method:"get" tags:"库存明细管理" summary:"获取库存明细详情" dc:"获取库存明细详情"`
|
||||
Id *bson.ObjectID `json:"id" v:"required" dc:"库存明细ID"`
|
||||
// CreateSockDetailsReq 创建明细请求
|
||||
type CreateSockDetailsReq struct {
|
||||
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
|
||||
AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"SKU ID"`
|
||||
Status stock.StockStatus `json:"status" dc:"状态"`
|
||||
Metadata []map[string]interface{} `json:"metadata" dc:"元数据"`
|
||||
}
|
||||
|
||||
// GetStockDetailsRes 获取库存明细详情响应
|
||||
type GetStockDetailsRes struct {
|
||||
Id *bson.ObjectID `json:"id"`
|
||||
AssetId *bson.ObjectID `json:"assetId"`
|
||||
AssetSkuId *bson.ObjectID `json:"assetSkuId"`
|
||||
Status stock.StockStatus `json:"status"`
|
||||
OrderId *bson.ObjectID `json:"orderId"`
|
||||
LockExpire string `json:"lockExpire"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
TokenId string `json:"tokenId"`
|
||||
AssignedChannel string `json:"assignedChannel"`
|
||||
ChannelSKU string `json:"channelSku"`
|
||||
AllocatedAt string `json:"allocatedAt"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
type DeleteSockDetailsReq struct {
|
||||
Id int64 `json:"Id" v:"required" dc:"库存明细ID"`
|
||||
}
|
||||
|
||||
// ListStockDetailsReq 获取库存明细列表请求
|
||||
type ListStockDetailsReq struct {
|
||||
g.Meta `path:"/listStockDetails" method:"get" tags:"库存明细管理" summary:"获取库存明细列表" dc:"分页查询库存明细列表,支持多条件筛选"`
|
||||
|
||||
type GetSockDetailsReq struct {
|
||||
*beans.Page
|
||||
OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"`
|
||||
Id int64 `json:"id" dc:"库存明细ID"`
|
||||
AssetId int64 `json:"assetId" dc:"资产ID"`
|
||||
AssetSkuId int64 `json:"assetSkuId" dc:"SKU ID"`
|
||||
CategoryPath string `json:"categoryPath" dc:"分类路径"`
|
||||
Status stock.StockStatus `json:"status" dc:"状态"`
|
||||
}
|
||||
|
||||
// ListStockDetailsRes 获取库存明细列表响应
|
||||
type ListStockDetailsRes struct {
|
||||
List []*StockDetailsListItem `json:"list" dc:"库存明细列表"`
|
||||
Total int64 `json:"total" dc:"总数"`
|
||||
}
|
||||
|
||||
// StockDetailsListItem 库存明细列表项
|
||||
type StockDetailsListItem struct {
|
||||
Id *bson.ObjectID `json:"id"`
|
||||
AssetId *bson.ObjectID `json:"assetId"`
|
||||
AssetSkuId *bson.ObjectID `json:"assetSkuId"`
|
||||
Status stock.StockStatus `json:"status"`
|
||||
OrderId *bson.ObjectID `json:"orderId"`
|
||||
LockExpire string `json:"lockExpire"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
TokenId *bson.ObjectID `json:"tokenId"`
|
||||
AssignedChannel string `json:"assignedChannel"`
|
||||
ChannelSKU string `json:"channelSku"`
|
||||
AllocatedAt string `json:"allocatedAt"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ type StockPublishMessage struct {
|
||||
StockCount int `json:"stockCount"`
|
||||
OperationType string `json:"operationType"`
|
||||
Metadata []map[string]interface{} `json:"metadata"`
|
||||
StockId string `json:"stockId"`
|
||||
StockMode int `json:"stockMode"`
|
||||
StockId int64 `json:"stockId"`
|
||||
StockMode stock.StockMode `json:"stockMode"`
|
||||
BatchNo string `json:"batchNo"`
|
||||
ProductionDate *gtime.Time `json:"productionDate"`
|
||||
ExpiryDate *gtime.Time `json:"expiryDate"`
|
||||
|
||||
@@ -3,9 +3,9 @@ package entity
|
||||
import (
|
||||
consts "assets/consts/asset"
|
||||
"assets/consts/stock"
|
||||
"assets/model/config"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
@@ -59,29 +59,29 @@ var AssetCol = assetCol{
|
||||
type Asset struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
// 基础信息
|
||||
Name string `orm:"name" json:"name" description:"资产名称"`
|
||||
Description string `orm:"description" json:"description" description:"资产描述"`
|
||||
Type consts.AssetType `orm:"type" json:"type" description:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `orm:"category_id" json:"categoryId" description:"分类ID"`
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath" description:"分类路径"`
|
||||
ImageURL string `orm:"image_url" json:"imageUrl" description:"主图URL"`
|
||||
Images []string `orm:"images" json:"images" description:"图片列表(JSONB)"`
|
||||
Status consts.AssetStatusType `orm:"status" json:"status" description:"资产状态:1启用/0停用"`
|
||||
BasePrice int `orm:"base_price" json:"basePrice" description:"基础价格(分为单位)"`
|
||||
Currency string `orm:"currency" json:"currency" description:"货币单位,默认CNY"`
|
||||
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock" description:"是否无库存限制"`
|
||||
StockMode stock.StockMode `orm:"stock_mode" json:"stockMode" description:"库存管理模式:1-明细模式 2-批次模式"`
|
||||
OnlineTime *gtime.Time `orm:"online_time" json:"onlineTime,omitempty" description:"上线时间"` // 上线和下线时间配置(由定时任务处理资产状态)
|
||||
OfflineTime *gtime.Time `orm:"offline_time" json:"offlineTime,omitempty" description:"下线时间"` // 上线和下线时间配置(由定时任务处理资产状态)
|
||||
Name string `orm:"name" json:"name" description:"资产名称"`
|
||||
Description string `orm:"description" json:"description" description:"资产描述"`
|
||||
Type consts.AssetType `orm:"type" json:"type" description:"资产类型:physical实物/virtual虚拟/service服务"`
|
||||
CategoryId int64 `orm:"category_id" json:"categoryId,string" description:"分类ID"`
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath" description:"分类路径"`
|
||||
ImageURL string `orm:"image_url" json:"imageUrl" description:"主图URL"`
|
||||
Images []string `orm:"images" json:"images" description:"图片列表(JSONB)"`
|
||||
Status consts.AssetStatus `orm:"status" json:"status" description:"资产状态:1启用/0停用"`
|
||||
BasePrice int `orm:"base_price" json:"basePrice" description:"基础价格(分为单位)"`
|
||||
Currency string `orm:"currency" json:"currency" description:"货币单位,默认CNY"`
|
||||
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock" description:"是否无库存限制"`
|
||||
StockMode stock.StockMode `orm:"stock_mode" json:"stockMode" description:"库存管理模式:1-明细模式 2-批次模式"`
|
||||
OnlineTime *gtime.Time `orm:"online_time" json:"onlineTime,omitempty" description:"上线时间"` // 上线和下线时间配置(由定时任务处理资产状态)
|
||||
OfflineTime *gtime.Time `orm:"offline_time" json:"offlineTime,omitempty" description:"下线时间"` // 上线和下线时间配置(由定时任务处理资产状态)
|
||||
|
||||
// 类型专用配置 - 实物资产配置(JSONB)
|
||||
PhysicalAssetConfig *gjson.Json `orm:"physical_asset_config" json:"physicalAssetConfig" description:"实物资产配置(JSONB)"`
|
||||
PhysicalAssetConfig *config.PhysicalAssetConfig `orm:"physical_asset_config" json:"physicalAssetConfig" description:"实物资产配置(JSONB)"`
|
||||
// 类型专用配置 - 服务资产配置(JSONB)
|
||||
ServiceAssetConfig *gjson.Json `orm:"service_asset_config" json:"serviceAssetConfig" description:"服务资产配置(JSONB)"`
|
||||
ServiceAssetConfig *config.ServiceAssetConfig `orm:"service_asset_config" json:"serviceAssetConfig" description:"服务资产配置(JSONB)"`
|
||||
// 类型专用配置 - 虚拟资产配置(JSONB)
|
||||
VirtualAssetConfig *gjson.Json `orm:"virtual_asset_config" json:"virtualAssetConfig" description:"虚拟资产配置(JSONB)"`
|
||||
VirtualAssetConfig *config.VirtualAssetConfig `orm:"virtual_asset_config" json:"virtualAssetConfig" description:"虚拟资产配置(JSONB)"`
|
||||
// 扩展字段(JSONB)
|
||||
Metadata []gjson.Json `orm:"metadata" json:"metadata" description:"动态元数据(JSONB)"`
|
||||
Metadata []map[string]interface{} `orm:"metadata" json:"metadata" description:"动态元数据(JSONB)"`
|
||||
|
||||
TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType" description:"租户模块类型"`
|
||||
}
|
||||
|
||||
@@ -3,77 +3,75 @@ package entity
|
||||
import (
|
||||
consts "assets/consts/asset"
|
||||
"assets/consts/stock"
|
||||
"assets/model/config"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
)
|
||||
|
||||
type assetSkuCol struct {
|
||||
beans.SQLBaseCol
|
||||
AssetId string
|
||||
AssetName string
|
||||
SkuName string
|
||||
ImageURL string
|
||||
SpecValues string
|
||||
Price string
|
||||
UnlimitedStock string
|
||||
Stock string
|
||||
SpecsCount string
|
||||
SpecsUnit string
|
||||
Sort string
|
||||
Status string
|
||||
StockMode string
|
||||
CategoryId string
|
||||
CategoryPath string
|
||||
CapacityUnitType string
|
||||
Capacity string
|
||||
AssetId string
|
||||
AssetName string
|
||||
SkuName string
|
||||
ImageURL string
|
||||
SpecValues string
|
||||
Price string
|
||||
UnlimitedStock string
|
||||
Stock string
|
||||
SpecsCount string
|
||||
SpecsUnit string
|
||||
Sort string
|
||||
Status string
|
||||
StockMode string
|
||||
CategoryId string
|
||||
CategoryPath string
|
||||
//CapacityUnitType string
|
||||
//Capacity string
|
||||
TenantModuleType string
|
||||
}
|
||||
|
||||
var AssetSkuCol = assetSkuCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
AssetId: "asset_id",
|
||||
AssetName: "asset_name",
|
||||
SkuName: "sku_name",
|
||||
ImageURL: "image_url",
|
||||
SpecValues: "spec_values",
|
||||
Price: "price",
|
||||
UnlimitedStock: "unlimited_stock",
|
||||
Stock: "stock",
|
||||
SpecsCount: "specs_count",
|
||||
SpecsUnit: "specs_unit",
|
||||
Sort: "sort",
|
||||
Status: "status",
|
||||
StockMode: "stock_mode",
|
||||
CategoryId: "category_id",
|
||||
CategoryPath: "category_path",
|
||||
CapacityUnitType: "capacity_unit_type",
|
||||
Capacity: "capacity",
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
AssetId: "asset_id",
|
||||
AssetName: "asset_name",
|
||||
SkuName: "sku_name",
|
||||
ImageURL: "image_url",
|
||||
SpecValues: "spec_values",
|
||||
Price: "price",
|
||||
UnlimitedStock: "unlimited_stock",
|
||||
Stock: "stock",
|
||||
SpecsCount: "specs_count",
|
||||
SpecsUnit: "specs_unit",
|
||||
Sort: "sort",
|
||||
Status: "status",
|
||||
StockMode: "stock_mode",
|
||||
CategoryId: "category_id",
|
||||
CategoryPath: "category_path",
|
||||
//CapacityUnitType: "capacity_unit_type",
|
||||
//Capacity: "capacity",
|
||||
TenantModuleType: "tenant_module_type",
|
||||
}
|
||||
|
||||
// AssetSku 资产SKU实体
|
||||
type AssetSku struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
|
||||
AssetName string `orm:"asset_name" json:"assetName"` // 资产名称
|
||||
SkuName string `orm:"sku_name" json:"skuName"` // SKU名称
|
||||
ImageURL string `orm:"image_url,omitempty" json:"imageUrl"` // SKU主图
|
||||
SpecValues []gjson.Json `orm:"spec_values" json:"specValues"` // 规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"}
|
||||
Price int `orm:"price" json:"price"` // 价格(分为单位)
|
||||
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock"` // 是否无库存限制
|
||||
Stock int `orm:"stock" json:"stock"` // 库存数量
|
||||
SpecsCount int `orm:"specs_count" json:"specsCount"` // 规格数量
|
||||
SpecsUnit *gjson.Json `orm:"specs_unit" json:"specsUnit"` // 规格单位 SpecsUnitKeyValue
|
||||
Sort int `orm:"sort" json:"sort"` // 排序
|
||||
Status consts.AssetSkuStatusType `orm:"status" json:"status"` // 状态:active/inactive/disabled
|
||||
StockMode stock.StockMode `orm:"stock_mode" json:"stockMode"` // 库存管理模式:1-明细模式 2-批次模式
|
||||
CategoryId int64 `orm:"category_id" json:"categoryId"` // 分类ID
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
|
||||
CapacityUnitType stock.CapacityUnitType `orm:"capacity_unit_type" json:"capacityUnitType"` // 容量单位类型
|
||||
Capacity config.Capacity `orm:"capacity" json:"capacity"` // 容量
|
||||
TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType"` // 租户模块类型
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
|
||||
AssetName string `orm:"asset_name" json:"assetName"` // 资产名称
|
||||
SkuName string `orm:"sku_name" json:"skuName"` // SKU名称
|
||||
ImageURL string `orm:"image_url,omitempty" json:"imageUrl"` // SKU主图
|
||||
SpecValues []map[string]interface{} `orm:"spec_values" json:"specValues"` // 规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"}
|
||||
Price int `orm:"price" json:"price"` // 价格(分为单位)
|
||||
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock"` // 是否无库存限制
|
||||
Stock int `orm:"stock" json:"stock"` // 库存数量
|
||||
SpecsCount int `orm:"specs_count" json:"specsCount"` // 规格数量
|
||||
SpecsUnit *SpecsUnitKeyValue `orm:"specs_unit" json:"specsUnit"` // 规格单位 SpecsUnitKeyValue
|
||||
Sort int `orm:"sort" json:"sort"` // 排序
|
||||
Status consts.AssetSkuStatus `orm:"status" json:"status"` // 状态:active/inactive/disabled
|
||||
StockMode stock.StockMode `orm:"stock_mode" json:"stockMode"` // 库存管理模式:1-明细模式 2-批次模式
|
||||
CategoryId int64 `orm:"category_id" json:"categoryId"` // 分类ID
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
|
||||
//CapacityUnitType stock.CapacityUnitType `orm:"capacity_unit_type" json:"capacityUnitType"` // 容量单位类型
|
||||
//Capacity int `orm:"capacity" json:"capacity"` // 容量
|
||||
TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType"` // 租户模块类型
|
||||
}
|
||||
|
||||
type SpecsUnitKeyValue struct {
|
||||
|
||||
@@ -35,15 +35,15 @@ var CategoryCol = categoryCol{
|
||||
// Category 分类实体
|
||||
type Category struct {
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
Name string `orm:"name" json:"name"` // 分类名称
|
||||
ParentId int64 `orm:"parent_id" json:"parentId"` // 父分类ID,为空表示根分类
|
||||
Path string `orm:"path" json:"path"` // 分类路径,如:/root/parent/child
|
||||
Level int `orm:"level" json:"level"` // 分类层级
|
||||
IsLeafNode *bool `orm:"is_leaf_node" json:"isLeafNode"` // 是叶子节点
|
||||
Sort int `orm:"sort" json:"sort"` // 排序
|
||||
Image string `orm:"image" json:"image"` // 分类图片
|
||||
Status consts.CategoryStatusType `orm:"status" json:"status"` // 状态:1启用/0禁用
|
||||
Attrs []CategoryAttr `orm:"attrs" json:"attrs,omitempty"` // 分类属性 CategoryAttr
|
||||
Name string `orm:"name" json:"name"` // 分类名称
|
||||
ParentId int64 `orm:"parent_id" json:"parentId"` // 父分类ID,为空表示根分类
|
||||
Path string `orm:"path" json:"path"` // 分类路径,如:/root/parent/child
|
||||
Level int `orm:"level" json:"level"` // 分类层级
|
||||
IsLeafNode *bool `orm:"is_leaf_node" json:"isLeafNode"` // 是叶子节点
|
||||
Sort int `orm:"sort" json:"sort"` // 排序
|
||||
Image string `orm:"image" json:"image"` // 分类图片
|
||||
Status consts.CategoryStatus `orm:"status" json:"status"` // 状态:1启用/0禁用
|
||||
Attrs []CategoryAttr `orm:"attrs" json:"attrs,omitempty"` // 分类属性 CategoryAttr
|
||||
// 使用场景说明:
|
||||
// 1. 商品分类属性:为该分类下的商品定义标准化的属性模板,如服装分类可定义尺寸、颜色、材质等属性
|
||||
// 2. 服务分类属性:为服务类目定义特性参数,如咨询服务可定义服务时长、服务方式、专业领域等
|
||||
|
||||
@@ -1,48 +1,80 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type stockBatchCol struct {
|
||||
beans.SQLBaseCol
|
||||
AssetId string
|
||||
AssetSkuId string
|
||||
BatchNo string
|
||||
BatchQty string
|
||||
AvailableQty string
|
||||
Metadata string
|
||||
Status string
|
||||
OrderId string
|
||||
AssignedChannel string
|
||||
ChannelSKU string
|
||||
ChannelMetadata string
|
||||
AllocatedAt string
|
||||
ProductionDate string
|
||||
ExpiryDate string
|
||||
ExpiryWarningDate string
|
||||
CategoryPath string
|
||||
}
|
||||
|
||||
var StockBatchCol = stockBatchCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
AssetId: "asset_id",
|
||||
AssetSkuId: "asset_sku_id",
|
||||
BatchNo: "batch_no",
|
||||
BatchQty: "batch_qty",
|
||||
AvailableQty: "available_qty",
|
||||
Metadata: "metadata",
|
||||
Status: "status",
|
||||
OrderId: "order_id",
|
||||
AssignedChannel: "assigned_channel",
|
||||
ChannelSKU: "channel_sku",
|
||||
ChannelMetadata: "channel_metadata",
|
||||
AllocatedAt: "allocated_at",
|
||||
ProductionDate: "production_date",
|
||||
ExpiryDate: "expiry_date",
|
||||
ExpiryWarningDate: "expiry_warning_date",
|
||||
CategoryPath: "category_path",
|
||||
}
|
||||
|
||||
// StockBatch 库存批次实体(用于批次管理模式)
|
||||
type StockBatch struct {
|
||||
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
|
||||
|
||||
AssetID *bson.ObjectID `bson:"assetId" json:"assetId"` // 关联资产ID
|
||||
AssetSkuID *bson.ObjectID `bson:"assetSkuId" json:"assetSkuId"` // 关联资产SKU ID
|
||||
BatchNo string `bson:"batchNo" json:"batchNo"` // 批次号
|
||||
BatchQty int `bson:"batchQty" json:"batchQty"` // 批次总数量(入库后不可变)
|
||||
AvailableQty int `bson:"availableQty" json:"availableQty"` // 可用数量(实时变化)
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
|
||||
AssetSkuId int64 `orm:"asset_sku_id" json:"assetSkuId"` // 关联资产SKU ID
|
||||
BatchNo string `orm:"batch_no" json:"batchNo"` // 批次号
|
||||
BatchQty int `orm:"batch_qty" json:"batchQty"` // 批次总数量(入库后不可变)
|
||||
AvailableQty int `orm:"available_qty" json:"availableQty"` // 可用数量(实时变化)
|
||||
|
||||
// 批次元数据
|
||||
Metadata []map[string]interface{} `bson:"metadata" json:"metadata"` // 其他元数据
|
||||
Metadata []map[string]interface{} `orm:"metadata" json:"metadata"` // 其他元数据
|
||||
|
||||
// 状态
|
||||
Status *stock.BatchStatus `bson:"status" json:"status"` // 批次状态
|
||||
Status stock.BatchStatus `orm:"status" json:"status"` // 批次状态
|
||||
// 锁定数量 = BatchQty - AvailableQty
|
||||
|
||||
// 订单关联
|
||||
OrderID *bson.ObjectID `bson:"orderId" json:"orderId"` // 关联订单ID(如果有)
|
||||
OrderID int64 `orm:"order_id" json:"orderId"` // 关联订单ID(如果有)
|
||||
|
||||
// 渠道分配信息
|
||||
AssignedChannel string `bson:"assignedChannel" json:"assignedChannel"` // 分配的销售渠道
|
||||
ChannelSKU string `bson:"channelSku" json:"channelSku"` // 渠道商品SKU
|
||||
ChannelMetadata map[string]interface{} `bson:"channelMetadata" json:"channelMetadata"` // 渠道专属数据
|
||||
AllocatedAt *gtime.Time `bson:"allocatedAt" json:"allocatedAt"` // 分配时间
|
||||
AssignedChannel string `orm:"assigned_channel" json:"assignedChannel"` // 分配的销售渠道
|
||||
ChannelSKU string `orm:"channel_sku" json:"channelSku"` // 渠道商品SKU
|
||||
ChannelMetadata map[string]interface{} `orm:"channel_metadata" json:"channelMetadata"` // 渠道专属数据
|
||||
AllocatedAt *gtime.Time `orm:"allocated_at" json:"allocatedAt"` // 分配时间
|
||||
|
||||
// 临期管理
|
||||
ProductionDate *gtime.Time `bson:"productionDate" json:"productionDate"` // 生产日期
|
||||
ExpiryDate *gtime.Time `bson:"expiryDate" json:"expiryDate"` // 过期日期
|
||||
ExpiryWarningDate *gtime.Time `bson:"expiryWarningDate" json:"expiryWarningDate"` // 临期预警时间(有过期日期时建议填写)
|
||||
CategoryPath string `bson:"categoryPath" json:"categoryPath"` // 分类路径
|
||||
}
|
||||
|
||||
// CollectionName 获取集合名称
|
||||
func (StockBatch) CollectionName() string {
|
||||
return public.StockBatchCollection
|
||||
ProductionDate *gtime.Time `orm:"production_date" json:"productionDate"` // 生产日期
|
||||
ExpiryDate *gtime.Time `orm:"expiry_date" json:"expiryDate"` // 过期日期
|
||||
ExpiryWarningDate *gtime.Time `orm:"expiry_warning_date" json:"expiryWarningDate"` // 临期预警时间(有过期日期时建议填写)
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
|
||||
}
|
||||
|
||||
@@ -1,35 +1,59 @@
|
||||
package entity
|
||||
|
||||
import (
|
||||
"assets/consts/public"
|
||||
"assets/consts/stock"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type stockDetailsCol struct {
|
||||
beans.SQLBaseCol
|
||||
AssetId string
|
||||
AssetSkuId string
|
||||
Status string
|
||||
OrderId string
|
||||
LockExpire string
|
||||
Metadata string
|
||||
TokenId string
|
||||
AssignedChannel string
|
||||
ChannelSKU string
|
||||
ChannelMetadata string
|
||||
AllocatedAt string
|
||||
CategoryPath string
|
||||
}
|
||||
|
||||
var StockDetailsCol = stockDetailsCol{
|
||||
SQLBaseCol: beans.DefSQLBaseCol,
|
||||
AssetId: "asset_id",
|
||||
AssetSkuId: "asset_sku_id",
|
||||
Status: "status",
|
||||
OrderId: "order_id",
|
||||
LockExpire: "lock_expire",
|
||||
Metadata: "metadata",
|
||||
TokenId: "token_id",
|
||||
AssignedChannel: "assigned_channel",
|
||||
ChannelSKU: "channel_sku",
|
||||
ChannelMetadata: "channel_metadata",
|
||||
AllocatedAt: "allocated_at",
|
||||
CategoryPath: "category_path",
|
||||
}
|
||||
|
||||
// StockDetails 库存实体,每一件商品都有独立ID,用于后期做区块链虚拟资产
|
||||
type StockDetails struct {
|
||||
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted
|
||||
|
||||
AssetId int64 `bson:"assetId" json:"assetId"` // 关联资产ID
|
||||
AssetSkuId int64 `bson:"assetSkuId" json:"assetSkuId"` // 关联资产SKU ID
|
||||
Status stock.StockStatus `bson:"status" json:"status"` // 库存状态
|
||||
OrderId *bson.ObjectID `bson:"orderId" json:"orderId"` // 关联订单ID(如果有)
|
||||
LockExpire *gtime.Time `bson:"lockExpire" json:"lockExpire"` // 锁定过期时间
|
||||
Metadata []map[string]interface{} `bson:"metadata" json:"metadata"` // 其他元数据
|
||||
TokenId string `bson:"tokenId" json:"tokenId"` // 区块链TokenID(如果有)
|
||||
beans.SQLBaseDO `orm:",inherit"`
|
||||
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
|
||||
AssetSkuId int64 `orm:"asset_sku_id" json:"assetSkuId"` // 关联资产SKU ID
|
||||
Status stock.StockStatus `orm:"status" json:"status"` // 库存状态
|
||||
OrderId int64 `orm:"order_id" json:"orderId"` // 关联订单ID(如果有)
|
||||
LockExpire *gtime.Time `orm:"lock_expire" json:"lockExpire"` // 锁定过期时间
|
||||
Metadata []map[string]interface{} `orm:"metadata" json:"metadata"` // 其他元数据
|
||||
TokenId string `orm:"token_id" json:"tokenId"` // 区块链TokenID(如果有)
|
||||
|
||||
// 渠道分配信息
|
||||
AssignedChannel string `bson:"assignedChannel" json:"assignedChannel"` // 分配的销售渠道
|
||||
ChannelSKU string `bson:"channelSku" json:"channelSku"` // 渠道商品SKU
|
||||
ChannelMetadata map[string]interface{} `bson:"channelMetadata" json:"channelMetadata"` // 渠道专属数据
|
||||
AllocatedAt *gtime.Time `bson:"allocatedAt" json:"allocatedAt"` // 分配时间
|
||||
CategoryPath string `bson:"categoryPath" json:"categoryPath"` // 分类路径
|
||||
}
|
||||
|
||||
// CollectionName 库存集合名称
|
||||
func (StockDetails) CollectionName() string {
|
||||
return public.StockDetailsCollection
|
||||
AssignedChannel string `orm:"assigned_channel" json:"assignedChannel"` // 分配的销售渠道
|
||||
ChannelSKU string `orm:"channel_sku" json:"channelSku"` // 渠道商品SKU
|
||||
ChannelMetadata map[string]interface{} `orm:"channel_metadata" json:"channelMetadata"` // 渠道专属数据
|
||||
AllocatedAt *gtime.Time `orm:"allocated_at" json:"allocatedAt"` // 分配时间
|
||||
CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ func (s *asset) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *dto.GetA
|
||||
if assetOne, err = dao.Asset.GetOne(ctx, req); err != nil {
|
||||
return
|
||||
}
|
||||
var assetListItem *dto.AssetItem
|
||||
if err = gconv.Struct(assetOne, assetListItem); err != nil {
|
||||
var assetListItem *entity.Asset
|
||||
if err = gconv.Struct(assetOne, &assetListItem); err != nil {
|
||||
return
|
||||
}
|
||||
getCategoryRes, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{
|
||||
@@ -93,7 +93,7 @@ func (s *asset) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *dto.GetA
|
||||
return
|
||||
}
|
||||
return &dto.GetAssetRes{
|
||||
AssetItem: assetListItem,
|
||||
Asset: assetListItem,
|
||||
CategoryName: getCategoryRes.Name,
|
||||
ImgAddressPrefix: minio.GetFileAddressPrefix(ctx),
|
||||
}, nil
|
||||
@@ -109,7 +109,7 @@ func (s *asset) GetAssetAndSku(ctx context.Context, req *dto.GetAssetAndSkuReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var assetListItem *dto.AssetItem
|
||||
var assetListItem *entity.Asset
|
||||
if err = gconv.Struct(assetOne, assetListItem); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func (s *asset) GetAssetAndSku(ctx context.Context, req *dto.GetAssetAndSkuReq)
|
||||
return
|
||||
}
|
||||
return &dto.GetAssetAndSkuRes{
|
||||
AssetItem: assetListItem,
|
||||
Asset: assetListItem,
|
||||
Skus: assetSkuListResItem,
|
||||
TenantModuleType: moduleType.Options,
|
||||
ImgAddressPrefix: minio.GetFileAddressPrefix(ctx),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
consts "assets/consts/asset"
|
||||
"assets/consts/public"
|
||||
dao "assets/dao/asset"
|
||||
dto "assets/model/dto/asset"
|
||||
@@ -10,7 +11,6 @@ import (
|
||||
"reflect"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
@@ -84,19 +84,18 @@ func (s *assetSku) parameterValidation(ctx context.Context, assetEntity *entity.
|
||||
specNoExist := true
|
||||
metadataList := make([]string, 0)
|
||||
// 验证,自定义属性传过来的全不全
|
||||
// TODO: Metadata类型从[]map[string]interface{}变为*gjson.Json,需要适配
|
||||
// if assetEntity.Metadata != nil {
|
||||
// for _, metadata := range assetEntity.Metadata {
|
||||
// attributeType := gconv.String(gconv.Map(metadata)["type"])
|
||||
// if attributeType == string(consts.AttributeTypeMultiSelect) {
|
||||
// metadataList = append(metadataList, attributeType)
|
||||
// }
|
||||
// }
|
||||
// if len(metadataList) != len(specValues) {
|
||||
// // 如果请求参数中不存在该键,则跳过
|
||||
// return errors.New("规格参数填写不完整")
|
||||
// }
|
||||
// }
|
||||
if assetEntity.Metadata != nil {
|
||||
for _, metadata := range assetEntity.Metadata {
|
||||
attributeType := gconv.String(gconv.Map(metadata)["type"])
|
||||
if attributeType == string(consts.AttributeTypeMultiSelect) {
|
||||
metadataList = append(metadataList, attributeType)
|
||||
}
|
||||
}
|
||||
if len(metadataList) != len(specValues) {
|
||||
// 如果请求参数中不存在该键,则跳过
|
||||
return errors.New("规格参数填写不完整")
|
||||
}
|
||||
}
|
||||
// 验证,自定义属性和sku名称重不重复
|
||||
for _, list := range list {
|
||||
if list.SkuName == skuName {
|
||||
@@ -155,7 +154,7 @@ func (s *assetSku) GetAssetSku(ctx context.Context, req *dto.GetAssetSkuReq) (re
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = utils.Struct(one, &res)
|
||||
err = gconv.Struct(one, &res)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -169,7 +168,7 @@ func (s *assetSku) ListAssetSkus(ctx context.Context, req *dto.ListAssetSkuReq)
|
||||
res = &dto.ListAssetSkuRes{
|
||||
Total: total,
|
||||
}
|
||||
err = utils.Struct(list, &res.List)
|
||||
err = gconv.Struct(list, &res.List)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func (s *CategoryService) GetOne(ctx context.Context, req *dto.GetCategoryReq) (
|
||||
}
|
||||
res := new(dto.GetCategoryRes)
|
||||
|
||||
if err = gconv.Scan(one, &res); err != nil {
|
||||
if err = gconv.Struct(one, &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/http"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
@@ -39,17 +41,25 @@ func (s *enum) GetSpecsUnit(ctx context.Context, req *dto.GetSpecsUnitReq) (res
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 使用简化的 RPC 调用方式 - 直接传 map 参数
|
||||
//dictData := &dto.GetDictRes{}
|
||||
//if err = message.CallRPC(ctx, "dictService.GetDictWithDataByType", map[string]interface{}{"dictType": gconv.String(req.AssetType)}, dictData); err != nil {
|
||||
// return
|
||||
//}
|
||||
//for _, v := range dictData.Values {
|
||||
// res.Options = append(res.Options, dto.KeyValue{
|
||||
// Key: v.DictValue,
|
||||
// Value: v.DictLabel,
|
||||
// })
|
||||
//}
|
||||
// 获取当前请求的 headers 并传递到下游
|
||||
headers := make(map[string]string)
|
||||
if r := g.RequestFromCtx(ctx); r != nil {
|
||||
for k, v := range r.Request.Header {
|
||||
if len(v) > 0 {
|
||||
headers[k] = v[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
dictData := &dto.GetDictRes{}
|
||||
if err = http.Get(ctx, "admin-go/api/v1/system/dict/data/getDictData", headers, &dictData, "dictType", gconv.String(req.AssetType)); err != nil {
|
||||
return
|
||||
}
|
||||
for _, v := range dictData.Values {
|
||||
res.Options = append(res.Options, dto.KeyValue{
|
||||
Key: v.DictValue,
|
||||
Value: v.DictLabel,
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,57 +4,48 @@
|
||||
// 注意:区别于PrivateStock的实物库存,批次库存是逻辑概念,不记录物理位置
|
||||
package service
|
||||
|
||||
import (
|
||||
dao "assets/dao/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/utils"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type stockBatch struct{}
|
||||
|
||||
// StockBatch 批次服务
|
||||
var StockBatch = new(stockBatch)
|
||||
|
||||
func (s *stockBatch) Create(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
|
||||
ids, err := dao.StockBatch.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
id := ids[0].(bson.ObjectID)
|
||||
res = &dto.CreateBatchRes{
|
||||
Id: &id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) error {
|
||||
return dao.StockBatch.Update(ctx, req)
|
||||
}
|
||||
|
||||
func (s *stockBatch) Delete(ctx context.Context, req *dto.DeleteBatchReq) error {
|
||||
return dao.StockBatch.DeleteFake(ctx, req)
|
||||
}
|
||||
|
||||
func (s *stockBatch) GetOne(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
|
||||
one, err := dao.StockBatch.GetOneById(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = utils.Struct(one, &res)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
|
||||
list, total, err := dao.StockBatch.List(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.ListBatchRes{
|
||||
Total: total,
|
||||
}
|
||||
err = utils.Struct(list, &res.List)
|
||||
return
|
||||
}
|
||||
//func (s *stockBatch) Create(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
|
||||
// ids, err := dao.StockBatch.Insert(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// id := ids[0].(bson.ObjectID)
|
||||
// res = &dto.CreateBatchRes{
|
||||
// Id: &id,
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (s *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) error {
|
||||
// return dao.StockBatch.Update(ctx, req)
|
||||
//}
|
||||
//
|
||||
//func (s *stockBatch) Delete(ctx context.Context, req *dto.DeleteBatchReq) error {
|
||||
// return dao.StockBatch.Delete(ctx, req)
|
||||
//}
|
||||
//
|
||||
//func (s *stockBatch) GetOne(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
|
||||
// one, err := dao.StockBatch.GetOneById(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// err = utils.Struct(one, &res)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (s *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
|
||||
// list, total, err := dao.StockBatch.List(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// res = &dto.ListBatchRes{
|
||||
// Total: total,
|
||||
// }
|
||||
// err = utils.Struct(list, &res.List)
|
||||
// return
|
||||
//}
|
||||
|
||||
@@ -4,36 +4,28 @@
|
||||
// 注意:区别于PrivateStock的实物库存,明细库存是逻辑概念,不记录物理位置
|
||||
package service
|
||||
|
||||
import (
|
||||
dao "assets/dao/stock"
|
||||
dto "assets/model/dto/stock"
|
||||
"context"
|
||||
|
||||
"gitea.com/red-future/common/utils"
|
||||
)
|
||||
|
||||
type stockDetails struct{}
|
||||
|
||||
// StockDetails 库存服务
|
||||
var StockDetails = new(stockDetails)
|
||||
|
||||
func (s *stockDetails) GetOne(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
|
||||
one, err := dao.StockDetails.GetOneById(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = utils.Struct(one, &res)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
|
||||
list, total, err := dao.StockDetails.List(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.ListStockDetailsRes{
|
||||
Total: total,
|
||||
}
|
||||
err = utils.Struct(list, &res.List)
|
||||
return
|
||||
}
|
||||
//func (s *stockDetails) GetOne(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
|
||||
// one, err := dao.StockDetails.GetOne(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// err = utils.Struct(one, &res)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (s *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
|
||||
// list, total, err := dao.StockDetails.List(ctx, req)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// res = &dto.ListStockDetailsRes{
|
||||
// Total: total,
|
||||
// }
|
||||
// err = utils.Struct(list, &res.List)
|
||||
// return
|
||||
//}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 库存管理服务(Stock公共库存)
|
||||
// Package service 库存管理服务(Stock公共库存)
|
||||
// 职责:入库/出库操作,支持明细模式(StockDetails)和批次模式(StockBatch)
|
||||
// 调用链:Controller → StockOperation → stockPublishMessage → NATS → AddStock(消费者)
|
||||
// 紧密耦合:dao.StockDetails、dao.StockBatch、dao.AssetSku(更新库存数)、common/message(NATS发布)
|
||||
@@ -13,18 +13,19 @@ import (
|
||||
assetDto "assets/model/dto/asset"
|
||||
stockDto "assets/model/dto/stock"
|
||||
assetEntity "assets/model/entity/asset"
|
||||
entity "assets/model/entity/stock"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
"gitea.com/red-future/common/redis"
|
||||
"gitea.com/red-future/common/utils"
|
||||
gmq "github.com/bjang03/gmq/core/gmq"
|
||||
"github.com/bjang03/gmq/mq"
|
||||
"github.com/bjang03/gmq/types"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type stockManage struct{}
|
||||
@@ -94,20 +95,25 @@ func (s *stockManage) StockOperation(ctx context.Context, req *stockDto.StockOpe
|
||||
return
|
||||
}
|
||||
if !assetSku.UnlimitedStock && req.Stock >= 0 {
|
||||
var stockId *bson.ObjectID
|
||||
var stockId int64
|
||||
count := 0
|
||||
if assetSku.StockMode == stock.StockModeDetail {
|
||||
_count, err := dao.StockDetails.GetStockCountBySkuId(ctx, assetSku.Id)
|
||||
detailsReq := &stockDto.GetSockDetailsReq{
|
||||
AssetSkuId: assetSku.Id,
|
||||
Status: stock.StockStatusAvailable.Code(),
|
||||
}
|
||||
count, err = dao.StockDetails.Count(ctx, detailsReq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
count = gconv.Int(_count)
|
||||
}
|
||||
if assetSku.StockMode == stock.StockModeBatch {
|
||||
if g.IsEmpty(req.BatchNo) {
|
||||
return gerror.New("批次号不能为空")
|
||||
}
|
||||
getOne, err := dao.StockBatch.GetOne(ctx, req.BatchNo)
|
||||
getOne, err := dao.StockBatch.One(ctx, &stockDto.GetSockBatchReq{
|
||||
BatchNo: req.BatchNo,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,7 +144,7 @@ func (s *stockManage) StockOperation(ctx context.Context, req *stockDto.StockOpe
|
||||
|
||||
// stockPublishMessage 发布库存变更消息到NATS
|
||||
// 消费者接收后执行实际的入库/出库操作(异步解耦)
|
||||
func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEntity.AssetSku, stockId *bson.ObjectID, stockCount int, operationType string, req *stockDto.StockOperationReq) (err error) {
|
||||
func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEntity.AssetSku, stockId int64, stockCount int, operationType string, req *stockDto.StockOperationReq) (err error) {
|
||||
// 用户信息
|
||||
user, err := utils.GetUserInfo(ctx)
|
||||
if err != nil {
|
||||
@@ -152,160 +158,128 @@ func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEn
|
||||
StockCount: stockCount,
|
||||
OperationType: operationType,
|
||||
Metadata: gconv.Maps(assetSku.SpecValues),
|
||||
StockMode: int(assetSku.StockMode),
|
||||
StockMode: assetSku.StockMode,
|
||||
BatchNo: req.BatchNo,
|
||||
ProductionDate: req.ProductionDate,
|
||||
ExpiryDate: req.ExpiryDate,
|
||||
ExpiryWarningDate: req.ExpiryWarningDate,
|
||||
}
|
||||
if !g.IsEmpty(stockId) && !stockId.IsZero() {
|
||||
publishMessage.StockId = stockId.Hex()
|
||||
if !g.IsEmpty(stockId) {
|
||||
publishMessage.StockId = stockId
|
||||
}
|
||||
// 发布到 NATS
|
||||
//plugin, err := message.GetMsgPlugin(ctx, message.MessageNATS)
|
||||
//if err != nil {
|
||||
// return gerror.Newf("NATS插件未就绪: %v", err)
|
||||
//}
|
||||
//err = plugin.Publish(ctx, &message.NatsPublishMsgConfig{
|
||||
// QueueName: public.StockDetailGroupName,
|
||||
// Durable: true,
|
||||
// Data: publishMessage,
|
||||
//})
|
||||
//_, err = message.PublishMessage(ctx, &message.RedisMessageConfig{StreamKey: public.StockDetailStreamKey}, publishMessage)
|
||||
//plugin, err := message.GetMsgPlugin(message.MessageRedis)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//err = plugin.Publish(ctx, &message.RedisPublishMsgConfig{
|
||||
// QueueName: public.StockDetailQueueName,
|
||||
// Data: publishMessage,
|
||||
//})
|
||||
err = gmq.GetGmq("primary").GmqPublish(ctx, &mq.RedisPubMessage{
|
||||
PubMessage: types.PubMessage{
|
||||
Topic: public.StockDetailQueueName,
|
||||
Data: publishMessage,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// AddStock NATS消费者调用,执行实际的入库/出库操作
|
||||
// 使用Redis分布式锁防止并发冲突,支持明细模式和批次模式
|
||||
func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) error {
|
||||
assetId := gconv.Int64(msg["assetId"])
|
||||
assetSkuId := gconv.Int64(msg["assetSkuId"])
|
||||
stockId := gconv.Int64(msg["stockId"])
|
||||
userName := gconv.String(msg["userName"])
|
||||
tenantId := gconv.Float64(msg["tenantId"])
|
||||
stockCount := gconv.Int(msg["stockCount"])
|
||||
operationType := gconv.String(msg["operationType"])
|
||||
metadata := gconv.Maps(msg["metadata"])
|
||||
stockMode := stock.StockMode(gconv.Int(msg["stockMode"]))
|
||||
batchNo := gconv.String(msg["batchNo"])
|
||||
productionDate := gtime.New(msg["productionDate"])
|
||||
expiryDate := gtime.New(msg["expiryDate"])
|
||||
expiryWarningDate := gtime.New(msg["expiryWarningDate"])
|
||||
func (s *stockManage) AddStock(ctx context.Context, msg any) error {
|
||||
var req = new(stockDto.StockPublishMessage)
|
||||
if err := gconv.Struct(msg, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
// 设置 userId 和 tenantId 到 ctx
|
||||
ctx = context.WithValue(ctx, "userName", userName)
|
||||
ctx = context.WithValue(ctx, "tenantId", tenantId)
|
||||
ctx = context.WithValue(ctx, "userName", req.UserName)
|
||||
ctx = context.WithValue(ctx, "tenantId", req.TenantId)
|
||||
// 获取redis-租户存储-锁key
|
||||
fileLockKey := fmt.Sprintf(public.StockDetailLockKey, assetSkuId)
|
||||
fileLockKey := fmt.Sprintf(public.StockDetailLockKey, req.AssetSkuId)
|
||||
success, err := redis.Lock(ctx, fileLockKey, int64(60), func(ctx context.Context) error {
|
||||
if operationType == "add" {
|
||||
if stockMode == stock.StockModeBatch {
|
||||
if !g.IsEmpty(stockId) {
|
||||
batch := stockDto.UpdateBatchReq{
|
||||
Id: stockId,
|
||||
BatchQty: stockCount,
|
||||
AvailableQty: stockCount,
|
||||
if req.OperationType == "add" {
|
||||
if req.StockMode == stock.StockModeBatch {
|
||||
if !g.IsEmpty(req.StockId) {
|
||||
var updateReq = new(stockDto.UpdateSockBatchReq)
|
||||
if err := gconv.Struct(req, &updateReq); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dao.StockBatch.Update(ctx, &batch); err != nil {
|
||||
if _, err := dao.StockBatch.Update(ctx, updateReq); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
batch := stockDto.CreateBatchReq{
|
||||
AssetId: assetId,
|
||||
AssetSkuId: assetSkuId,
|
||||
Status: stock.BatchStatusActive,
|
||||
Metadata: metadata,
|
||||
BatchNo: batchNo,
|
||||
BatchQty: stockCount,
|
||||
AvailableQty: stockCount,
|
||||
ProductionDate: productionDate,
|
||||
ExpiryDate: expiryDate,
|
||||
ExpiryWarningDate: expiryWarningDate,
|
||||
var createReq = new(stockDto.CreateSockBatchReq)
|
||||
if err := gconv.Struct(req, &createReq); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := dao.StockBatch.Insert(ctx, &batch); err != nil {
|
||||
if _, err := dao.StockBatch.Insert(ctx, createReq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if stockMode == stock.StockModeDetail {
|
||||
if req.StockMode == stock.StockModeDetail {
|
||||
// 创建指定数量的库存
|
||||
var stockInterfaces []interface{}
|
||||
for i := 0; i < stockCount; i++ {
|
||||
stockInterfaces = append(stockInterfaces, entity.StockDetails{
|
||||
AssetId: assetId,
|
||||
AssetSkuId: assetSkuId,
|
||||
Status: stock.StockStatusAvailable,
|
||||
Metadata: metadata,
|
||||
})
|
||||
stockDetailsList := make([]*stockDto.CreateSockDetailsReq, req.StockCount)
|
||||
for i := 0; i < req.StockCount; i++ {
|
||||
var createReq = new(stockDto.CreateSockDetailsReq)
|
||||
if err := gconv.Struct(req, &createReq); err != nil {
|
||||
return err
|
||||
}
|
||||
stockDetailsList = append(stockDetailsList, createReq)
|
||||
}
|
||||
// 批量插入数据库
|
||||
if _, err := dao.StockDetails.BatchInsert(ctx, stockInterfaces); err != nil {
|
||||
if _, err := dao.StockDetails.BatchInsert(ctx, stockDetailsList); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if operationType == "del" {
|
||||
if stockMode == stock.StockModeBatch {
|
||||
stockCount = 0 - stockCount
|
||||
if req.OperationType == "del" {
|
||||
if req.StockMode == stock.StockModeBatch {
|
||||
req.StockCount = 0 - req.StockCount
|
||||
// 更新批次
|
||||
batch := stockDto.UpdateBatchReq{
|
||||
Id: stockId,
|
||||
BatchQty: stockCount,
|
||||
AvailableQty: stockCount,
|
||||
batch := stockDto.UpdateSockBatchReq{
|
||||
Id: req.StockId,
|
||||
BatchQty: req.StockCount,
|
||||
AvailableQty: req.StockCount,
|
||||
}
|
||||
if err := dao.StockBatch.Update(ctx, &batch); err != nil {
|
||||
if _, err := dao.StockBatch.Update(ctx, &batch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if stockMode == stock.StockModeDetail {
|
||||
if req.StockMode == stock.StockModeDetail {
|
||||
// 分页查询所有库存明细,收集所有ID
|
||||
var allStockIds []*bson.ObjectID
|
||||
var allStockIds []stockDto.DeleteSockDetailsReq
|
||||
pageSize := int64(50)
|
||||
for pageNum := int64(1); ; pageNum++ {
|
||||
details, total, err := dao.StockDetails.List(ctx,
|
||||
&stockDto.ListStockDetailsReq{
|
||||
AssetSkuId: assetSkuId,
|
||||
Status: stock.StockStatusAvailable,
|
||||
&stockDto.GetSockDetailsReq{
|
||||
AssetSkuId: req.AssetSkuId,
|
||||
Status: stock.StockStatusAvailable.Code(),
|
||||
Page: &beans.Page{PageNum: pageNum, PageSize: pageSize},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pageNum == 1 && int(total) < stockCount {
|
||||
if pageNum == 1 && total < req.StockCount {
|
||||
return gerror.New("可操作库存数量不足")
|
||||
}
|
||||
// 收集当前页的ID
|
||||
for _, detail := range details {
|
||||
if detail.Id != nil && !detail.Id.IsZero() {
|
||||
allStockIds = append(allStockIds, detail.Id)
|
||||
if len(allStockIds) >= stockCount {
|
||||
if !g.IsEmpty(detail.Id) {
|
||||
allStockIds = append(allStockIds, stockDto.DeleteSockDetailsReq{Id: detail.Id})
|
||||
if len(allStockIds) >= req.StockCount {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(allStockIds) >= stockCount {
|
||||
if len(allStockIds) >= req.StockCount {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 根据ID批量删除库存
|
||||
delCount, err := dao.StockDetails.DeleteManyByIds(ctx, allStockIds)
|
||||
delCount, err := dao.StockDetails.Delete(ctx, allStockIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if delCount != int64(stockCount) {
|
||||
if delCount != int64(req.StockCount) {
|
||||
return gerror.New("删除库存数量不匹配")
|
||||
}
|
||||
stockCount = 0 - stockCount
|
||||
req.StockCount = 0 - req.StockCount
|
||||
}
|
||||
}
|
||||
_, err := assetDao.AssetSku.Update(ctx, &assetDto.UpdateAssetSkuReq{Id: assetSkuId, Stock: stockCount})
|
||||
_, err := assetDao.AssetSku.Update(ctx, &assetDto.UpdateAssetSkuReq{Id: req.AssetSkuId, Stock: req.StockCount})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
71
update.sql
71
update.sql
@@ -123,4 +123,73 @@ COMMENT ON COLUMN assets_asset.virtual_asset_config IS '虚拟资产配置(JSONB
|
||||
COMMENT ON COLUMN assets_asset.metadata IS '动态元数据(JSONB)';
|
||||
COMMENT ON COLUMN assets_asset.tenant_module_type IS '租户模块类型';
|
||||
|
||||
--------------------pgsql创建assets_asset表语句---------------------------
|
||||
--------------------pgsql创建assets_asset表语句---------------------------
|
||||
|
||||
--------------------pgsql创建assets_asset_sku表语句---------------------------
|
||||
-- 资产SKU表
|
||||
CREATE TABLE IF NOT EXISTS assets_asset_sku (
|
||||
-- 基础字段(继承 SQLBaseDO 通用字段)
|
||||
id BIGINT PRIMARY KEY, -- 主键ID(非自增)
|
||||
creator VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updater VARCHAR(64) NOT NULL,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at timestamp(6),
|
||||
|
||||
-- SKU核心字段
|
||||
asset_id BIGINT NOT NULL, -- 关联资产ID
|
||||
asset_name VARCHAR(128) NOT NULL, -- 资产名称
|
||||
sku_name VARCHAR(128) NOT NULL, -- SKU名称
|
||||
image_url VARCHAR(256) DEFAULT '', -- SKU主图
|
||||
spec_values JSONB NOT NULL DEFAULT '[]'::JSONB, -- 规格值:{"颜色":"红色","尺寸":"L"}
|
||||
price INT NOT NULL DEFAULT 0, -- 价格(分为单位)
|
||||
unlimited_stock BOOLEAN NOT NULL DEFAULT FALSE, -- 是否无库存限制
|
||||
stock INT NOT NULL DEFAULT 0, -- 库存数量
|
||||
specs_count INT NOT NULL DEFAULT 0, -- 规格数量
|
||||
specs_unit JSONB DEFAULT '{}'::JSONB, -- 规格单位 SpecsUnitKeyValue
|
||||
sort INT NOT NULL DEFAULT 0, -- 排序
|
||||
status SMALLINT NOT NULL DEFAULT 1, -- 资产状态:1启用/0停用
|
||||
stock_mode SMALLINT NOT NULL DEFAULT 1, -- 库存管理模式:1-明细模式 2-批次模式
|
||||
category_id BIGINT NOT NULL DEFAULT 0, -- 分类ID
|
||||
category_path VARCHAR(512) DEFAULT '', -- 分类路径
|
||||
tenant_module_type VARCHAR(32) DEFAULT '', -- 租户模块类型
|
||||
|
||||
-- 外键约束(可选,根据业务需要启用)
|
||||
CONSTRAINT fk_sku_asset_id FOREIGN KEY (asset_id) REFERENCES assets_asset(id) ON DELETE CASCADE,
|
||||
CONSTRAINT fk_sku_category_id FOREIGN KEY (category_id) REFERENCES assets_category(id) ON DELETE SET DEFAULT
|
||||
);
|
||||
|
||||
-- 索引(根据查询场景优化)
|
||||
CREATE INDEX idx_sku_asset_id ON assets_asset_sku(asset_id);
|
||||
CREATE INDEX idx_sku_category_id ON assets_asset_sku(category_id);
|
||||
CREATE INDEX idx_sku_status ON assets_asset_sku(status);
|
||||
CREATE INDEX idx_sku_stock_mode ON assets_asset_sku(stock_mode);
|
||||
CREATE INDEX idx_sku_deleted_at ON assets_asset_sku(deleted_at); -- 软删字段索引
|
||||
CREATE INDEX idx_sku_tenant_module_type ON assets_asset_sku(tenant_module_type);
|
||||
|
||||
-- 表和字段注释
|
||||
COMMENT ON TABLE assets_asset_sku IS '资产SKU表';
|
||||
COMMENT ON COLUMN assets_asset_sku.id IS '主键ID(非自增)';
|
||||
COMMENT ON COLUMN assets_asset_sku.creator IS '创建人';
|
||||
COMMENT ON COLUMN assets_asset_sku.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN assets_asset_sku.updater IS '更新人';
|
||||
COMMENT ON COLUMN assets_asset_sku.updated_at IS '更新时间';
|
||||
COMMENT ON COLUMN assets_asset_sku.deleted_at IS '删除时间(软删)';
|
||||
COMMENT ON COLUMN assets_asset_sku.asset_id IS '关联资产ID';
|
||||
COMMENT ON COLUMN assets_asset_sku.asset_name IS '资产名称';
|
||||
COMMENT ON COLUMN assets_asset_sku.sku_name IS 'SKU名称';
|
||||
COMMENT ON COLUMN assets_asset_sku.image_url IS 'SKU主图';
|
||||
COMMENT ON COLUMN assets_asset_sku.spec_values IS '规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"}';
|
||||
COMMENT ON COLUMN assets_asset_sku.price IS '价格(分为单位)';
|
||||
COMMENT ON COLUMN assets_asset_sku.unlimited_stock IS '是否无库存限制';
|
||||
COMMENT ON COLUMN assets_asset_sku.stock IS '库存数量';
|
||||
COMMENT ON COLUMN assets_asset_sku.specs_count IS '规格数量';
|
||||
COMMENT ON COLUMN assets_asset_sku.specs_unit IS '规格单位 SpecsUnitKeyValue';
|
||||
COMMENT ON COLUMN assets_asset_sku.sort IS '排序';
|
||||
COMMENT ON COLUMN assets_asset_sku.status IS '状态:active-启用/inactive-未启用/disabled-禁用';
|
||||
COMMENT ON COLUMN assets_asset_sku.stock_mode IS '库存管理模式:1-明细模式 2-批次模式';
|
||||
COMMENT ON COLUMN assets_asset_sku.category_id IS '分类ID';
|
||||
COMMENT ON COLUMN assets_asset_sku.category_path IS '分类路径';
|
||||
COMMENT ON COLUMN assets_asset_sku.tenant_module_type IS '租户模块类型';
|
||||
|
||||
--------------------pgsql创建assets_sku表语句---------------------------
|
||||
|
||||
Reference in New Issue
Block a user