Compare commits

...

5 Commits

Author SHA1 Message Date
qhd
018d60469a fix: 更新文件上传服务地址为http协议 2026-03-24 16:16:14 +08:00
qhd
99fbce121a feat: 添加租户字段及索引重构 2026-03-24 16:15:24 +08:00
qhd
989d89579b sql 2026-03-23 10:30:44 +08:00
qhd
829dc07747 refactor: 重构资产实体和DTO结构类型
将gjson.Json类型替换为具体的结构体和map类型,修正DAO层链式调用,启用SKU元数据校验逻辑
2026-03-22 20:08:32 +08:00
34a1ba79b6 删除 .idea/.gitignore 2026-03-20 03:06:56 +00:00
37 changed files with 1120 additions and 811 deletions

5
.idea/.gitignore generated vendored
View File

@@ -1,5 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@@ -17,8 +17,8 @@ rate:
database: database:
default: default:
- type: "pgsql" - type: "pgsql"
host: "116.204.74.41" host: "localhost"
port: "15432" port: "5432"
user: "postgres" user: "postgres"
pass: "123456" pass: "123456"
name: "assets" name: "assets"
@@ -34,8 +34,8 @@ database:
deletedAt: "deleted_at" # (可选)软删除时间字段名称 deletedAt: "deleted_at" # (可选)软删除时间字段名称
timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性为true时CreatedAt/UpdatedAt/DeletedAt都将失效 timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性为true时CreatedAt/UpdatedAt/DeletedAt都将失效
- type: "pgsql" - type: "pgsql"
host: "116.204.74.41" host: "localhost"
port: "15432" port: "5432"
user: "postgres" user: "postgres"
pass: "123456" pass: "123456"
name: "assets" name: "assets"
@@ -52,8 +52,8 @@ database:
timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性为true时CreatedAt/UpdatedAt/DeletedAt都将失效 timeMaintainDisabled: false # (可选)是否完全关闭时间更新特性为true时CreatedAt/UpdatedAt/DeletedAt都将失效
tenant-1: tenant-1:
- type: "pgsql" # 使用自定义驱动,自动赋值创建人/修改人/租户ID - type: "pgsql" # 使用自定义驱动,自动赋值创建人/修改人/租户ID
host: "116.204.74.41" host: "localhost"
port: "15432" port: "5432"
user: "postgres" user: "postgres"
pass: "123456" pass: "123456"
name: "tenant" name: "tenant"
@@ -72,7 +72,7 @@ database:
redis: redis:
# 集群模式配置方法 # 集群模式配置方法
default: default:
address: 116.204.74.41:6379 address: localhost:6379
db: 0 db: 0
idleTimeout: "60s" idleTimeout: "60s"
maxConnLifetime: "90s" maxConnLifetime: "90s"
@@ -82,7 +82,7 @@ redis:
writeTimeout: "30s" writeTimeout: "30s"
maxActive: 100 maxActive: 100
test: test:
address: 116.204.74.41:6379 address: localhost:6379
db: 1 db: 1
idleTimeout: "60s" idleTimeout: "60s"
maxConnLifetime: "90s" maxConnLifetime: "90s"
@@ -93,18 +93,31 @@ redis:
maxActive: 100 maxActive: 100
consul: consul:
address: 116.204.74.41:8500 address: localhost:8500
jaeger: jaeger:
addr: 116.204.74.41:4318 addr: localhost:4318
nats: nats:
default: default:
url: "nats://116.204.74.41:4222" url: "nats://localhost:4222"
# 文件上传服务地址与oss模块minio中的endpoint一致 # 文件上传服务地址与oss模块minio中的endpoint一致
filePrefix: "116.204.74.41:9000" filePrefix: "http://116.204.74.41:9000"
cache: cache:
localTTL: 60 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

View File

@@ -1,9 +1,28 @@
package consts package consts
import "github.com/gogf/gf/v2/util/gconv"
// AssetSkuStatus SKU状态枚举 // AssetSkuStatus SKU状态枚举
type AssetSkuStatusType *int var (
AssetSkuStatusDisable = newAssetSkuStatus(gconv.PtrInt8(0), "disable")
AssetSkuStatusEnable = newAssetSkuStatus(gconv.PtrInt8(1), "enable")
)
type AssetSkuStatus struct { type AssetSkuStatus *int8
Status AssetSkuStatusType
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}
} }

View File

@@ -1,9 +1,28 @@
package consts package consts
import "github.com/gogf/gf/v2/util/gconv"
// AssetStatus 资产状态枚举 // AssetStatus 资产状态枚举
type AssetStatusType *int var (
AssetStatusDisable = newAssetStatus(gconv.PtrInt8(0), "disable")
AssetStatusEnable = newAssetStatus(gconv.PtrInt8(1), "enable")
)
type AssetStatus struct { type AssetStatus *int8
Status AssetStatusType
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}
} }

View File

@@ -1,14 +1,28 @@
package consts package consts
import "github.com/gogf/gf/v2/util/gconv"
// CategoryStatus 分类状态枚举 // CategoryStatus 分类状态枚举
type CategoryStatusType *int var (
CategoryStatusDisable = newCategoryStatus(gconv.PtrInt8(0), "disable")
CategoryStatusEnable = newCategoryStatus(gconv.PtrInt8(1), "enable")
)
type CategoryStatus struct { type CategoryStatus *int8
Status CategoryStatusType
type categoryStatus struct {
code CategoryStatus
desc string
} }
//var CategoryStatusVal = CategoryStatus{ func (s categoryStatus) Code() CategoryStatus {
// CategoryStatusActive: gconv.PtrInt(1), return s.code
// CategoryStatusInactive: gconv.PtrInt(0), }
//} func (s categoryStatus) Desc() string {
return s.desc
}
func newCategoryStatus(code CategoryStatus, desc string) categoryStatus {
return categoryStatus{code: code, desc: desc}
}

View File

@@ -2,16 +2,16 @@ package public
// MongoDB集合名称常量 // MongoDB集合名称常量
const ( const (
AssetCollection = "assets_asset" // 资产集合
CategoryCollection = "assets_category" // 分类集合 CategoryCollection = "assets_category" // 分类集合
AssetCollection = "assets_asset" // 资产集合
AssetSkuCollection = "assets_asset_sku" // SKU集合
StockDetailsCollection = "assets_stock_details" // 库存明细集合
StockBatchCollection = "assets_stock_batch" // 库存批次集合
PrivateCategoryCollection = "private_category" // 私域分类集合 PrivateCategoryCollection = "private_category" // 私域分类集合
StockDetailsCollection = "stock_details" // 库存明细集合
StockBatchCollection = "stock_batch" // 库存批次集合
PrivateStockCollection = "private_stock" // 私域库存批次集合 PrivateStockCollection = "private_stock" // 私域库存批次集合
PurchaseOrderCollection = "purchase_order" // 采购订单主表集合(统一模式) PurchaseOrderCollection = "purchase_order" // 采购订单主表集合(统一模式)
PurchaseOrderItemCollection = "purchase_order_item" // 采购订单明细集合 PurchaseOrderItemCollection = "purchase_order_item" // 采购订单明细集合
PurchaseBidCollection = "purchase_bid" // 采购投标单集合(供应商抢单参与记录) PurchaseBidCollection = "purchase_bid" // 采购投标单集合(供应商抢单参与记录)
AssetSkuCollection = "asset_sku" // SKU集合
PrivateSkuCollection = "private_sku" // 私域sku集合 PrivateSkuCollection = "private_sku" // 私域sku集合
SupplierCollection = "supplier" // 供应商集合 SupplierCollection = "supplier" // 供应商集合
ExpiryMessageCollection = "expiry_message" // 临期消息集合(兼容旧数据) ExpiryMessageCollection = "expiry_message" // 临期消息集合(兼容旧数据)

View File

@@ -1,11 +1,10 @@
package public package public
const StockDetailLockKey = "stock:lock:skuId-%s" const StockDetailLockKey = "stock:lock:skuId-%v"
// 消费者配置(从 Redis Stream 消费请求) // 消费者配置(从 Redis Stream 消费请求)
const StockDetailQueueName = "assets:stock:detail:request:stream" // 请求 Stream 键名与发消息的key一致 const StockDetailQueueName = "assets:stock:stream" // 请求 Stream 键名与发消息的key一致
const StockDetailGroupName = "assets:stock:detail:consumer:group" // 消费者 const StockDetailConsumerName = "assets-stock-consumer" // 消费者名称(唯一标识)
const StockDetailConsumerName = "message-consumer-1" // 消费者名称(唯一标识)
const StockDetailPrefetchCount = 1 // 批处理大小每次读取1条 const StockDetailPrefetchCount = 1 // 批处理大小每次读取1条
const StockDetailAutoAck = false // ACK是否自动确认true自动确认false不确认 const StockDetailAutoAck = false // ACK是否自动确认true自动确认false不确认

View File

@@ -1,21 +1,30 @@
package stock package stock
// BatchStatus 批次状态枚举 import "github.com/gogf/gf/v2/util/gconv"
type BatchStatus int
const ( // BatchStatus 批次状态枚举
BatchStatusActive BatchStatus = 1 // 活跃
BatchStatusExpiring BatchStatus = 2 // 临期 var (
BatchStatusExpired BatchStatus = 3 // 过期 BatchStatusActive = newBatchStatus(gconv.PtrInt8(1), "活跃")
BatchStatusSoldOut BatchStatus = 4 // 售罄 BatchStatusExpiring = newBatchStatus(gconv.PtrInt8(2), "临期")
BatchStatusExpired = newBatchStatus(gconv.PtrInt8(3), "过期")
BatchStatusSoldOut = newBatchStatus(gconv.PtrInt8(4), "售罄")
) )
// GetAllBatchStatuses 获取所有批次状态 type BatchStatus *int8
func GetAllBatchStatuses() []BatchStatus {
return []BatchStatus{ type batchStatus struct {
BatchStatusActive, code BatchStatus
BatchStatusExpiring, desc string
BatchStatusExpired, }
BatchStatusSoldOut,
} 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}
} }

View File

@@ -1,21 +1,30 @@
package stock package stock
// StockStatus 库存状态枚举 import "github.com/gogf/gf/v2/util/gconv"
type StockStatus int
const ( // StockStatus 库存状态枚举
StockStatusAvailable StockStatus = 1 // 可用,未分配渠道
StockStatusSold StockStatus = 2 // 已售出 var (
StockStatusReserved StockStatus = 3 // 预留 StockStatusAvailable = newStockStatus(gconv.PtrInt8(1), "可用,未分配渠道")
StockStatusLocked StockStatus = 4 // 锁定 StockStatusSold = newStockStatus(gconv.PtrInt8(2), "已售出")
StockStatusReserved = newStockStatus(gconv.PtrInt8(3), "预留")
StockStatusLocked = newStockStatus(gconv.PtrInt8(4), "锁定")
) )
// GetAllStockStatuses 获取所有库存状态 type StockStatus *int8
func GetAllStockStatuses() []StockStatus {
return []StockStatus{ type stockStatus struct {
StockStatusAvailable, code StockStatus
StockStatusSold, desc string
StockStatusReserved, }
StockStatusLocked,
} 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}
} }

View File

