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