@@ -4,14 +4,6 @@
// 注意Update/Delete返回*beans.ResponseEmpty直接return // 注意Update/Delete返回*beans.ResponseEmpty直接return
package controller package controller
import (
dto "assets/model/dto/stock"
service "assets/service/stock"
"context"
"gitea.com/red-future/common/beans"
)
type stockBatchController struct{} type stockBatchController struct{}
var StockBatch = new(stockBatchController) var StockBatch = new(stockBatchController)
@@ -19,24 +11,24 @@ var StockBatch = new(stockBatchController)
func init() { func init() {
} }
func (c *stockBatchController) CreateBatch(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) { //func (c *stockBatchController) CreateBatch(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
return service.StockBatch.Create(ctx, req) // return service.StockBatch.Create(ctx, req)
} //}
//
func (c *stockBatchController) UpdateBatch(ctx context.Context, req *dto.UpdateBatchReq) (res *beans.ResponseEmpty, err error) { //func (c *stockBatchController) UpdateBatch(ctx context.Context, req *dto.UpdateBatchReq) (res *beans.ResponseEmpty, err error) {
err = service.StockBatch.Update(ctx, req) // err = service.StockBatch.Update(ctx, req)
return // return
} //}
//
func (c *stockBatchController) DeleteBatch(ctx context.Context, req *dto.DeleteBatchReq) (res *beans.ResponseEmpty, err error) { //func (c *stockBatchController) DeleteBatch(ctx context.Context, req *dto.DeleteBatchReq) (res *beans.ResponseEmpty, err error) {
err = service.StockBatch.Delete(ctx, req) // err = service.StockBatch.Delete(ctx, req)
return // return
} //}
//
func (c *stockBatchController) GetBatch(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) { //func (c *stockBatchController) GetBatch(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
return service.StockBatch.GetOne(ctx, req) // return service.StockBatch.GetOne(ctx, req)
} //}
//
func (c *stockBatchController) ListBatches(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) { //func (c *stockBatchController) ListBatches(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
return service.StockBatch.List(ctx, req) // return service.StockBatch.List(ctx, req)
} //}

View File

@@ -4,12 +4,6 @@
// 注意:只读接口,无写操作 // 注意:只读接口,无写操作
package controller package controller
import (
dto "assets/model/dto/stock"
service "assets/service/stock"
"context"
)
type stockDetails struct{} type stockDetails struct{}
// StockDetails 库存控制器 // StockDetails 库存控制器
@@ -18,10 +12,10 @@ var StockDetails = new(stockDetails)
func init() { func init() {
} }
func (c *stockDetails) GetStockDetails(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) { //func (c *stockDetails) GetStockDetails(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
return service.StockDetails.GetOne(ctx, req) // return service.StockDetails.GetOne(ctx, req)
} //}
//
func (c *stockDetails) ListStockDetails(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) { //func (c *stockDetails) ListStockDetails(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
return service.StockDetails.List(ctx, req) // return service.StockDetails.List(ctx, req)
} //}

View File

@@ -23,7 +23,7 @@ func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int6
if err = gconv.Struct(req, &res); err != nil { if err = gconv.Struct(req, &res); err != nil {
return 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 { if err != nil {
return return
} }
@@ -32,7 +32,7 @@ func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int6
// Update 更新资产 // Update 更新资产
func (d *assetDao) Update(ctx context.Context, req *dto.UpdateAssetReq) (rows int64, err error) { 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 { if err != nil {
return return
} }
@@ -50,7 +50,7 @@ func (d *assetDao) Delete(ctx context.Context, req *dto.DeleteAssetReq) (rows in
// GetOne 获取单个资产 // GetOne 获取单个资产
func (d *assetDao) GetOne(ctx context.Context, req *dto.GetAssetReq, fields ...string) (res *entity.Asset, err error) { 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 { if err != nil {
return return
} }

View File

@@ -23,7 +23,7 @@ func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (id i
if err = gconv.Struct(req, &res); err != nil { if err = gconv.Struct(req, &res); err != nil {
return 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 { if err != nil {
return return
} }
@@ -32,7 +32,7 @@ func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (id i
// Update 更新SKU // Update 更新SKU
func (d *assetSku) Update(ctx context.Context, req *dto.UpdateAssetSkuReq) (rows int64, err error) { 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 { if err != nil {
return return
} }
@@ -50,7 +50,7 @@ func (d *assetSku) Delete(ctx context.Context, req *dto.DeleteAssetSkuReq) (rows
// GetOne 获取单个SKU // GetOne 获取单个SKU
func (d *assetSku) GetOne(ctx context.Context, req *dto.GetAssetSkuReq, fields ...string) (res *entity.AssetSku, err error) { 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 { if err != nil {
return 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.Id, req.Id)
model.Where(entity.AssetSkuCol.Status, req.Status) model.Where(entity.AssetSkuCol.Status, req.Status)
if req.MinPrice > 0 && req.MaxPrice > 0 {
model.WhereGT(entity.AssetSkuCol.Price, req.MinPrice) model.WhereGT(entity.AssetSkuCol.Price, req.MinPrice)
model.WhereLT(entity.AssetSkuCol.Price, req.MaxPrice) model.WhereLT(entity.AssetSkuCol.Price, req.MaxPrice)
}
model.OmitEmptyWhere() model.OmitEmptyWhere()
return model return model
} }

View File

@@ -10,9 +10,10 @@ import (
entity "assets/model/entity/stock" entity "assets/model/entity/stock"
"context" "context"
"gitea.com/red-future/common/db/mongo" "gitea.com/red-future/common/db/gfdb"
"gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/database/gdb"
"go.mongodb.org/mongo-driver/v2/bson" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
) )
var StockBatch = new(stockBatch) var StockBatch = new(stockBatch)
@@ -21,58 +22,48 @@ type stockBatch struct {
} }
// Insert 插入 // Insert 插入
func (d *stockBatch) Insert(ctx context.Context, req *dto.CreateBatchReq) (ids []interface{}, err error) { func (d *stockBatch) Insert(ctx context.Context, req *dto.CreateSockBatchReq) (id int64, err error) {
var result *entity.StockBatch var res *entity.StockBatch
if err = utils.Struct(req, &result); err != nil { if err = gconv.Struct(req, &res); err != nil {
return return
} }
ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.StockBatchCollection) r, err := gfdb.DB(ctx).Model(ctx, public.StockBatchCollection).Data(&res).Insert()
if err != nil {
return 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,
},
} }
_, err = mongo.DB().Update(ctx, filter, update, public.StockBatchCollection) return r.LastInsertId()
}
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 return
}
// 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
} }
if req.AssetSkuId != nil { return r.RowsAffected()
filter["assetSkuId"] = req.AssetSkuId }
// 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 return
} }

View File

@@ -6,15 +6,13 @@ package dao
import ( import (
"assets/consts/public" "assets/consts/public"
"assets/consts/stock"
dto "assets/model/dto/stock" dto "assets/model/dto/stock"
entity "assets/model/entity/stock" entity "assets/model/entity/stock"
"context" "context"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/db/gfdb"
"gitea.com/red-future/common/db/mongo" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv"
"go.mongodb.org/mongo-driver/v2/bson"
) )
var StockDetails = new(stockDetails) var StockDetails = new(stockDetails)
@@ -23,58 +21,52 @@ type stockDetails struct {
} }
// BatchInsert 批量插入库存 // BatchInsert 批量插入库存
func (d *stockDetails) BatchInsert(ctx context.Context, stockInterfaces []interface{}) (ids []interface{}, err error) { func (d *stockDetails) BatchInsert(ctx context.Context, req []*dto.CreateSockDetailsReq) (rows int64, err error) {
ids, err = mongo.DB().Insert(ctx, stockInterfaces, public.StockDetailsCollection) 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 return
} }
// DeleteManyByIds 根据ID批量删除库存 // buildListFilter 构建列表查询的过滤条件
func (d *stockDetails) DeleteManyByIds(ctx context.Context, allStockIds []*bson.ObjectID) (count int64, err error) { func (d *stockDetails) buildListFilter(ctx context.Context, req *dto.GetSockDetailsReq) *gdb.Model {
if len(allStockIds) == 0 { model := gfdb.DB(ctx).Model(ctx, public.StockDetailsCollection).Model
return 0, nil model.Where(entity.StockDetailsCol.Id, req.Id)
} model.Where(entity.StockDetailsCol.AssetId, req.AssetId)
filter := bson.M{"_id": bson.M{"$in": allStockIds}} model.Where(entity.StockDetailsCol.AssetSkuId, req.AssetSkuId)
count, err = mongo.DB().Delete(ctx, filter, public.StockDetailsCollection) model.Where(entity.StockDetailsCol.Status, req.Status)
return model.OmitEmptyWhere()
} return model
// 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
} }

51
go.mod
View File

@@ -4,14 +4,17 @@ go 1.25.7
require ( require (
gitea.com/red-future/common v0.0.4 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/contrib/drivers/pgsql/v2 v2.10.0
github.com/gogf/gf/v2 v2.10.0 github.com/gogf/gf/v2 v2.10.0
github.com/redis/go-redis/v9 v9.12.1 github.com/redis/go-redis/v9 v9.18.0
github.com/xuri/excelize/v2 v2.10.0 github.com/xuri/excelize/v2 v2.10.1
go.mongodb.org/mongo-driver/v2 v2.4.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 ( require (
github.com/BurntSushi/toml v1.5.0 // indirect 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emirpasic/gods/v2 v2.0.0-alpha // 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/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-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // 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/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/nosql/redis/v2 v2.9.1 // indirect
github.com/gogf/gf/contrib/registry/consul/v2 v2.9.5 // 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/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/serf v0.10.1 // 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/cpuid/v2 v2.2.11 // indirect
github.com/klauspost/crc32 v1.3.0 // 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/lib/pq v1.10.9 // indirect
github.com/magiconair/properties v1.8.10 // indirect github.com/magiconair/properties v1.8.10 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // 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/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/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/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect github.com/olekukonko/ll v0.0.9 // indirect
github.com/olekukonko/tablewriter v1.1.0 // indirect github.com/olekukonko/tablewriter v1.1.0 // indirect
github.com/philhofer/fwd v1.2.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect github.com/rabbitmq/amqp091-go v1.10.0 // indirect
github.com/richardlehane/msoleps v1.0.4 // 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/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.6.0 // 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/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/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/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/xdg-go/stringprep v1.0.4 // indirect
github.com/xuri/efp v0.0.1 // indirect github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // 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/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // 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/exp v0.0.0-20250808145144-a408d31f581a // indirect
golang.org/x/net v0.47.0 // indirect golang.org/x/net v0.50.0 // indirect
golang.org/x/sync v0.18.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.38.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.31.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/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc 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 google.golang.org/grpc v1.75.0 // indirect

60
go.sum
View File

@@ -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.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 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.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 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 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 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 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= 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/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 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 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-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 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= 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/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 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.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.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 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= 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.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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= 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/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 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.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 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= 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 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.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/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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/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/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 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= 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.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.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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 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.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 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= 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.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 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= 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.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 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/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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 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.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.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= 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/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 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ= 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 h1:fNiBE/Dq5iTHvTGlCx3DmXa2o4hr0NtumFpffZ39k6s=
github.com/tiger1103/gfast-token v1.0.10/go.mod h1:a/21mxmj7zFeNvjhZSC0XpEAFHfb1aT2k6DXnufFU1s= 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 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww=
github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= 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/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 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 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 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= 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 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= 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 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= 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 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.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 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= 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= 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= 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 h1:hGDMngUao03OVQ6sgV5csk+RWOIkF+CuLsTPobNMGNI=
go.mongodb.org/mongo-driver/v2 v2.4.1/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI= 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 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 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/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 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= 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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 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-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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 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.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 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= 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-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 h1:Y+7uR/b1Mw2iSXZ3G//1haIiSElDQZ8KWh0h+sZPG90=
golang.org/x/exp v0.0.0-20250808145144-a408d31f581a/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg= 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.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 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= 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/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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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.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 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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-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-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= 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.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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= 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.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-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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=

21
main.go
View File

@@ -1,11 +1,13 @@
package main package main
import ( import (
"assets/consts/public"
assetController "assets/controller/asset" assetController "assets/controller/asset"
enumController "assets/controller/enum" enumController "assets/controller/enum"
procurementController "assets/controller/procurement" procurementController "assets/controller/procurement"
stockController "assets/controller/stock" stockController "assets/controller/stock"
syncController "assets/controller/sync" syncController "assets/controller/sync"
stockService "assets/service/stock"
"context" "context"
"os" "os"
"os/signal" "os/signal"
@@ -13,10 +15,11 @@ import (
"gitea.com/red-future/common/http" "gitea.com/red-future/common/http"
"gitea.com/red-future/common/jaeger" "gitea.com/red-future/common/jaeger"
_ "gitea.com/red-future/common/swagger" _ "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/contrib/drivers/pgsql/v2"
"github.com/gogf/gf/v2/frame/g" "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) quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

View File

@@ -5,6 +5,7 @@ import (
"assets/consts/stock" "assets/consts/stock"
"assets/model/config" "assets/model/config"
enumDto "assets/model/dto/enum" enumDto "assets/model/dto/enum"
entity "assets/model/entity/asset"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@@ -22,7 +23,7 @@ type CreateAssetReq struct {
CategoryPath string `json:"categoryPath" dc:"分类路径"` CategoryPath string `json:"categoryPath" dc:"分类路径"`
ImageURL string `json:"imageUrl" dc:"主图URL"` ImageURL string `json:"imageUrl" dc:"主图URL"`
Images []string `json:"images" dc:"图片列表"` Images []string `json:"images" dc:"图片列表"`
Status consts.AssetStatusType `json:"status" dc:"状态1/0" d:"1"` Status consts.AssetStatus `json:"status" dc:"状态1/0" d:"1"`
UnlimitedStock bool `json:"unlimitedStock" dc:"是否无库存限制"` UnlimitedStock bool `json:"unlimitedStock" dc:"是否无库存限制"`
StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式1-明细模式 2-批次模式" d:"2"` StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式1-明细模式 2-批次模式" d:"2"`
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间格式2006-01-02 15:04:05"` OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间格式2006-01-02 15:04:05"`
@@ -52,7 +53,7 @@ type ListAssetReq struct {
Type consts.AssetType `json:"type" dc:"资产类型"` Type consts.AssetType `json:"type" dc:"资产类型"`
CategoryId int64 `json:"categoryId" dc:"分类ID"` CategoryId int64 `json:"categoryId" dc:"分类ID"`
CategoryPath string `json:"categoryPath" dc:"分类路径"` CategoryPath string `json:"categoryPath" dc:"分类路径"`
Status consts.AssetStatusType `json:"status" dc:"状态"` Status consts.AssetStatus `json:"status" dc:"状态"`
TenantModuleType beans.TenantModuleType `json:"tenantModuleType" dc:"租户模块类型"` TenantModuleType beans.TenantModuleType `json:"tenantModuleType" dc:"租户模块类型"`
Keyword string `json:"keyword" dc:"关键词搜索"` Keyword string `json:"keyword" dc:"关键词搜索"`
} }
@@ -64,13 +65,13 @@ type ListAssetRes struct {
} }
type AssetItem struct { type AssetItem struct {
Id int64 `json:"id"` // 资产ID Id int64 `json:"id,string"` // 资产ID
Name string `json:"name"` // 资产名称 Name string `json:"name"` // 资产名称
Type consts.AssetType `json:"type"` // 资产类型physical实物/virtual虚拟/service服务 Type consts.AssetType `json:"type"` // 资产类型physical实物/virtual虚拟/service服务
TypeName string `json:"typeName"` // 资产类型physical实物/virtual虚拟/service服务 TypeName string `json:"typeName"` // 资产类型physical实物/virtual虚拟/service服务
CategoryId int64 `json:"categoryId"` // 分类ID CategoryId int64 `json:"categoryId,string"` // 分类ID
UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制 UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制
Status consts.AssetStatusType `json:"status"` // 资产状态active启用/inactive停用 Status consts.AssetStatus `json:"status"` // 资产状态active启用/inactive停用
BasePrice int `json:"basePrice"` // 基础价格(分为单位) BasePrice int `json:"basePrice"` // 基础价格(分为单位)
OnlineTime *gtime.Time `json:"onlineTime,omitempty"` // 上线时间 OnlineTime *gtime.Time `json:"onlineTime,omitempty"` // 上线时间
OfflineTime *gtime.Time `json:"offlineTime,omitempty"` // 下线时间 OfflineTime *gtime.Time `json:"offlineTime,omitempty"` // 下线时间
@@ -86,7 +87,7 @@ type GetAssetReq struct {
// GetAssetRes 获取资产详情响应 // GetAssetRes 获取资产详情响应
type GetAssetRes struct { type GetAssetRes struct {
*AssetItem *entity.Asset
CategoryName string `json:"categoryName" dc:"分类名称"` CategoryName string `json:"categoryName" dc:"分类名称"`
ImgAddressPrefix string `json:"imgAddressPrefix"` ImgAddressPrefix string `json:"imgAddressPrefix"`
} }
@@ -99,7 +100,7 @@ type GetAssetAndSkuReq struct {
// GetAssetAndSkuRes 获取资产详情响应 // GetAssetAndSkuRes 获取资产详情响应
type GetAssetAndSkuRes struct { type GetAssetAndSkuRes struct {
*AssetItem *entity.Asset
Skus []AssetSkuItem `json:"skus" dc:"SKU列表"` Skus []AssetSkuItem `json:"skus" dc:"SKU列表"`
TenantModuleType []enumDto.KeyValue `json:"tenantModuleType" dc:"租户模块类型"` TenantModuleType []enumDto.KeyValue `json:"tenantModuleType" dc:"租户模块类型"`
ImgAddressPrefix string `json:"imgAddressPrefix"` ImgAddressPrefix string `json:"imgAddressPrefix"`
@@ -115,7 +116,7 @@ type UpdateAssetReq struct {
CategoryId int64 `json:"categoryId" dc:"分类ID"` CategoryId int64 `json:"categoryId" dc:"分类ID"`
ImageURL string `json:"imageUrl" dc:"主图URL"` ImageURL string `json:"imageUrl" dc:"主图URL"`
Images []string `json:"images" dc:"图片列表"` Images []string `json:"images" dc:"图片列表"`
Status consts.AssetStatusType `json:"status,omitempty" dc:"状态1/0"` Status consts.AssetStatus `json:"status,omitempty" dc:"状态1/0"`
OnlineTime *gtime.Time `json:"onlineTime,omitempty" dc:"上线时间格式2006-01-02 15:04:05"` 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"` OfflineTime *gtime.Time `json:"offlineTime,omitempty" dc:"下线时间格式2006-01-02 15:04:05"`
// 类型专用配置 - 实物资产配置 // 类型专用配置 - 实物资产配置
@@ -132,7 +133,7 @@ type UpdateAssetReq struct {
type UpdateAssetStatusReq struct { type UpdateAssetStatusReq struct {
g.Meta `path:"/updateAssetStatus" method:"put" tags:"资产管理" summary:"更新资产状态" dc:"更新资产状态"` g.Meta `path:"/updateAssetStatus" method:"put" tags:"资产管理" summary:"更新资产状态" dc:"更新资产状态"`
Id int64 `json:"id" v:"required" dc:"资产ID"` Id int64 `json:"id" v:"required" dc:"资产ID"`
Status consts.AssetStatusType `json:"status" v:"required|in:1,0" dc:"状态1启用/0停用"` Status consts.AssetStatus `json:"status" v:"required|in:1,0" dc:"状态1启用/0停用"`
} }
// DeleteAssetReq 删除资产请求 // DeleteAssetReq 删除资产请求

View File

@@ -23,7 +23,7 @@ type CreateAssetSkuReq struct {
ImageURL string `json:"imageUrl" v:"required" dc:"SKU主图"` ImageURL string `json:"imageUrl" v:"required" dc:"SKU主图"`
Price int `json:"price" v:"required|min:0" dc:"价格(分为单位)"` Price int `json:"price" v:"required|min:0" dc:"价格(分为单位)"`
Sort int `json:"sort" 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:"是否无库存限制"` UnlimitedStock bool `json:"unlimitedStock" v:"required" dc:"是否无库存限制"`
StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式"` StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式"`
CategoryId int64 `json:"categoryId" dc:"分类ID"` CategoryId int64 `json:"categoryId" dc:"分类ID"`
@@ -49,7 +49,7 @@ type UpdateAssetSkuReq struct {
Price int `json:"price" dc:"价格(分为单位)"` Price int `json:"price" dc:"价格(分为单位)"`
Sort int `json:"sort" dc:"排序"` Sort int `json:"sort" dc:"排序"`
Stock int `json:"stock" dc:"库存数量"` Stock int `json:"stock" dc:"库存数量"`
Status consts.AssetSkuStatusType `json:"status" dc:"状态"` Status consts.AssetSkuStatus `json:"status" dc:"状态"`
} }
// DeleteAssetSkuReq 删除SKU请求 // DeleteAssetSkuReq 删除SKU请求
@@ -88,7 +88,7 @@ type ListAssetSkuReq struct {
*beans.Page *beans.Page
Id int64 `json:"id" dc:"SKU ID"` Id int64 `json:"id" dc:"SKU ID"`
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"` AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
Status consts.AssetSkuStatusType `json:"status" dc:"状态"` Status consts.AssetSkuStatus `json:"status" dc:"状态"`
Keyword string `json:"keyword" dc:"关键词搜索"` Keyword string `json:"keyword" dc:"关键词搜索"`
MinPrice int `json:"minPrice" dc:"最低价格"` MinPrice int `json:"minPrice" dc:"最低价格"`
MaxPrice int `json:"maxPrice" dc:"最高价格"` MaxPrice int `json:"maxPrice" dc:"最高价格"`
@@ -102,8 +102,8 @@ type ListAssetSkuRes struct {
} }
type AssetSkuItem struct { type AssetSkuItem struct {
Id int64 `json:"id"` // SKU ID Id int64 `json:"id,string"` // SKU ID
AssetId int64 `json:"assetId"` AssetId int64 `json:"assetId,string"`
AssetName string `json:"assetName"` // 资产名称 AssetName string `json:"assetName"` // 资产名称
SkuName string `json:"skuName"` // SKU名称 SkuName string `json:"skuName"` // SKU名称
SpecsCount int `json:"specsCount"` // 规格数量 SpecsCount int `json:"specsCount"` // 规格数量
@@ -113,8 +113,9 @@ type AssetSkuItem struct {
UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制 UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制
Stock int `json:"stock"` // 库存数量 Stock int `json:"stock"` // 库存数量
Sort int `json:"sort"` // 排序 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-批次模式 StockMode stock.StockMode `json:"stockMode"` // 库存管理模式1-明细模式 2-批次模式
ImageURL string `json:"imageUrl"` // SKU主图
CreatedAt *gtime.Time `json:"createdAt"` // 创建时间 CreatedAt *gtime.Time `json:"createdAt"` // 创建时间
UpdatedAt *gtime.Time `json:"updatedAt"` // 更新时间 UpdatedAt *gtime.Time `json:"updatedAt"` // 更新时间
} }

View File

@@ -19,7 +19,7 @@ type CreateCategoryReq struct {
Sort int `json:"sort" dc:"排序"` Sort int `json:"sort" dc:"排序"`
Path string `json:"path" dc:"分类路径"` Path string `json:"path" dc:"分类路径"`
Level int `json:"level" dc:"分类层级"` Level int `json:"level" dc:"分类层级"`
Status consts.CategoryStatusType `json:"status" v:"in:1,0" default:"1" dc:"状态1启用0禁用"` Status consts.CategoryStatus `json:"status" v:"in:1,0" default:"1" dc:"状态1启用0禁用"`
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"` Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
} }
@@ -38,14 +38,14 @@ type UpdateCategoryReq struct {
Sort int `json:"sort" dc:"排序"` Sort int `json:"sort" dc:"排序"`
IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"` IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"`
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"` Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
Status consts.CategoryStatusType `json:"status" dc:"状态1启用0禁用"` Status consts.CategoryStatus `json:"status" dc:"状态1启用0禁用"`
} }
// UpdateCategoryStatusReq 更新分类状态请求 // UpdateCategoryStatusReq 更新分类状态请求
type UpdateCategoryStatusReq struct { type UpdateCategoryStatusReq struct {
g.Meta `path:"/updateCategoryStatus" method:"put" tags:"分类管理" summary:"更新分类状态" dc:"更新分类状态"` g.Meta `path:"/updateCategoryStatus" method:"put" tags:"分类管理" summary:"更新分类状态" dc:"更新分类状态"`
Id int64 `json:"id" v:"required" dc:"分类ID"` Id int64 `json:"id" v:"required" dc:"分类ID"`
Status consts.CategoryStatusType `json:"status" v:"in:1,0" dc:"状态1启用0禁用"` Status consts.CategoryStatus `json:"status" v:"in:1,0" dc:"状态1启用0禁用"`
} }
// DeleteCategoryReq 删除分类请求 // DeleteCategoryReq 删除分类请求
@@ -73,7 +73,7 @@ type CategoryTreeNode struct {
Type string `json:"type" dc:"分类类型"` Type string `json:"type" dc:"分类类型"`
Path string `json:"path" dc:"分类路径"` Path string `json:"path" dc:"分类路径"`
IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"` IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"`
Status consts.CategoryStatusType `json:"status" dc:"状态"` Status consts.CategoryStatus `json:"status" dc:"状态"`
Sort int `json:"sort" dc:"排序"` Sort int `json:"sort" dc:"排序"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"` UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间"`
@@ -85,7 +85,7 @@ type ListCategoryReq struct {
g.Meta `path:"/listCategories" method:"get" tags:"分类管理" summary:"获取分类列表" dc:"获取分类列表"` g.Meta `path:"/listCategories" method:"get" tags:"分类管理" summary:"获取分类列表" dc:"获取分类列表"`
*beans.Page *beans.Page
ParentId int64 `json:"parentId" dc:"父分类ID"` ParentId int64 `json:"parentId" dc:"父分类ID"`
Status consts.CategoryStatusType `json:"status" dc:"状态1启用0禁用"` Status consts.CategoryStatus `json:"status" dc:"状态1启用0禁用"`
Keyword string `json:"keyword" dc:"关键词搜索"` Keyword string `json:"keyword" dc:"关键词搜索"`
} }
@@ -112,7 +112,7 @@ type GetCategoryRes struct {
Sort int `json:"sort" dc:"排序"` Sort int `json:"sort" dc:"排序"`
Image string `json:"image" dc:"分类图片"` Image string `json:"image" dc:"分类图片"`
Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"` Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"`
Status consts.CategoryStatusType `json:"status" dc:"状态1启用0禁用"` Status consts.CategoryStatus `json:"status" dc:"状态1启用0禁用"`
Creator string `json:"creator" dc:"创建人"` Creator string `json:"creator" dc:"创建人"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
Updater string `json:"updater" dc:"更新人"` Updater string `json:"updater" dc:"更新人"`

View File

@@ -3,24 +3,11 @@ package dto
import ( import (
"assets/consts/stock" "assets/consts/stock"
"gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"go.mongodb.org/mongo-driver/v2/bson"
) )
// CommonResp 通用响应 // CreateSockBatchReq 创建批次请求
type CommonResp struct { type CreateSockBatchReq struct {
Success bool `json:"success"` // 是否成功
Message string `json:"message"` // 消息
}
// --- 批次管理API相关结构 ---
// CreateBatchReq 创建批次请求
type CreateBatchReq struct {
g.Meta `path:"/createBatch" method:"post" tags:"库存批次管理" summary:"创建批次" dc:"创建新的库存批次"`
AssetId int64 `json:"assetId" v:"required" dc:"资产ID"` AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"SKU ID"` AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"SKU ID"`
BatchNo string `json:"batchNo" v:"required" dc:"批次号"` BatchNo string `json:"batchNo" v:"required" dc:"批次号"`
@@ -33,58 +20,13 @@ type CreateBatchReq struct {
ExpiryWarningDate *gtime.Time `json:"expiryWarningDate" dc:"临期预警时间(格式:2006-01-02)"` ExpiryWarningDate *gtime.Time `json:"expiryWarningDate" dc:"临期预警时间(格式:2006-01-02)"`
} }
// CreateBatchRes 创建批次响应 type UpdateSockBatchReq struct {
type CreateBatchRes struct {
Id *bson.ObjectID `json:"id"` // 批次ID
}
// UpdateBatchReq 更新批次请求
type UpdateBatchReq struct {
g.Meta `path:"/updateBatch" method:"put" tags:"库存批次管理" summary:"更新批次" dc:"更新批次信息"`
Id int64 `json:"id" v:"required" dc:"批次ID"` Id int64 `json:"id" v:"required" dc:"批次ID"`
BatchQty int `json:"batchQty" v:"required|min:1" dc:"批次数量"` BatchQty int `json:"batchQty" v:"required|min:1" dc:"批次数量"`
AvailableQty int `json:"availableQty" v:"required|min:1" dc:"可用数量"` AvailableQty int `json:"availableQty" v:"required|min:1" dc:"可用数量"`
} }
// DeleteBatchReq 删除批次请求 type GetSockBatchReq struct {
type DeleteBatchReq struct { Id int64 `json:"id" v:"required" dc:"批次ID"`
g.Meta `path:"/deleteBatch" method:"delete" tags:"库存批次管理" summary:"删除批次" dc:"删除批次"` BatchNo string `json:"batchNo" 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"`
} }

View File

@@ -4,64 +4,25 @@ import (
"assets/consts/stock" "assets/consts/stock"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/frame/g"
"go.mongodb.org/mongo-driver/v2/bson"
) )
// GetStockDetailsReq 获取库存明细详情请求 // CreateSockDetailsReq 创建明细请求
type GetStockDetailsReq struct { type CreateSockDetailsReq struct {
g.Meta `path:"/getStockDetails" method:"get" tags:"库存明细管理" summary:"获取库存明细详情" dc:"获取库存明细详情"` AssetId int64 `json:"assetId" v:"required" dc:"资产ID"`
Id *bson.ObjectID `json:"id" 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 DeleteSockDetailsReq struct {
type GetStockDetailsRes struct { Id int64 `json:"Id" v:"required" dc:"库存明细ID"`
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"`
} }
// ListStockDetailsReq 获取库存明细列表请求 type GetSockDetailsReq struct {
type ListStockDetailsReq struct {
g.Meta `path:"/listStockDetails" method:"get" tags:"库存明细管理" summary:"获取库存明细列表" dc:"分页查询库存明细列表,支持多条件筛选"`
*beans.Page *beans.Page
OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"` Id int64 `json:"id" dc:"库存明细ID"`
AssetId int64 `json:"assetId" dc:"资产ID"` AssetId int64 `json:"assetId" dc:"资产ID"`
AssetSkuId int64 `json:"assetSkuId" dc:"SKU ID"` AssetSkuId int64 `json:"assetSkuId" dc:"SKU ID"`
CategoryPath string `json:"categoryPath" dc:"分类路径"` CategoryPath string `json:"categoryPath" dc:"分类路径"`
Status stock.StockStatus `json:"status" 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"`
}

View File

@@ -29,8 +29,8 @@ type StockPublishMessage struct {
StockCount int `json:"stockCount"` StockCount int `json:"stockCount"`
OperationType string `json:"operationType"` OperationType string `json:"operationType"`
Metadata []map[string]interface{} `json:"metadata"` Metadata []map[string]interface{} `json:"metadata"`
StockId string `json:"stockId"` StockId int64 `json:"stockId"`
StockMode int `json:"stockMode"` StockMode stock.StockMode `json:"stockMode"`
BatchNo string `json:"batchNo"` BatchNo string `json:"batchNo"`
ProductionDate *gtime.Time `json:"productionDate"` ProductionDate *gtime.Time `json:"productionDate"`
ExpiryDate *gtime.Time `json:"expiryDate"` ExpiryDate *gtime.Time `json:"expiryDate"`

View File

@@ -3,9 +3,9 @@ package entity
import ( import (
consts "assets/consts/asset" consts "assets/consts/asset"
"assets/consts/stock" "assets/consts/stock"
"assets/model/config"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
) )
@@ -62,11 +62,11 @@ type Asset struct {
Name string `orm:"name" json:"name" description:"资产名称"` Name string `orm:"name" json:"name" description:"资产名称"`
Description string `orm:"description" json:"description" description:"资产描述"` Description string `orm:"description" json:"description" description:"资产描述"`
Type consts.AssetType `orm:"type" json:"type" description:"资产类型physical实物/virtual虚拟/service服务"` Type consts.AssetType `orm:"type" json:"type" description:"资产类型physical实物/virtual虚拟/service服务"`
CategoryId int64 `orm:"category_id" json:"categoryId" description:"分类ID"` CategoryId int64 `orm:"category_id" json:"categoryId,string" description:"分类ID"`
CategoryPath string `orm:"category_path" json:"categoryPath" description:"分类路径"` CategoryPath string `orm:"category_path" json:"categoryPath" description:"分类路径"`
ImageURL string `orm:"image_url" json:"imageUrl" description:"主图URL"` ImageURL string `orm:"image_url" json:"imageUrl" description:"主图URL"`
Images []string `orm:"images" json:"images" description:"图片列表(JSONB)"` Images []string `orm:"images" json:"images" description:"图片列表(JSONB)"`
Status consts.AssetStatusType `orm:"status" json:"status" description:"资产状态1启用/0停用"` Status consts.AssetStatus `orm:"status" json:"status" description:"资产状态1启用/0停用"`
BasePrice int `orm:"base_price" json:"basePrice" description:"基础价格(分为单位)"` BasePrice int `orm:"base_price" json:"basePrice" description:"基础价格(分为单位)"`
Currency string `orm:"currency" json:"currency" description:"货币单位默认CNY"` Currency string `orm:"currency" json:"currency" description:"货币单位默认CNY"`
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock" description:"是否无库存限制"` UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock" description:"是否无库存限制"`
@@ -75,13 +75,13 @@ type Asset struct {
OfflineTime *gtime.Time `orm:"offline_time" json:"offlineTime,omitempty" description:"下线时间"` // 上线和下线时间配置(由定时任务处理资产状态) OfflineTime *gtime.Time `orm:"offline_time" json:"offlineTime,omitempty" description:"下线时间"` // 上线和下线时间配置(由定时任务处理资产状态)
// 类型专用配置 - 实物资产配置(JSONB) // 类型专用配置 - 实物资产配置(JSONB)
PhysicalAssetConfig *gjson.Json `orm:"physical_asset_config" json:"physicalAssetConfig" description:"实物资产配置(JSONB)"` PhysicalAssetConfig *config.PhysicalAssetConfig `orm:"physical_asset_config" json:"physicalAssetConfig" description:"实物资产配置(JSONB)"`
// 类型专用配置 - 服务资产配置(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) // 类型专用配置 - 虚拟资产配置(JSONB)
VirtualAssetConfig *gjson.Json `orm:"virtual_asset_config" json:"virtualAssetConfig" description:"虚拟资产配置(JSONB)"` VirtualAssetConfig *config.VirtualAssetConfig `orm:"virtual_asset_config" json:"virtualAssetConfig" description:"虚拟资产配置(JSONB)"`
// 扩展字段(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:"租户模块类型"` TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType" description:"租户模块类型"`
} }

View File

@@ -3,10 +3,8 @@ package entity
import ( import (
consts "assets/consts/asset" consts "assets/consts/asset"
"assets/consts/stock" "assets/consts/stock"
"assets/model/config"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/encoding/gjson"
) )
type assetSkuCol struct { type assetSkuCol struct {
@@ -26,8 +24,8 @@ type assetSkuCol struct {
StockMode string StockMode string
CategoryId string CategoryId string
CategoryPath string CategoryPath string
CapacityUnitType string //CapacityUnitType string
Capacity string //Capacity string
TenantModuleType string TenantModuleType string
} }
@@ -48,8 +46,8 @@ var AssetSkuCol = assetSkuCol{
StockMode: "stock_mode", StockMode: "stock_mode",
CategoryId: "category_id", CategoryId: "category_id",
CategoryPath: "category_path", CategoryPath: "category_path",
CapacityUnitType: "capacity_unit_type", //CapacityUnitType: "capacity_unit_type",
Capacity: "capacity", //Capacity: "capacity",
TenantModuleType: "tenant_module_type", TenantModuleType: "tenant_module_type",
} }
@@ -60,19 +58,19 @@ type AssetSku struct {
AssetName string `orm:"asset_name" json:"assetName"` // 资产名称 AssetName string `orm:"asset_name" json:"assetName"` // 资产名称
SkuName string `orm:"sku_name" json:"skuName"` // SKU名称 SkuName string `orm:"sku_name" json:"skuName"` // SKU名称
ImageURL string `orm:"image_url,omitempty" json:"imageUrl"` // SKU主图 ImageURL string `orm:"image_url,omitempty" json:"imageUrl"` // SKU主图
SpecValues []gjson.Json `orm:"spec_values" json:"specValues"` // 规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"} SpecValues []map[string]interface{} `orm:"spec_values" json:"specValues"` // 规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"}
Price int `orm:"price" json:"price"` // 价格(分为单位) Price int `orm:"price" json:"price"` // 价格(分为单位)
UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock"` // 是否无库存限制 UnlimitedStock bool `orm:"unlimited_stock" json:"unlimitedStock"` // 是否无库存限制
Stock int `orm:"stock" json:"stock"` // 库存数量 Stock int `orm:"stock" json:"stock"` // 库存数量
SpecsCount int `orm:"specs_count" json:"specsCount"` // 规格数量 SpecsCount int `orm:"specs_count" json:"specsCount"` // 规格数量
SpecsUnit *gjson.Json `orm:"specs_unit" json:"specsUnit"` // 规格单位 SpecsUnitKeyValue SpecsUnit *SpecsUnitKeyValue `orm:"specs_unit" json:"specsUnit"` // 规格单位 SpecsUnitKeyValue
Sort int `orm:"sort" json:"sort"` // 排序 Sort int `orm:"sort" json:"sort"` // 排序
Status consts.AssetSkuStatusType `orm:"status" json:"status"` // 状态active/inactive/disabled Status consts.AssetSkuStatus `orm:"status" json:"status"` // 状态active/inactive/disabled
StockMode stock.StockMode `orm:"stock_mode" json:"stockMode"` // 库存管理模式1-明细模式 2-批次模式 StockMode stock.StockMode `orm:"stock_mode" json:"stockMode"` // 库存管理模式1-明细模式 2-批次模式
CategoryId int64 `orm:"category_id" json:"categoryId"` // 分类ID CategoryId int64 `orm:"category_id" json:"categoryId"` // 分类ID
CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径 CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
CapacityUnitType stock.CapacityUnitType `orm:"capacity_unit_type" json:"capacityUnitType"` // 容量单位类型 //CapacityUnitType stock.CapacityUnitType `orm:"capacity_unit_type" json:"capacityUnitType"` // 容量单位类型
Capacity config.Capacity `orm:"capacity" json:"capacity"` // 容量 //Capacity int `orm:"capacity" json:"capacity"` // 容量
TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType"` // 租户模块类型 TenantModuleType beans.TenantModuleType `orm:"tenant_module_type" json:"tenantModuleType"` // 租户模块类型
} }

View File

@@ -42,7 +42,7 @@ type Category struct {
IsLeafNode *bool `orm:"is_leaf_node" json:"isLeafNode"` // 是叶子节点 IsLeafNode *bool `orm:"is_leaf_node" json:"isLeafNode"` // 是叶子节点
Sort int `orm:"sort" json:"sort"` // 排序 Sort int `orm:"sort" json:"sort"` // 排序
Image string `orm:"image" json:"image"` // 分类图片 Image string `orm:"image" json:"image"` // 分类图片
Status consts.CategoryStatusType `orm:"status" json:"status"` // 状态1启用/0禁用 Status consts.CategoryStatus `orm:"status" json:"status"` // 状态1启用/0禁用
Attrs []CategoryAttr `orm:"attrs" json:"attrs,omitempty"` // 分类属性 CategoryAttr Attrs []CategoryAttr `orm:"attrs" json:"attrs,omitempty"` // 分类属性 CategoryAttr
// 使用场景说明: // 使用场景说明:
// 1. 商品分类属性:为该分类下的商品定义标准化的属性模板,如服装分类可定义尺寸、颜色、材质等属性 // 1. 商品分类属性:为该分类下的商品定义标准化的属性模板,如服装分类可定义尺寸、颜色、材质等属性

View File

@@ -1,48 +1,80 @@
package entity package entity
import ( import (
"assets/consts/public"
"assets/consts/stock" "assets/consts/stock"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/os/gtime" "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 库存批次实体(用于批次管理模式) // StockBatch 库存批次实体(用于批次管理模式)
type StockBatch struct { type StockBatch struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted beans.SQLBaseDO `orm:",inherit"`
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
AssetID *bson.ObjectID `bson:"assetId" json:"assetId"` // 关联资产ID AssetSkuId int64 `orm:"asset_sku_id" json:"assetSkuId"` // 关联资产SKU ID
AssetSkuID *bson.ObjectID `bson:"assetSkuId" json:"assetSkuId"` // 关联资产SKU ID BatchNo string `orm:"batch_no" json:"batchNo"` // 批次号
BatchNo string `bson:"batchNo" json:"batchNo"` // 批次 BatchQty int `orm:"batch_qty" json:"batchQty"` // 批次总数量(入库后不可变)
BatchQty int `bson:"batchQty" json:"batchQty"` // 批次总数量(入库后不可变 AvailableQty int `orm:"available_qty" json:"availableQty"` // 可用数量(实时变化
AvailableQty int `bson:"availableQty" 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 // 锁定数量 = BatchQty - AvailableQty
// 订单关联 // 订单关联
OrderID *bson.ObjectID `bson:"orderId" json:"orderId"` // 关联订单ID如果有 OrderID int64 `orm:"order_id" json:"orderId"` // 关联订单ID如果有
// 渠道分配信息 // 渠道分配信息
AssignedChannel string `bson:"assignedChannel" json:"assignedChannel"` // 分配的销售渠道 AssignedChannel string `orm:"assigned_channel" json:"assignedChannel"` // 分配的销售渠道
ChannelSKU string `bson:"channelSku" json:"channelSku"` // 渠道商品SKU ChannelSKU string `orm:"channel_sku" json:"channelSku"` // 渠道商品SKU
ChannelMetadata map[string]interface{} `bson:"channelMetadata" json:"channelMetadata"` // 渠道专属数据 ChannelMetadata map[string]interface{} `orm:"channel_metadata" json:"channelMetadata"` // 渠道专属数据
AllocatedAt *gtime.Time `bson:"allocatedAt" json:"allocatedAt"` // 分配时间 AllocatedAt *gtime.Time `orm:"allocated_at" json:"allocatedAt"` // 分配时间
// 临期管理 // 临期管理
ProductionDate *gtime.Time `bson:"productionDate" json:"productionDate"` // 生产日期 ProductionDate *gtime.Time `orm:"production_date" json:"productionDate"` // 生产日期
ExpiryDate *gtime.Time `bson:"expiryDate" json:"expiryDate"` // 过期日期 ExpiryDate *gtime.Time `orm:"expiry_date" json:"expiryDate"` // 过期日期
ExpiryWarningDate *gtime.Time `bson:"expiryWarningDate" json:"expiryWarningDate"` // 临期预警时间(有过期日期时建议填写) ExpiryWarningDate *gtime.Time `orm:"expiry_warning_date" json:"expiryWarningDate"` // 临期预警时间(有过期日期时建议填写)
CategoryPath string `bson:"categoryPath" json:"categoryPath"` // 分类路径 CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
}
// CollectionName 获取集合名称
func (StockBatch) CollectionName() string {
return public.StockBatchCollection
} }

View File

@@ -1,35 +1,59 @@
package entity package entity
import ( import (
"assets/consts/public"
"assets/consts/stock" "assets/consts/stock"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"github.com/gogf/gf/v2/os/gtime" "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用于后期做区块链虚拟资产 // StockDetails 库存实体每一件商品都有独立ID用于后期做区块链虚拟资产
type StockDetails struct { type StockDetails struct {
beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted beans.SQLBaseDO `orm:",inherit"`
AssetId int64 `orm:"asset_id" json:"assetId"` // 关联资产ID
AssetId int64 `bson:"assetId" json:"assetId"` // 关联资产ID AssetSkuId int64 `orm:"asset_sku_id" json:"assetSkuId"` // 关联资产SKU ID
AssetSkuId int64 `bson:"assetSkuId" json:"assetSkuId"` // 关联资产SKU ID Status stock.StockStatus `orm:"status" json:"status"` // 库存状态
Status stock.StockStatus `bson:"status" json:"status"` // 库存状态 OrderId int64 `orm:"order_id" json:"orderId"` // 关联订单ID如果有
OrderId *bson.ObjectID `bson:"orderId" json:"orderId"` // 关联订单ID如果有 LockExpire *gtime.Time `orm:"lock_expire" json:"lockExpire"` // 锁定过期时间
LockExpire *gtime.Time `bson:"lockExpire" json:"lockExpire"` // 锁定过期时间 Metadata []map[string]interface{} `orm:"metadata" json:"metadata"` // 其他元数据
Metadata []map[string]interface{} `bson:"metadata" json:"metadata"` // 其他元数据 TokenId string `orm:"token_id" json:"tokenId"` // 区块链TokenID如果有
TokenId string `bson:"tokenId" json:"tokenId"` // 区块链TokenID如果有
// 渠道分配信息 // 渠道分配信息
AssignedChannel string `bson:"assignedChannel" json:"assignedChannel"` // 分配的销售渠道 AssignedChannel string `orm:"assigned_channel" json:"assignedChannel"` // 分配的销售渠道
ChannelSKU string `bson:"channelSku" json:"channelSku"` // 渠道商品SKU ChannelSKU string `orm:"channel_sku" json:"channelSku"` // 渠道商品SKU
ChannelMetadata map[string]interface{} `bson:"channelMetadata" json:"channelMetadata"` // 渠道专属数据 ChannelMetadata map[string]interface{} `orm:"channel_metadata" json:"channelMetadata"` // 渠道专属数据
AllocatedAt *gtime.Time `bson:"allocatedAt" json:"allocatedAt"` // 分配时间 AllocatedAt *gtime.Time `orm:"allocated_at" json:"allocatedAt"` // 分配时间
CategoryPath string `bson:"categoryPath" json:"categoryPath"` // 分类路径 CategoryPath string `orm:"category_path" json:"categoryPath"` // 分类路径
}
// CollectionName 库存集合名称
func (StockDetails) CollectionName() string {
return public.StockDetailsCollection
} }

View File

@@ -11,11 +11,11 @@ import (
"errors" "errors"
"gitea.com/red-future/common/http" "gitea.com/red-future/common/http"
"gitea.com/red-future/common/utils"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"gitea.com/red-future/common/minio"
) )
type asset struct{} type asset struct{}
@@ -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 { if assetOne, err = dao.Asset.GetOne(ctx, req); err != nil {
return return
} }
var assetListItem *dto.AssetItem var assetListItem *entity.Asset
if err = gconv.Struct(assetOne, assetListItem); err != nil { if err = gconv.Struct(assetOne, &assetListItem); err != nil {
return return
} }
getCategoryRes, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{ getCategoryRes, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{
@@ -92,11 +92,15 @@ func (s *asset) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *dto.GetA
if err != nil { if err != nil {
return return
} }
return &dto.GetAssetRes{ res = &dto.GetAssetRes{
AssetItem: assetListItem, Asset: assetListItem,
CategoryName: getCategoryRes.Name, CategoryName: getCategoryRes.Name,
ImgAddressPrefix: minio.GetFileAddressPrefix(ctx), }
}, nil res.ImgAddressPrefix, err = utils.GetFileAddressPrefix(ctx)
if err != nil {
return
}
return
} }
// GetAssetAndSku 获取资产和Sku详情 // GetAssetAndSku 获取资产和Sku详情
@@ -109,7 +113,7 @@ func (s *asset) GetAssetAndSku(ctx context.Context, req *dto.GetAssetAndSkuReq)
if err != nil { if err != nil {
return return
} }
var assetListItem *dto.AssetItem var assetListItem *entity.Asset
if err = gconv.Struct(assetOne, assetListItem); err != nil { if err = gconv.Struct(assetOne, assetListItem); err != nil {
return return
} }
@@ -125,12 +129,17 @@ func (s *asset) GetAssetAndSku(ctx context.Context, req *dto.GetAssetAndSkuReq)
if err = gconv.Structs(skus, assetSkuListResItem); err != nil { if err = gconv.Structs(skus, assetSkuListResItem); err != nil {
return return
} }
return &dto.GetAssetAndSkuRes{ res = &dto.GetAssetAndSkuRes{
AssetItem: assetListItem, Asset: assetListItem,
Skus: assetSkuListResItem, Skus: assetSkuListResItem,
TenantModuleType: moduleType.Options, TenantModuleType: moduleType.Options,
ImgAddressPrefix: minio.GetFileAddressPrefix(ctx), }
}, nil url, err := utils.GetFileAddressPrefix(ctx)
if err != nil {
return
}
res.ImgAddressPrefix = url
return
} }
// Update 更新资产 // Update 更新资产

View File

@@ -1,6 +1,7 @@
package service package service
import ( import (
consts "assets/consts/asset"
"assets/consts/public" "assets/consts/public"
dao "assets/dao/asset" dao "assets/dao/asset"
dto "assets/model/dto/asset" dto "assets/model/dto/asset"
@@ -10,7 +11,6 @@ import (
"reflect" "reflect"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"gitea.com/red-future/common/utils"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
) )
@@ -84,19 +84,18 @@ func (s *assetSku) parameterValidation(ctx context.Context, assetEntity *entity.
specNoExist := true specNoExist := true
metadataList := make([]string, 0) metadataList := make([]string, 0)
// 验证,自定义属性传过来的全不全 // 验证,自定义属性传过来的全不全
// TODO: Metadata类型从[]map[string]interface{}变为*gjson.Json需要适配 if assetEntity.Metadata != nil {
// if assetEntity.Metadata != nil { for _, metadata := range assetEntity.Metadata {
// for _, metadata := range assetEntity.Metadata { attributeType := gconv.String(gconv.Map(metadata)["type"])
// attributeType := gconv.String(gconv.Map(metadata)["type"]) if attributeType == string(consts.AttributeTypeMultiSelect) {
// if attributeType == string(consts.AttributeTypeMultiSelect) { metadataList = append(metadataList, attributeType)
// metadataList = append(metadataList, attributeType) }
// } }
// } if len(metadataList) != len(specValues) {
// if len(metadataList) != len(specValues) { // 如果请求参数中不存在该键,则跳过
// // 如果请求参数中不存在该键,则跳过 return errors.New("规格参数填写不完整")
// return errors.New("规格参数填写不完整") }
// } }
// }
// 验证自定义属性和sku名称重不重复 // 验证自定义属性和sku名称重不重复
for _, list := range list { for _, list := range list {
if list.SkuName == skuName { if list.SkuName == skuName {
@@ -155,7 +154,7 @@ func (s *assetSku) GetAssetSku(ctx context.Context, req *dto.GetAssetSkuReq) (re
if err != nil { if err != nil {
return return
} }
err = utils.Struct(one, &res) err = gconv.Struct(one, &res)
return return
} }
@@ -169,7 +168,7 @@ func (s *assetSku) ListAssetSkus(ctx context.Context, req *dto.ListAssetSkuReq)
res = &dto.ListAssetSkuRes{ res = &dto.ListAssetSkuRes{
Total: total, Total: total,
} }
err = utils.Struct(list, &res.List) err = gconv.Struct(list, &res.List)
return return
} }

View File

@@ -77,7 +77,7 @@ func (s *CategoryService) GetOne(ctx context.Context, req *dto.GetCategoryReq) (
} }
res := new(dto.GetCategoryRes) res := new(dto.GetCategoryRes)
if err = gconv.Scan(one, &res); err != nil { if err = gconv.Struct(one, &res); err != nil {
panic(err) panic(err)
} }

View File

@@ -7,6 +7,8 @@ import (
"context" "context"
"gitea.com/red-future/common/beans" "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" "github.com/gogf/gf/v2/util/gconv"
) )
@@ -39,17 +41,25 @@ func (s *enum) GetSpecsUnit(ctx context.Context, req *dto.GetSpecsUnitReq) (res
return return
} }
} else { } else {
// 使用简化的 RPC 调用方式 - 直接传 map 参数 // 获取当前请求的 headers 并传递到下游
//dictData := &dto.GetDictRes{} headers := make(map[string]string)
//if err = message.CallRPC(ctx, "dictService.GetDictWithDataByType", map[string]interface{}{"dictType": gconv.String(req.AssetType)}, dictData); err != nil { if r := g.RequestFromCtx(ctx); r != nil {
// return for k, v := range r.Request.Header {
//} if len(v) > 0 {
//for _, v := range dictData.Values { headers[k] = v[0]
// res.Options = append(res.Options, dto.KeyValue{ }
// Key: v.DictValue, }
// Value: v.DictLabel, }
// }) 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 return
} }

View File

@@ -4,57 +4,48 @@
// 注意区别于PrivateStock的实物库存批次库存是逻辑概念不记录物理位置 // 注意区别于PrivateStock的实物库存批次库存是逻辑概念不记录物理位置
package service 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{} type stockBatch struct{}
// StockBatch 批次服务 // StockBatch 批次服务
var StockBatch = new(stockBatch) var StockBatch = new(stockBatch)
func (s *stockBatch) Create(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) { //func (s *stockBatch) Create(ctx context.Context, req *dto.CreateBatchReq) (res *dto.CreateBatchRes, err error) {
ids, err := dao.StockBatch.Insert(ctx, req) // ids, err := dao.StockBatch.Insert(ctx, req)
if err != nil { // if err != nil {
return // return
} // }
id := ids[0].(bson.ObjectID) // id := ids[0].(bson.ObjectID)
res = &dto.CreateBatchRes{ // res = &dto.CreateBatchRes{
Id: &id, // Id: &id,
} // }
return // return
} //}
//
func (s *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) error { //func (s *stockBatch) Update(ctx context.Context, req *dto.UpdateBatchReq) error {
return dao.StockBatch.Update(ctx, req) // return dao.StockBatch.Update(ctx, req)
} //}
//
func (s *stockBatch) Delete(ctx context.Context, req *dto.DeleteBatchReq) error { //func (s *stockBatch) Delete(ctx context.Context, req *dto.DeleteBatchReq) error {
return dao.StockBatch.DeleteFake(ctx, req) // return dao.StockBatch.Delete(ctx, req)
} //}
//
func (s *stockBatch) GetOne(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) { //func (s *stockBatch) GetOne(ctx context.Context, req *dto.GetBatchReq) (res *dto.GetBatchRes, err error) {
one, err := dao.StockBatch.GetOneById(ctx, req) // one, err := dao.StockBatch.GetOneById(ctx, req)
if err != nil { // if err != nil {
return // return
} // }
err = utils.Struct(one, &res) // err = utils.Struct(one, &res)
return // return
} //}
//
func (s *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) { //func (s *stockBatch) List(ctx context.Context, req *dto.ListBatchReq) (res *dto.ListBatchRes, err error) {
list, total, err := dao.StockBatch.List(ctx, req) // list, total, err := dao.StockBatch.List(ctx, req)
if err != nil { // if err != nil {
return // return
} // }
res = &dto.ListBatchRes{ // res = &dto.ListBatchRes{
Total: total, // Total: total,
} // }
err = utils.Struct(list, &res.List) // err = utils.Struct(list, &res.List)
return // return
} //}

View File

@@ -4,36 +4,28 @@
// 注意区别于PrivateStock的实物库存明细库存是逻辑概念不记录物理位置 // 注意区别于PrivateStock的实物库存明细库存是逻辑概念不记录物理位置
package service package service
import (
dao "assets/dao/stock"
dto "assets/model/dto/stock"
"context"
"gitea.com/red-future/common/utils"
)
type stockDetails struct{} type stockDetails struct{}
// StockDetails 库存服务 // StockDetails 库存服务
var StockDetails = new(stockDetails) var StockDetails = new(stockDetails)
func (s *stockDetails) GetOne(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) { //func (s *stockDetails) GetOne(ctx context.Context, req *dto.GetStockDetailsReq) (res *dto.GetStockDetailsRes, err error) {
one, err := dao.StockDetails.GetOneById(ctx, req) // one, err := dao.StockDetails.GetOne(ctx, req)
if err != nil { // if err != nil {
return // return
} // }
err = utils.Struct(one, &res) // err = utils.Struct(one, &res)
return // return
} //}
//
func (s *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) { //func (s *stockDetails) List(ctx context.Context, req *dto.ListStockDetailsReq) (res *dto.ListStockDetailsRes, err error) {
list, total, err := dao.StockDetails.List(ctx, req) // list, total, err := dao.StockDetails.List(ctx, req)
if err != nil { // if err != nil {
return // return
} // }
res = &dto.ListStockDetailsRes{ // res = &dto.ListStockDetailsRes{
Total: total, // Total: total,
} // }
err = utils.Struct(list, &res.List) // err = utils.Struct(list, &res.List)
return // return
} //}

View File

@@ -1,4 +1,4 @@
// 库存管理服务Stock公共库存 // Package service 库存管理服务Stock公共库存
// 职责:入库/出库操作,支持明细模式(StockDetails)和批次模式(StockBatch) // 职责:入库/出库操作,支持明细模式(StockDetails)和批次模式(StockBatch)
// 调用链Controller → StockOperation → stockPublishMessage → NATS → AddStock(消费者) // 调用链Controller → StockOperation → stockPublishMessage → NATS → AddStock(消费者)
// 紧密耦合dao.StockDetails、dao.StockBatch、dao.AssetSku(更新库存数)、common/message(NATS发布) // 紧密耦合dao.StockDetails、dao.StockBatch、dao.AssetSku(更新库存数)、common/message(NATS发布)
@@ -13,18 +13,19 @@ import (
assetDto "assets/model/dto/asset" assetDto "assets/model/dto/asset"
stockDto "assets/model/dto/stock" stockDto "assets/model/dto/stock"
assetEntity "assets/model/entity/asset" assetEntity "assets/model/entity/asset"
entity "assets/model/entity/stock"
"context" "context"
"fmt" "fmt"
"gitea.com/red-future/common/beans" "gitea.com/red-future/common/beans"
"gitea.com/red-future/common/redis" "gitea.com/red-future/common/redis"
"gitea.com/red-future/common/utils" "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/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"go.mongodb.org/mongo-driver/v2/bson"
) )
type stockManage struct{} type stockManage struct{}
@@ -94,20 +95,25 @@ func (s *stockManage) StockOperation(ctx context.Context, req *stockDto.StockOpe
return return
} }
if !assetSku.UnlimitedStock && req.Stock >= 0 { if !assetSku.UnlimitedStock && req.Stock >= 0 {
var stockId *bson.ObjectID var stockId int64
count := 0 count := 0
if assetSku.StockMode == stock.StockModeDetail { 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 { if err != nil {
return err return err
} }
count = gconv.Int(_count)
} }
if assetSku.StockMode == stock.StockModeBatch { if assetSku.StockMode == stock.StockModeBatch {
if g.IsEmpty(req.BatchNo) { if g.IsEmpty(req.BatchNo) {
return gerror.New("批次号不能为空") 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 { if err != nil {
return err return err
} }
@@ -138,7 +144,7 @@ func (s *stockManage) StockOperation(ctx context.Context, req *stockDto.StockOpe
// stockPublishMessage 发布库存变更消息到NATS // 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) user, err := utils.GetUserInfo(ctx)
if err != nil { if err != nil {
@@ -152,160 +158,128 @@ func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEn
StockCount: stockCount, StockCount: stockCount,
OperationType: operationType, OperationType: operationType,
Metadata: gconv.Maps(assetSku.SpecValues), Metadata: gconv.Maps(assetSku.SpecValues),
StockMode: int(assetSku.StockMode), StockMode: assetSku.StockMode,
BatchNo: req.BatchNo, BatchNo: req.BatchNo,
ProductionDate: req.ProductionDate, ProductionDate: req.ProductionDate,
ExpiryDate: req.ExpiryDate, ExpiryDate: req.ExpiryDate,
ExpiryWarningDate: req.ExpiryWarningDate, ExpiryWarningDate: req.ExpiryWarningDate,
} }
if !g.IsEmpty(stockId) && !stockId.IsZero() { if !g.IsEmpty(stockId) {
publishMessage.StockId = stockId.Hex() publishMessage.StockId = stockId
} }
// 发布到 NATS err = gmq.GetGmq("primary").GmqPublish(ctx, &mq.RedisPubMessage{
//plugin, err := message.GetMsgPlugin(ctx, message.MessageNATS) PubMessage: types.PubMessage{
//if err != nil { Topic: public.StockDetailQueueName,
// return gerror.Newf("NATS插件未就绪: %v", err) Data: publishMessage,
//} },
//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,
//})
return return
} }
// AddStock NATS消费者调用执行实际的入库/出库操作 // AddStock NATS消费者调用执行实际的入库/出库操作
// 使用Redis分布式锁防止并发冲突支持明细模式和批次模式 // 使用Redis分布式锁防止并发冲突支持明细模式和批次模式
func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) error { func (s *stockManage) AddStock(ctx context.Context, msg any) error {
assetId := gconv.Int64(msg["assetId"]) var req = new(stockDto.StockPublishMessage)
assetSkuId := gconv.Int64(msg["assetSkuId"]) if err := gconv.Struct(msg, &req); err != nil {
stockId := gconv.Int64(msg["stockId"]) return err
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"])
// 设置 userId 和 tenantId 到 ctx
ctx = context.WithValue(ctx, "userName", userName)
ctx = context.WithValue(ctx, "tenantId", tenantId)
// 获取redis-租户存储-锁key
fileLockKey := fmt.Sprintf(public.StockDetailLockKey, 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 err := dao.StockBatch.Update(ctx, &batch); err != nil { // 设置 userId 和 tenantId 到 ctx
ctx = context.WithValue(ctx, "userName", req.UserName)
ctx = context.WithValue(ctx, "tenantId", req.TenantId)
// 获取redis-租户存储-锁key
fileLockKey := fmt.Sprintf(public.StockDetailLockKey, req.AssetSkuId)
success, err := redis.Lock(ctx, fileLockKey, int64(60), func(ctx context.Context) error {
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, updateReq); err != nil {
return err return err
} }
} else { } else {
batch := stockDto.CreateBatchReq{ var createReq = new(stockDto.CreateSockBatchReq)
AssetId: assetId, if err := gconv.Struct(req, &createReq); err != nil {
AssetSkuId: assetSkuId, return err
Status: stock.BatchStatusActive,
Metadata: metadata,
BatchNo: batchNo,
BatchQty: stockCount,
AvailableQty: stockCount,
ProductionDate: productionDate,
ExpiryDate: expiryDate,
ExpiryWarningDate: expiryWarningDate,
} }
if _, err := dao.StockBatch.Insert(ctx, &batch); err != nil { if _, err := dao.StockBatch.Insert(ctx, createReq); err != nil {
return err return err
} }
} }
} }
if stockMode == stock.StockModeDetail { if req.StockMode == stock.StockModeDetail {
// 创建指定数量的库存 // 创建指定数量的库存
var stockInterfaces []interface{} stockDetailsList := make([]*stockDto.CreateSockDetailsReq, req.StockCount)
for i := 0; i < stockCount; i++ { for i := 0; i < req.StockCount; i++ {
stockInterfaces = append(stockInterfaces, entity.StockDetails{ var createReq = new(stockDto.CreateSockDetailsReq)
AssetId: assetId, if err := gconv.Struct(req, &createReq); err != nil {
AssetSkuId: assetSkuId, return err
Status: stock.StockStatusAvailable, }
Metadata: metadata, stockDetailsList = append(stockDetailsList, createReq)
})
} }
// 批量插入数据库 // 批量插入数据库
if _, err := dao.StockDetails.BatchInsert(ctx, stockInterfaces); err != nil { if _, err := dao.StockDetails.BatchInsert(ctx, stockDetailsList); err != nil {
return err return err
} }
} }
} }
if operationType == "del" { if req.OperationType == "del" {
if stockMode == stock.StockModeBatch { if req.StockMode == stock.StockModeBatch {
stockCount = 0 - stockCount req.StockCount = 0 - req.StockCount
// 更新批次 // 更新批次
batch := stockDto.UpdateBatchReq{ batch := stockDto.UpdateSockBatchReq{
Id: stockId, Id: req.StockId,
BatchQty: stockCount, BatchQty: req.StockCount,
AvailableQty: stockCount, AvailableQty: req.StockCount,
} }
if err := dao.StockBatch.Update(ctx, &batch); err != nil { if _, err := dao.StockBatch.Update(ctx, &batch); err != nil {
return err return err
} }
} }
if stockMode == stock.StockModeDetail { if req.StockMode == stock.StockModeDetail {
// 分页查询所有库存明细收集所有ID // 分页查询所有库存明细收集所有ID
var allStockIds []*bson.ObjectID var allStockIds []stockDto.DeleteSockDetailsReq
pageSize := int64(50) pageSize := int64(50)
for pageNum := int64(1); ; pageNum++ { for pageNum := int64(1); ; pageNum++ {
details, total, err := dao.StockDetails.List(ctx, details, total, err := dao.StockDetails.List(ctx,
&stockDto.ListStockDetailsReq{ &stockDto.GetSockDetailsReq{
AssetSkuId: assetSkuId, AssetSkuId: req.AssetSkuId,
Status: stock.StockStatusAvailable, Status: stock.StockStatusAvailable.Code(),
Page: &beans.Page{PageNum: pageNum, PageSize: pageSize}, Page: &beans.Page{PageNum: pageNum, PageSize: pageSize},
}) })
if err != nil { if err != nil {
return err return err
} }
if pageNum == 1 && int(total) < stockCount { if pageNum == 1 && total < req.StockCount {
return gerror.New("可操作库存数量不足") return gerror.New("可操作库存数量不足")
} }
// 收集当前页的ID // 收集当前页的ID
for _, detail := range details { for _, detail := range details {
if detail.Id != nil && !detail.Id.IsZero() { if !g.IsEmpty(detail.Id) {
allStockIds = append(allStockIds, detail.Id) allStockIds = append(allStockIds, stockDto.DeleteSockDetailsReq{Id: detail.Id})
if len(allStockIds) >= stockCount { if len(allStockIds) >= req.StockCount {
break break
} }
} }
} }
if len(allStockIds) >= stockCount { if len(allStockIds) >= req.StockCount {
break break
} }
} }
// 根据ID批量删除库存 // 根据ID批量删除库存
delCount, err := dao.StockDetails.DeleteManyByIds(ctx, allStockIds) delCount, err := dao.StockDetails.Delete(ctx, allStockIds)
if err != nil { if err != nil {
return err return err
} }
if delCount != int64(stockCount) { if delCount != int64(req.StockCount) {
return gerror.New("删除库存数量不匹配") 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 return err
}) })
if err != nil { if err != nil {

View File

@@ -5,6 +5,7 @@
CREATE TABLE IF NOT EXISTS assets_category ( CREATE TABLE IF NOT EXISTS assets_category (
-- 基础字段 -- 基础字段
id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT取消自增 id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT取消自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID int8
creator VARCHAR(64) NOT NULL, creator VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL, updater VARCHAR(64) NOT NULL,
@@ -24,6 +25,7 @@ CREATE TABLE IF NOT EXISTS assets_category (
); );
-- 为分类表添加索引移除原uk_category_id唯一索引保留其他索引 -- 为分类表添加索引移除原uk_category_id唯一索引保留其他索引
CREATE INDEX idx_category_tenant_id ON assets_category(tenant_id);
CREATE INDEX idx_category_parent_id ON assets_category(parent_id); CREATE INDEX idx_category_parent_id ON assets_category(parent_id);
CREATE INDEX idx_category_level ON assets_category(level); CREATE INDEX idx_category_level ON assets_category(level);
CREATE INDEX idx_category_status ON assets_category(status); CREATE INDEX idx_category_status ON assets_category(status);
@@ -32,6 +34,7 @@ CREATE INDEX idx_category_is_leaf_node ON assets_category(is_leaf_node);
-- 分类表字段注释移除bid字段注释 -- 分类表字段注释移除bid字段注释
COMMENT ON TABLE assets_category IS '商品/服务分类表'; COMMENT ON TABLE assets_category IS '商品/服务分类表';
COMMENT ON COLUMN assets_category.id IS '主键ID非自增'; COMMENT ON COLUMN assets_category.id IS '主键ID非自增';
COMMENT ON COLUMN assets_category.tenant_id IS '租户ID';
COMMENT ON COLUMN assets_category.creator IS '创建人'; COMMENT ON COLUMN assets_category.creator IS '创建人';
COMMENT ON COLUMN assets_category.created_at IS '创建时间'; COMMENT ON COLUMN assets_category.created_at IS '创建时间';
COMMENT ON COLUMN assets_category.updater IS '更新人'; COMMENT ON COLUMN assets_category.updater IS '更新人';
@@ -49,12 +52,12 @@ COMMENT ON COLUMN assets_category.status IS '状态1启用/0禁用';
--------------------pgsql创建assets_category表语句--------------------------- --------------------pgsql创建assets_category表语句---------------------------
--------------------pgsql创建assets_asset表语句--------------------------- --------------------pgsql创建assets_asset表语句---------------------------
-- 资产表asset -- 资产表asset
CREATE TABLE IF NOT EXISTS assets_asset ( CREATE TABLE IF NOT EXISTS assets_asset (
-- 嵌入基础字段(复用 SQLBaseDO 结构) -- 嵌入基础字段(复用 SQLBaseDO 结构)
id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT取消自增 id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT取消自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID int8
creator VARCHAR(64) NOT NULL, creator VARCHAR(64) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL, updater VARCHAR(64) NOT NULL,
@@ -85,9 +88,10 @@ CREATE TABLE IF NOT EXISTS assets_asset (
-- 租户相关 -- 租户相关
tenant_module_type VARCHAR(64) DEFAULT '' tenant_module_type VARCHAR(64) DEFAULT ''
); );
-- 为资产表添加索引移除原uk_asset_id唯一索引保留其他索引 -- 为资产表添加索引
CREATE INDEX idx_asset_tenant_id ON assets_asset(tenant_id);
CREATE INDEX idx_asset_category_id ON assets_asset(category_id); CREATE INDEX idx_asset_category_id ON assets_asset(category_id);
CREATE INDEX idx_asset_type ON assets_asset(type); CREATE INDEX idx_asset_type ON assets_asset(type);
CREATE INDEX idx_asset_status ON assets_asset(status); CREATE INDEX idx_asset_status ON assets_asset(status);
@@ -95,9 +99,10 @@ CREATE INDEX idx_asset_online_time ON assets_asset(online_time);
CREATE INDEX idx_asset_offline_time ON assets_asset(offline_time); CREATE INDEX idx_asset_offline_time ON assets_asset(offline_time);
CREATE INDEX idx_asset_tenant_module_type ON assets_asset(tenant_module_type); CREATE INDEX idx_asset_tenant_module_type ON assets_asset(tenant_module_type);
-- 为资产表添加注释移除bid字段注释更新id注释 -- 为资产表添加注释
COMMENT ON TABLE assets_asset IS '资产主表'; COMMENT ON TABLE assets_asset IS '资产主表';
COMMENT ON COLUMN assets_asset.id IS '主键ID非自增'; COMMENT ON COLUMN assets_asset.id IS '主键ID非自增';
COMMENT ON COLUMN assets_asset.tenant_id IS '租户ID';
COMMENT ON COLUMN assets_asset.creator IS '创建人'; COMMENT ON COLUMN assets_asset.creator IS '创建人';
COMMENT ON COLUMN assets_asset.created_at IS '创建时间'; COMMENT ON COLUMN assets_asset.created_at IS '创建时间';
COMMENT ON COLUMN assets_asset.updater IS '更新人'; COMMENT ON COLUMN assets_asset.updater IS '更新人';
@@ -124,3 +129,233 @@ COMMENT ON COLUMN assets_asset.metadata IS '动态元数据(JSONB)';
COMMENT ON COLUMN assets_asset.tenant_module_type IS '租户模块类型'; 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非自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID int8
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 '' -- 租户模块类型
);
-- 外键约束
ALTER TABLE assets_asset_sku ADD CONSTRAINT fk_sku_asset_id FOREIGN KEY (asset_id) REFERENCES assets_asset(id) ON DELETE CASCADE;
ALTER TABLE assets_asset_sku ADD CONSTRAINT fk_sku_category_id FOREIGN KEY (category_id) REFERENCES assets_category(id) ON DELETE SET DEFAULT;
-- 索引
CREATE INDEX idx_sku_tenant_id ON assets_asset_sku(tenant_id);
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.tenant_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 '状态1启用 0停用';
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_asset_sku表语句---------------------------
--------------------pgsql创建assets_stock_batch表语句---------------------------
-- 库存批次表(批次管理模式专用)
CREATE TABLE IF NOT EXISTS assets_stock_batch (
-- 基础字段(继承 SQLBaseDO 通用字段)
id BIGINT PRIMARY KEY, -- 主键ID非自增
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID int8
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),
-- 核心关联字段
asset_id BIGINT NOT NULL, -- 关联资产ID
asset_sku_id BIGINT NOT NULL, -- 关联资产SKU ID
batch_no VARCHAR(64) NOT NULL, -- 批次号
batch_qty INT NOT NULL DEFAULT 0, -- 批次总数量(入库后不可变)
available_qty INT NOT NULL DEFAULT 0, -- 可用数量(实时变化)
-- 批次元数据
metadata JSONB NOT NULL DEFAULT '[]'::JSONB, -- 其他元数据:[]map[string]interface{}
-- 状态
status SMALLINT NOT NULL DEFAULT 1,
-- 订单关联
order_id BIGINT DEFAULT 0, -- 关联订单ID如果有
-- 渠道分配信息
assigned_channel VARCHAR(64) DEFAULT '', -- 分配的销售渠道
channel_sku VARCHAR(128) DEFAULT '', -- 渠道商品SKU
channel_metadata JSONB DEFAULT '{}'::JSONB, -- 渠道专属数据map[string]interface{}
allocated_at TIMESTAMP, -- 分配时间(可为空)
-- 临期管理
production_date TIMESTAMP, -- 生产日期(可为空)
expiry_date TIMESTAMP, -- 过期日期(可为空)
expiry_warning_date TIMESTAMP, -- 临期预警时间(可为空)
category_path VARCHAR(512) DEFAULT '' -- 分类路径
);
-- 外键约束
ALTER TABLE assets_stock_batch ADD CONSTRAINT fk_batch_asset_id FOREIGN KEY (asset_id) REFERENCES assets_asset(id) ON DELETE CASCADE;
ALTER TABLE assets_stock_batch ADD CONSTRAINT fk_batch_asset_sku_id FOREIGN KEY (asset_sku_id) REFERENCES assets_asset_sku(id) ON DELETE CASCADE;
-- 索引
CREATE INDEX idx_batch_tenant_id ON assets_stock_batch(tenant_id);
CREATE INDEX idx_batch_asset_id ON assets_stock_batch(asset_id);
CREATE INDEX idx_batch_asset_sku_id ON assets_stock_batch(asset_sku_id);
CREATE INDEX idx_batch_batch_no ON assets_stock_batch(batch_no);
CREATE INDEX idx_batch_status ON assets_stock_batch(status);
CREATE INDEX idx_batch_order_id ON assets_stock_batch(order_id);
CREATE INDEX idx_batch_expiry_date ON assets_stock_batch(expiry_date);
CREATE INDEX idx_batch_assigned_channel ON assets_stock_batch(assigned_channel);
CREATE INDEX idx_batch_deleted_at ON assets_stock_batch(deleted_at);
-- 唯一索引
CREATE UNIQUE INDEX uk_batch_sku_batch_no ON assets_stock_batch(asset_sku_id, batch_no) WHERE deleted_at IS NULL;
-- 注释
COMMENT ON TABLE assets_stock_batch IS '库存批次表(批次管理模式专用)';
COMMENT ON COLUMN assets_stock_batch.id IS '主键ID非自增';
COMMENT ON COLUMN assets_stock_batch.tenant_id IS '租户ID';
COMMENT ON COLUMN assets_stock_batch.creator IS '创建人';
COMMENT ON COLUMN assets_stock_batch.created_at IS '创建时间';
COMMENT ON COLUMN assets_stock_batch.updater IS '更新人';
COMMENT ON COLUMN assets_stock_batch.updated_at IS '更新时间';
COMMENT ON COLUMN assets_stock_batch.deleted_at IS '删除时间(软删)';
COMMENT ON COLUMN assets_stock_batch.asset_id IS '关联资产ID';
COMMENT ON COLUMN assets_stock_batch.asset_sku_id IS '关联资产SKU ID';
COMMENT ON COLUMN assets_stock_batch.batch_no IS '批次号';
COMMENT ON COLUMN assets_stock_batch.batch_qty IS '批次总数量(入库后不可变)';
COMMENT ON COLUMN assets_stock_batch.available_qty IS '可用数量(实时变化)';
COMMENT ON COLUMN assets_stock_batch.metadata IS '其他元数据,结构为[]map[string]interface{}';
COMMENT ON COLUMN assets_stock_batch.status IS '批次状态1-活跃/2-临期/3-过期/4-售罄)';
COMMENT ON COLUMN assets_stock_batch.order_id IS '关联订单ID如果有';
COMMENT ON COLUMN assets_stock_batch.assigned_channel IS '分配的销售渠道';
COMMENT ON COLUMN assets_stock_batch.channel_sku IS '渠道商品SKU';
COMMENT ON COLUMN assets_stock_batch.channel_metadata IS '渠道专属数据结构为map[string]interface{}';
COMMENT ON COLUMN assets_stock_batch.allocated_at IS '分配时间';
COMMENT ON COLUMN assets_stock_batch.production_date IS '生产日期';
COMMENT ON COLUMN assets_stock_batch.expiry_date IS '过期日期';
COMMENT ON COLUMN assets_stock_batch.expiry_warning_date IS '临期预警时间(有过期日期时建议填写)';
COMMENT ON COLUMN assets_stock_batch.category_path IS '分类路径';
--------------------pgsql创建assets_stock_batch表语句---------------------------
--------------------pgsql创建assets_stock_details表语句---------------------------
-- 库存明细表单件商品独立ID适配区块链虚拟资产场景
CREATE TABLE IF NOT EXISTS assets_stock_details (
-- 基础字段(继承 SQLBaseDO 通用字段)
id BIGINT PRIMARY KEY, -- 主键ID非自增单件商品独立ID适配区块链资产标识
tenant_id BIGINT NOT NULL DEFAULT 0, -- 租户ID int8
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),
-- 核心关联字段
asset_id BIGINT NOT NULL, -- 关联资产ID
asset_sku_id BIGINT NOT NULL, -- 关联资产SKU ID
status SMALLINT NOT NULL DEFAULT 1,
order_id BIGINT DEFAULT 0, -- 关联订单ID如果有
lock_expire TIMESTAMP, -- 锁定过期时间(可为空)
metadata JSONB NOT NULL DEFAULT '[]'::JSONB, -- 其他元数据:[]map[string]interface{}
token_id VARCHAR(256) DEFAULT '', -- 区块链TokenID如果有
-- 渠道分配信息
assigned_channel VARCHAR(64) DEFAULT '', -- 分配的销售渠道
channel_sku VARCHAR(128) DEFAULT '', -- 渠道商品SKU
channel_metadata JSONB DEFAULT '{}'::JSONB, -- 渠道专属数据map[string]interface{}
allocated_at TIMESTAMP, -- 分配时间(可为空)
category_path VARCHAR(512) DEFAULT '' -- 分类路径
);
-- 外键约束
ALTER TABLE assets_stock_details ADD CONSTRAINT fk_details_asset_id FOREIGN KEY (asset_id) REFERENCES assets_asset(id) ON DELETE CASCADE;
ALTER TABLE assets_stock_details ADD CONSTRAINT fk_details_asset_sku_id FOREIGN KEY (asset_sku_id) REFERENCES assets_asset_sku(id) ON DELETE CASCADE;
-- 索引
CREATE INDEX idx_details_tenant_id ON assets_stock_details(tenant_id);
CREATE INDEX idx_details_asset_id ON assets_stock_details(asset_id);
CREATE INDEX idx_details_asset_sku_id ON assets_stock_details(asset_sku_id);
CREATE INDEX idx_details_status ON assets_stock_details(status);
CREATE INDEX idx_details_order_id ON assets_stock_details(order_id);
CREATE INDEX idx_details_lock_expire ON assets_stock_details(lock_expire);
CREATE INDEX idx_details_token_id ON assets_stock_details(token_id);
CREATE INDEX idx_details_assigned_channel ON assets_stock_details(assigned_channel);
CREATE INDEX idx_details_deleted_at ON assets_stock_details(deleted_at);
-- 唯一索引
CREATE UNIQUE INDEX uk_details_token_id ON assets_stock_details(token_id) WHERE deleted_at IS NULL AND token_id != '';
-- 注释
COMMENT ON TABLE assets_stock_details IS '库存明细表单件商品独立ID用于区块链虚拟资产管理';
COMMENT ON COLUMN assets_stock_details.id IS '主键ID非自增单件商品独立唯一标识';
COMMENT ON COLUMN assets_stock_details.tenant_id IS '租户ID';
COMMENT ON COLUMN assets_stock_details.creator IS '创建人';
COMMENT ON COLUMN assets_stock_details.created_at IS '创建时间';
COMMENT ON COLUMN assets_stock_details.updater IS '更新人';
COMMENT ON COLUMN assets_stock_details.updated_at IS '更新时间';
COMMENT ON COLUMN assets_stock_details.deleted_at IS '删除时间(软删)';
COMMENT ON COLUMN assets_stock_details.asset_id IS '关联资产ID';
COMMENT ON COLUMN assets_stock_details.asset_sku_id IS '关联资产SKU ID';
COMMENT ON COLUMN assets_stock_details.status IS '库存状态1-可用/2-已售出/3-预留/4-锁定)';
COMMENT ON COLUMN assets_stock_details.order_id IS '关联订单ID如果有';
COMMENT ON COLUMN assets_stock_details.lock_expire IS '锁定过期时间(锁定状态下有效)';
COMMENT ON COLUMN assets_stock_details.metadata IS '其他元数据,结构为[]map[string]interface{}';
COMMENT ON COLUMN assets_stock_details.token_id IS '区块链TokenID虚拟资产唯一标识可为空';
COMMENT ON COLUMN assets_stock_details.assigned_channel IS '分配的销售渠道';
COMMENT ON COLUMN assets_stock_details.channel_sku IS '渠道商品SKU';
COMMENT ON COLUMN assets_stock_details.channel_metadata IS '渠道专属数据结构为map[string]interface{}';
COMMENT ON COLUMN assets_stock_details.allocated_at IS '分配时间';
COMMENT ON COLUMN assets_stock_details.category_path IS '分类路径';
--------------------pgsql创建assets_stock_details表语句---------------------------