From f30141679ca0a5ed37bed1da7cfbf98fca393ddb Mon Sep 17 00:00:00 2001 From: qhd <1766646056@qq.com> Date: Thu, 19 Mar 2026 17:45:06 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E6=A8=A1=E5=9E=8B=E4=B8=8EDAO=E5=B1=82=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yml | 1 + consts/asset/asset_sku_status.go | 14 +-- consts/asset/asset_status.go | 14 +-- consts/asset/attribute_type.go | 12 +-- dao/asset/asset_dao.go | 109 +++++++++---------- dao/asset/asset_sku_dao.go | 147 +++++++++++--------------- dao/asset/category_dao.go | 76 +++++++------ dao/stock/stock_details_dao.go | 2 +- model/dto/asset/asset_dto.go | 117 ++++++++++---------- model/dto/asset/asset_sku_dto.go | 52 +++++---- model/dto/asset/category_dto.go | 46 ++++---- model/dto/enum/enum_dto.go | 3 +- model/dto/stock/stock_batch_dto.go | 10 +- model/dto/stock/stock_details_dto.go | 4 +- model/dto/stock/stock_manage_dto.go | 10 +- model/entity/asset/asset.go | 82 ++++++++++---- model/entity/asset/asset_sku.go | 90 +++++++++++----- model/entity/asset/category.go | 40 ++++--- model/entity/stock/stock_details.go | 4 +- service/asset/asset_service.go | 128 ++++++++++------------ service/asset/asset_sku_service.go | 42 ++++---- service/asset/category_service.go | 72 ++++++------- service/stock/stock_manage_service.go | 49 ++++----- update.sql | 46 +++----- 24 files changed, 570 insertions(+), 600 deletions(-) diff --git a/config.yml b/config.yml index 39aa463..78ca851 100644 --- a/config.yml +++ b/config.yml @@ -1,6 +1,7 @@ server: address: ":3003" name: "assets" + workerId: 1 #logPath: "resource/log/server" logStdout: true errorStack: true diff --git a/consts/asset/asset_sku_status.go b/consts/asset/asset_sku_status.go index 496906b..5de2d6d 100644 --- a/consts/asset/asset_sku_status.go +++ b/consts/asset/asset_sku_status.go @@ -1,17 +1,9 @@ package consts // AssetSkuStatus SKU状态枚举 -type AssetSkuStatus int -const ( - AssetSkuStatusActive AssetSkuStatus = 1 // 启用 - AssetSkuStatusInactive AssetSkuStatus = 0 // 停用 -) +type AssetSkuStatusType *int -// GetAllSkuStatuses 获取所有SKU状态 -func GetAllSkuStatuses() []AssetSkuStatus { - return []AssetSkuStatus{ - AssetSkuStatusActive, - AssetSkuStatusInactive, - } +type AssetSkuStatus struct { + Status AssetSkuStatusType } diff --git a/consts/asset/asset_status.go b/consts/asset/asset_status.go index dd8b76a..7503924 100644 --- a/consts/asset/asset_status.go +++ b/consts/asset/asset_status.go @@ -1,17 +1,9 @@ package consts // AssetStatus 资产状态枚举 -type AssetStatus int -const ( - AssetStatusActive AssetStatus = 1 // 启用 - AssetStatusInactive AssetStatus = 0 // 停用 -) +type AssetStatusType *int -// GetAllAssetStatuses 获取所有资产状态 -func GetAllAssetStatuses() []AssetStatus { - return []AssetStatus{ - AssetStatusActive, - AssetStatusInactive, - } +type AssetStatus struct { + Status AssetStatusType } diff --git a/consts/asset/attribute_type.go b/consts/asset/attribute_type.go index d8c971c..16d745b 100644 --- a/consts/asset/attribute_type.go +++ b/consts/asset/attribute_type.go @@ -4,9 +4,7 @@ package consts type AttributeType string const ( - AttributeTypeText AttributeType = "text" // 文本 - //AttributeTypeNumber AttributeType = "number" // 数字 - //AttributeTypeDate AttributeType = "date" // 日期 + AttributeTypeText AttributeType = "text" // 文本 AttributeTypeSelect AttributeType = "select" // 单选 AttributeTypeMultiSelect AttributeType = "multi_select" // 多选 ) @@ -15,8 +13,6 @@ const ( func GetAllAttributeTypes() []AttributeType { return []AttributeType{ AttributeTypeText, - //AttributeTypeNumber, - //AttributeTypeDate, AttributeTypeSelect, AttributeTypeMultiSelect, } @@ -29,9 +25,7 @@ type AttrTypeKeyValue struct { // 定义枚举实例(Key-Value 绑定),相当于改造后的常量 var ( - AttrTypeTextKeyValue = AttrTypeKeyValue{Key: AttributeTypeText, Value: "文本"} - //AttrTypeNumberKeyValue = AttrTypeKeyValue{Key: AttributeTypeNumber, Value: "数字"} - //AttrTypeDateKeyValue = AttrTypeKeyValue{Key: AttributeTypeDate, Value: "日期"} + AttrTypeTextKeyValue = AttrTypeKeyValue{Key: AttributeTypeText, Value: "文本"} AttrTypeSelectKeyValue = AttrTypeKeyValue{Key: AttributeTypeSelect, Value: "单选"} AttrTypeMultiSelectKeyValue = AttrTypeKeyValue{Key: AttributeTypeMultiSelect, Value: "多选"} ) @@ -39,8 +33,6 @@ var ( func GetAllAttrTypeKeyValue() []AttrTypeKeyValue { return []AttrTypeKeyValue{ AttrTypeTextKeyValue, - //AttrTypeNumberKeyValue, - //AttrTypeDateKeyValue, AttrTypeSelectKeyValue, AttrTypeMultiSelectKeyValue, } diff --git a/dao/asset/asset_dao.go b/dao/asset/asset_dao.go index 150ad7a..a571ca6 100644 --- a/dao/asset/asset_dao.go +++ b/dao/asset/asset_dao.go @@ -19,92 +19,79 @@ type assetDao struct { // Insert 插入资产 func (d *assetDao) Insert(ctx context.Context, req *dto.CreateAssetReq) (id int64, err error) { - var result entity.Asset - if err = gconv.Struct(req, &result); err != nil { + var res *entity.Asset + if err = gconv.Struct(req, &res); err != nil { return } - return gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Data(&result).InsertAndGetId() -} - -// GetOne 获取单个资产 -func (d *assetDao) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *entity.Asset, err error) { - err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Scan(&res) - return + r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Data(&res).Insert() + if err != nil { + return + } + return r.LastInsertId() } // Update 更新资产 -func (d *assetDao) Update(ctx context.Context, req *dto.UpdateAssetReq) (err error) { - data := g.Map{ - "name": req.Name, - "description": req.Description, - "type": req.Type, - "category_id": req.CategoryId, - "image_url": req.ImageURL, - "images": req.Images, - "status": req.Status, - "online_time": req.OnlineTime, - "offline_time": req.OfflineTime, - "physical_asset_config": req.PhysicalAssetConfig, - "service_asset_config": req.ServiceAssetConfig, - "virtual_asset_config": req.VirtualAssetConfig, - "metadata": req.Metadata, +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() + if err != nil { + return } - _, err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Update(data) - return + return r.RowsAffected() } -// DeleteFake 删除资产-根据id进行假删 -func (d *assetDao) DeleteFake(ctx context.Context, req *dto.DeleteAssetReq) (err error) { - _, err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", req.Id).Update(g.Map{ - "is_deleted": true, - }) - return +// Delete 删除资产-根据id进行假删 +func (d *assetDao) Delete(ctx context.Context, req *dto.DeleteAssetReq) (rows int64, err error) { + r, err := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Where(entity.AssetCol.Id, req.Id).Delete() + if err != nil { + return + } + return r.RowsAffected() } -// GetOneById 通过ID获取单个资产(内部使用uint64) -func (d *assetDao) GetOneById(ctx context.Context, id uint64) (res *entity.Asset, err error) { - err = gfdb.DB(ctx).Model(ctx, public.AssetCollection).Ctx(ctx).Where("id", id).Scan(&res) +// 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() + if err != nil { + return + } + err = r.Struct(&res) return } // Count 获取资产数量 -func (d *assetDao) Count(ctx context.Context, req *dto.ListAssetReq) (count int64, err error) { - m := d.buildListFilter(ctx, req) - c, err := m.Count() - return int64(c), err +func (d *assetDao) Count(ctx context.Context, req *dto.ListAssetReq) (count int, err error) { + return d.buildListFilter(ctx, req).Count() } // List 获取资产列表 -func (d *assetDao) List(ctx context.Context, req *dto.ListAssetReq) (res []entity.Asset, total int, err error) { - m := d.buildListFilter(ctx, req) +func (d *assetDao) List(ctx context.Context, req *dto.ListAssetReq, fields ...string) (res []entity.Asset, total int, err error) { + model := d.buildListFilter(ctx, req) + model.Fields(fields) + model.OrderDesc(entity.AssetCol.CreatedAt) if req.Page != nil { - m = m.Page(int(req.Page.PageNum), int(req.Page.PageSize)) + model.Page(int(req.Page.PageNum), int(req.Page.PageSize)) } - err = m.ScanAndCount(&res, &total, false) + r, total, err := model.AllAndCount(false) + if err != nil { + return + } + err = r.Structs(&res) return } // buildListFilter 构建列表查询的过滤条件 func (d *assetDao) buildListFilter(ctx context.Context, req *dto.ListAssetReq) *gdb.Model { - m := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Cache(ctx).Where("is_deleted", false) - - if !g.IsEmpty(req.Name) { - m = m.Where("name", req.Name) - } - if !g.IsEmpty(req.Type) { - m = m.Where("type", req.Type) - } - if !g.IsEmpty(req.CategoryId) { - m = m.Where("category_id", req.CategoryId) - } - if !g.IsEmpty(req.Status) { - m = m.Where("status", req.Status) + model := gfdb.DB(ctx).Model(ctx, public.AssetCollection).Model + if !g.IsEmpty(req.Keyword) { + model.WhereLike(entity.AssetCol.Name, "%"+req.Keyword+"%") } if !g.IsEmpty(req.CategoryPath) { - m = m.WhereLike("category_path", req.CategoryPath+"%") + model.WhereLike(entity.AssetCol.CategoryPath, req.CategoryPath+"%") } - if !g.IsEmpty(req.Keyword) { - m = m.WhereLike("name", "%"+req.Keyword+"%") - } - return m + model.Where(entity.AssetCol.Name, req.Name) + model.Where(entity.AssetCol.Type, req.Type) + model.Where(entity.AssetCol.CategoryId, req.CategoryId) + model.Where(entity.AssetCol.Status, req.Status) + model.OmitEmptyWhere() + return model } diff --git a/dao/asset/asset_sku_dao.go b/dao/asset/asset_sku_dao.go index 445cad5..522ad0e 100644 --- a/dao/asset/asset_sku_dao.go +++ b/dao/asset/asset_sku_dao.go @@ -6,11 +6,10 @@ import ( "assets/model/entity/asset" "context" - "gitea.com/red-future/common/beans" - "gitea.com/red-future/common/db/mongo" - "gitea.com/red-future/common/utils" + "gitea.com/red-future/common/db/gfdb" + "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" - "go.mongodb.org/mongo-driver/v2/bson" + "github.com/gogf/gf/v2/util/gconv" ) var AssetSku = new(assetSku) @@ -19,112 +18,94 @@ type assetSku struct { } // Insert 插入SKU -func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (ids []any, err error) { - var result *entity.AssetSku - if err = utils.Struct(req, &result); err != nil { +func (d *assetSku) Insert(ctx context.Context, req *dto.CreateAssetSkuReq) (id int64, err error) { + var res *entity.AssetSku + if err = gconv.Struct(req, &res); err != nil { return } - ids, err = mongo.DB().Insert(ctx, []interface{}{&result}, public.AssetSkuCollection) - return -} - -// Update 更新SKU -func (d *assetSku) Update(ctx context.Context, req *dto.UpdateAssetSkuReq) (err error) { - buildUpdateData, err := mongo.BuildUpdateData(ctx, req) + r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Ctx(ctx).Data(&res).Insert() if err != nil { return } - filter := bson.M{"_id": req.Id} - update := bson.M{"$set": buildUpdateData} - if !g.IsEmpty(req.Stock) { - // 从$set中移除stock字段避免$set和$inc冲突 - delete(buildUpdateData, "stock") - update = bson.M{ - "$inc": bson.M{ - "stock": req.Stock, - }, - } - if len(buildUpdateData) > 0 { - update["$set"] = buildUpdateData - } - } - _, err = mongo.DB().Update(ctx, filter, update, public.AssetSkuCollection) - return + return r.LastInsertId() } -// DeleteFake 删除SKU-根据id进行假删 -func (d *assetSku) DeleteFake(ctx context.Context, req *dto.DeleteAssetSkuReq) (err error) { - filter := bson.M{"_id": req.Id} - _, err = mongo.DB().DeleteSoft(ctx, filter, public.AssetSkuCollection) - return +// 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() + if err != nil { + return + } + return r.RowsAffected() +} + +// Delete 删除SKU-根据id进行假删 +func (d *assetSku) Delete(ctx context.Context, req *dto.DeleteAssetSkuReq) (rows int64, err error) { + r, err := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Where(entity.AssetSkuCol.Id, req.Id).Delete() + if err != nil { + return + } + return r.RowsAffected() } // GetOne 获取单个SKU -func (d *assetSku) GetOne(ctx context.Context, req *dto.GetAssetSkuReq, noTenantId bool) (res *entity.AssetSku, err error) { - filter := bson.M{"_id": req.Id} - if noTenantId { - err = mongo.DB().NoTenantId().FindOne(ctx, filter, &res, public.AssetSkuCollection) - } else { - err = mongo.DB().FindOne(ctx, filter, &res, public.AssetSkuCollection) +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() + if err != nil { + return } + err = r.Struct(&res) return } // GetListByAssetIdExcludeCurrentSku 根据资产ID获取SKU列表并且排除当前SKU -func (d *assetSku) GetListByAssetIdExcludeCurrentSku(ctx context.Context, assetId *bson.ObjectID, req *dto.ListAssetSkuReq) (res []entity.AssetSku, total int64, err error) { - filter := bson.M{"assetId": assetId, "_id": bson.M{"$ne": req.Id}} - total, err = mongo.DB().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy) +func (d *assetSku) GetListByAssetIdExcludeCurrentSku(ctx context.Context, assetId int64, req *dto.ListAssetSkuReq, fields ...string) (res []entity.AssetSku, total int, err error) { + model := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection) + model.Fields(fields) + model.Where(entity.AssetSkuCol.AssetId, assetId) + model.WhereNot(entity.AssetSkuCol.Id, req.Id) + 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 } // List 获取SKU列表 -func (d *assetSku) List(ctx context.Context, req *dto.ListAssetSkuReq, noTenantId bool) (res []entity.AssetSku, total int64, err error) { - // 构建查询过滤条件 - filter, err := d.buildListFilter(ctx, req) +func (d *assetSku) List(ctx context.Context, req *dto.ListAssetSkuReq, fields ...string) (res []entity.AssetSku, total int, err error) { + model := d.buildListFilter(ctx, req) + model.Fields(fields) + model.OrderAsc(entity.AssetSkuCol.Sort) + model.OrderDesc(entity.AssetSkuCol.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 } - // 排序处理 - req.OrderBy = []beans.OrderBy{ - {Field: "sort", Order: beans.Asc}, - {Field: "createdAt", Order: beans.Desc}, - } - if noTenantId { - total, err = mongo.DB().NoTenantId().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy) - } else { - total, err = mongo.DB().Find(ctx, filter, &res, public.AssetSkuCollection, req.Page, req.OrderBy) - } + err = r.Structs(&res) return } // buildListFilter 构建列表查询的过滤条件 -func (d *assetSku) buildListFilter(ctx context.Context, req *dto.ListAssetSkuReq) (filter bson.M, err error) { - _ = ctx - filter = bson.M{} - if !g.IsEmpty(req.AssetId) { - filter["assetId"] = req.AssetId - } - if !g.IsEmpty(req.Status) { - filter["status"] = req.Status +func (d *assetSku) buildListFilter(ctx context.Context, req *dto.ListAssetSkuReq) *gdb.Model { + model := gfdb.DB(ctx).Model(ctx, public.AssetSkuCollection).Model + if !g.IsEmpty(req.Keyword) { + model.WhereLike(entity.AssetCol.Name, "%"+req.Keyword+"%") + model.WhereOrLike(entity.AssetSkuCol.SkuName, "%"+req.Keyword+"%") } if !g.IsEmpty(req.CategoryPath) { - filter["categoryPath"] = bson.M{"$regex": "^" + req.CategoryPath, "$options": "i"} + model.WhereLike(entity.AssetSkuCol.CategoryPath, req.CategoryPath+"%") } - if !g.IsEmpty(req.Keyword) { - orConditions := bson.A{ - bson.M{"skuName": bson.M{"$regex": req.Keyword, "$options": "i"}}, - bson.M{"assetName": bson.M{"$regex": req.Keyword, "$options": "i"}}, - } - filter["$or"] = orConditions - } - if req.MinPrice > 0 { - filter["price"] = bson.M{"$gte": req.MinPrice} - } - if req.MaxPrice > 0 { - if filter["price"] == nil { - filter["price"] = bson.M{} - } - filter["price"].(bson.M)["$lte"] = req.MaxPrice - } - return + 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) + model.OmitEmptyWhere() + return model } diff --git a/dao/asset/category_dao.go b/dao/asset/category_dao.go index a39d63d..202db1a 100644 --- a/dao/asset/category_dao.go +++ b/dao/asset/category_dao.go @@ -8,10 +8,8 @@ import ( "gitea.com/red-future/common/db/gfdb" "github.com/gogf/gf/v2/database/gdb" - "github.com/gogf/gf/v2/util/gconv" - "github.com/gogf/gf/v2/util/guid" - "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/util/gconv" ) var Category = new(category) @@ -20,63 +18,65 @@ type category struct { } // Insert 插入分类 -func (d *category) Insert(ctx context.Context, req *dto.CreateCategoryReq) (res *entity.Category, err error) { +func (d *category) Insert(ctx context.Context, req *dto.CreateCategoryReq) (id int64, err error) { + var res *entity.Category if err = gconv.Struct(req, &res); err != nil { return } - res.Bid = guid.S() - _, err = gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Insert(&res) - return res, nil + r, err := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Insert(&res) + if err != nil { + return + } + return r.LastInsertId() } // Update 更新分类 -func (d *category) Update(ctx context.Context, req *dto.UpdateCategoryReq) (err error) { - model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Data(gconv.Map(&req)).OmitEmpty() - if !g.IsEmpty(req.Bid) { - model.Where("bid", req.Bid) +func (d *category) Update(ctx context.Context, req *dto.UpdateCategoryReq) (rows int64, err error) { + r, err := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Data(&req).OmitEmpty().Where(entity.CategoryCol.Id, req.Id).Update() + if err != nil { + return } - if !g.IsEmpty(req.Id) { - model.Where("id", req.Id) + return r.RowsAffected() +} + +// Delete 删除分类-根据id及父id进行假删 +func (d *category) Delete(ctx context.Context, req *dto.DeleteCategoryReq) (rows int64, err error) { + r, err := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Where(entity.CategoryCol.Id, req.Id).Delete() + if err != nil { + return } - _, err = model.Update() - return + return r.RowsAffected() } // GetOne 获取单个分类 -func (d *category) GetOne(ctx context.Context, req *dto.GetCategoryReq, fields ...string) (category *entity.Category, err error) { - model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection) - if !g.IsEmpty(req.Bid) { - model.Where(entity.CategoryCol.Bid, req.Bid) +func (d *category) GetOne(ctx context.Context, req *dto.GetCategoryReq, fields ...string) (res *entity.Category, err error) { + r, err := gfdb.DB(ctx).Model(ctx, public.CategoryCollection).Where(entity.CategoryCol.Id, req.Id).Fields(fields).One() + if err != nil { + return } - if !g.IsEmpty(req.Id) { - model.Where(entity.CategoryCol.Id, req.Id) - } - res, err := model.Fields(fields).One() - err = res.Struct(&category) - return -} - -// DeleteFake 删除分类-根据id及父id进行假删 -func (d *category) DeleteFake(ctx context.Context, req *dto.DeleteCategoryReq) (err error) { - model := gfdb.DB(ctx).Model(ctx, public.CategoryCollection) - model.Where(entity.CategoryCol.Bid, req.Bid) - _, err = model.Delete() + err = r.Struct(&res) return } // Count 根据条件统计分类数量 -func (d *category) Count(ctx context.Context, req *dto.ListCategoryReq) (count int64, err error) { - m := d.buildListFilter(ctx, req) - c, err := m.Count() - return int64(c), err +func (d *category) Count(ctx context.Context, req *dto.ListCategoryReq) (count int, err error) { + return d.buildListFilter(ctx, req).Count() } // List 获取分类列表 func (d *category) List(ctx context.Context, req *dto.ListCategoryReq, fields ...string) (res []entity.Category, total int, err error) { model := d.buildListFilter(ctx, req) model.Fields(fields) + model.OrderAsc(entity.CategoryCol.Sort) + model.OrderDesc(entity.CategoryCol.CreatedAt) + if req.Page != nil { + model.Page(int(req.Page.PageNum), int(req.Page.PageSize)) + } r, total, err := model.AllAndCount(false) - err = gconv.Structs(r.List(), &res) + if err != nil { + return + } + err = r.Structs(&res) return } @@ -88,8 +88,6 @@ func (d *category) buildListFilter(ctx context.Context, req *dto.ListCategoryReq } model.Where(entity.CategoryCol.ParentId, req.ParentId) model.Where(entity.CategoryCol.Status, req.Status) - model.OrderAsc(entity.CategoryCol.Sort) - model.OrderDesc(entity.CategoryCol.CreatedAt) model.OmitEmptyWhere() return model } diff --git a/dao/stock/stock_details_dao.go b/dao/stock/stock_details_dao.go index df29760..54dcf16 100644 --- a/dao/stock/stock_details_dao.go +++ b/dao/stock/stock_details_dao.go @@ -39,7 +39,7 @@ func (d *stockDetails) DeleteManyByIds(ctx context.Context, allStockIds []*bson. } // GetStockCountBySkuId 获取库存数根据SKU ID -func (d *stockDetails) GetStockCountBySkuId(ctx context.Context, assetSkuId *bson.ObjectID) (total int64, err error) { +func (d *stockDetails) GetStockCountBySkuId(ctx context.Context, assetSkuId int64) (total int64, err error) { // 构建查询过滤条件 filter := bson.M{} filter["assetSkuId"] = assetSkuId diff --git a/model/dto/asset/asset_dto.go b/model/dto/asset/asset_dto.go index 1f4287d..1584e06 100644 --- a/model/dto/asset/asset_dto.go +++ b/model/dto/asset/asset_dto.go @@ -5,32 +5,28 @@ import ( "assets/consts/stock" "assets/model/config" enumDto "assets/model/dto/enum" - entity "assets/model/entity/asset" - "time" "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" ) // CreateAssetReq 创建资产请求 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 uint64 `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 *time.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"` - OfflineTime *time.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.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)"` // 类型专用配置 - 实物资产配置 PhysicalAssetConfig *config.PhysicalAssetConfig `json:"physicalAssetConfig"` // 类型专用配置 - 服务资产配置 @@ -45,86 +41,83 @@ type CreateAssetReq struct { // CreateAssetRes 创建资产响应 type CreateAssetRes struct { - Id uint64 `json:"id" dc:"资产ID"` + Id int64 `json:"id" dc:"资产ID"` } // ListAssetReq 获取资产列表请求 type ListAssetReq struct { g.Meta `path:"/listAssets" method:"get" tags:"资产管理" summary:"获取资产列表" dc:"分页查询资产列表,支持多条件筛选"` *beans.Page - OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"` - Name string `json:"name" dc:"资产名称"` - Type consts.AssetType `json:"type" dc:"资产类型"` - CategoryId string `json:"categoryId" dc:"分类ID"` - CategoryPath string `json:"categoryPath" dc:"分类路径"` - Status *consts.AssetStatus `json:"status" dc:"状态"` - Keyword string `json:"keyword" dc:"关键词搜索"` + Name string `json:"name" dc:"资产名称"` + Type consts.AssetType `json:"type" dc:"资产类型"` + CategoryId int64 `json:"categoryId" dc:"分类ID"` + CategoryPath string `json:"categoryPath" dc:"分类路径"` + Status consts.AssetStatusType `json:"status" dc:"状态"` + TenantModuleType beans.TenantModuleType `json:"tenantModuleType" dc:"租户模块类型"` + Keyword string `json:"keyword" dc:"关键词搜索"` } // ListAssetRes 获取资产列表响应 type ListAssetRes struct { - List []AssetListItem `json:"list" dc:"资产列表"` - Total int `json:"total" dc:"总数"` + List []AssetItem `json:"list" dc:"资产列表"` + Total int `json:"total" dc:"总数"` } -type AssetListItem struct { - // 基础信息 - Id uint64 `json:"id"` // 资产ID - Name string `json:"name"` // 资产名称 - Type consts.AssetType `json:"type"` // 资产类型:physical实物/virtual虚拟/service服务 - TypeName string `json:"typeName"` // 资产类型:physical实物/virtual虚拟/service服务 - CategoryId uint64 `json:"categoryId"` // 分类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:"更新时间"` +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:"更新时间"` } // GetAssetReq 获取资产详情请求 type GetAssetReq struct { g.Meta `path:"/getAsset" method:"get" tags:"资产管理" summary:"获取资产详情" dc:"获取资产详情"` - Id *bson.ObjectID `json:"id" v:"required" dc:"资产ID"` + Id int64 `json:"id" v:"required" dc:"资产ID"` } // GetAssetRes 获取资产详情响应 type GetAssetRes struct { - *entity.Asset + *AssetItem CategoryName string `json:"categoryName" dc:"分类名称"` ImgAddressPrefix string `json:"imgAddressPrefix"` } // GetAssetAndSkuReq 获取资产和Sku详情请求 type GetAssetAndSkuReq struct { - g.Meta `path:"/getAssetAndSku" method:"get" tags:"资产管理" summary:"获取资产和SKU详情" dc:"获取资产和SKU详情"` - AssetId *bson.ObjectID `json:"assetId" v:"required" dc:"资产ID"` + g.Meta `path:"/getAssetAndSku" method:"get" tags:"资产管理" summary:"获取资产和SKU详情" dc:"获取资产和SKU详情"` + Id int64 `json:"id" v:"required" dc:"资产ID"` } // GetAssetAndSkuRes 获取资产详情响应 type GetAssetAndSkuRes struct { - *entity.Asset - Skus []entity.AssetSku `json:"skus" dc:"SKU列表"` + *AssetItem + Skus []AssetSkuItem `json:"skus" dc:"SKU列表"` TenantModuleType []enumDto.KeyValue `json:"tenantModuleType" dc:"租户模块类型"` ImgAddressPrefix string `json:"imgAddressPrefix"` } // UpdateAssetReq 更新资产请求 type UpdateAssetReq struct { - g.Meta `path:"/updateAsset" method:"put" tags:"资产管理" summary:"更新资产" dc:"更新资产信息"` - Id *bson.ObjectID `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 *bson.ObjectID `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 *time.Time `json:"onlineTime,omitempty" dc:"上线时间(格式:2006-01-02 15:04:05)"` - OfflineTime *time.Time `json:"offlineTime,omitempty" dc:"下线时间(格式:2006-01-02 15:04:05)"` + 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)"` // 类型专用配置 - 实物资产配置 PhysicalAssetConfig *config.PhysicalAssetConfig `json:"physicalAssetConfig"` // 类型专用配置 - 服务资产配置 @@ -138,12 +131,12 @@ type UpdateAssetReq struct { // UpdateAssetStatusReq 更新资产状态请求 type UpdateAssetStatusReq struct { g.Meta `path:"/updateAssetStatus" method:"put" tags:"资产管理" summary:"更新资产状态" dc:"更新资产状态"` - Id *bson.ObjectID `json:"id" v:"required" dc:"资产ID"` - Status *consts.AssetStatus `json:"status" v:"required|in:1,0" dc:"状态:1启用/0停用"` + Id int64 `json:"id" v:"required" dc:"资产ID"` + Status consts.AssetStatusType `json:"status" v:"required|in:1,0" dc:"状态:1启用/0停用"` } // DeleteAssetReq 删除资产请求 type DeleteAssetReq struct { g.Meta `path:"/deleteAsset" method:"delete" tags:"资产管理" summary:"删除资产" dc:"删除资产"` - Id *bson.ObjectID `json:"id" v:"required" dc:"资产ID"` + Id int64 `json:"id" v:"required" dc:"资产ID"` } diff --git a/model/dto/asset/asset_sku_dto.go b/model/dto/asset/asset_sku_dto.go index 49cc343..6996182 100644 --- a/model/dto/asset/asset_sku_dto.go +++ b/model/dto/asset/asset_sku_dto.go @@ -8,14 +8,13 @@ import ( "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" ) // CreateAssetSkuReq 创建SKU请求 type CreateAssetSkuReq struct { g.Meta `path:"/createAssetSku" method:"post" tags:"SKU管理" summary:"创建SKU" dc:"创建新的资产SKU"` - AssetId *bson.ObjectID `json:"assetId" v:"required" dc:"关联资产ID"` + AssetId int64 `json:"assetId" v:"required" dc:"关联资产ID"` AssetName string `json:"assetName" v:"required" dc:"关联资产名称"` SkuName string `json:"skuName" v:"required" dc:"SKU名称"` SpecsCount int `json:"specsCount" v:"required|min:1" dc:"规格数量"` @@ -24,24 +23,24 @@ 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.AssetSkuStatus `json:"status" v:"required|in:1,0" dc:"状态"` + Status consts.AssetSkuStatusType `json:"status" v:"required|in:1,0" dc:"状态"` UnlimitedStock bool `json:"unlimitedStock" v:"required" dc:"是否无库存限制"` StockMode stock.StockMode `json:"stockMode" dc:"库存管理模式:1-明细模式 2-批次模式"` - CategoryId *bson.ObjectID `json:"categoryId" dc:"分类ID"` + CategoryId int64 `json:"categoryId" dc:"分类ID"` CategoryPath string `json:"categoryPath" dc:"分类路径"` TenantModuleType beans.TenantModuleType `json:"tenantModuleType" dc:"租户模块类型"` } // CreateAssetSkuRes 创建SKU响应 type CreateAssetSkuRes struct { - Id *bson.ObjectID `json:"id" dc:"SKU ID"` + Id int64 `json:"id" dc:"SKU ID"` } // UpdateAssetSkuReq 更新SKU请求 type UpdateAssetSkuReq struct { g.Meta `path:"/updateAssetSku" method:"put" tags:"SKU管理" summary:"更新SKU" dc:"更新SKU信息"` - Id *bson.ObjectID `json:"id" v:"required" dc:"SKU ID"` + Id int64 `json:"id" v:"required" dc:"SKU ID"` SkuName string `json:"skuName" dc:"SKU名称"` SpecsCount int `json:"specsCount" dc:"规格数量"` SpecsUnit *entity.SpecsUnitKeyValue `json:"specsUnit" dc:"规格单位"` @@ -50,36 +49,36 @@ type UpdateAssetSkuReq struct { Price int `json:"price" dc:"价格(分为单位)"` Sort int `json:"sort" dc:"排序"` Stock int `json:"stock" dc:"库存数量"` - Status *consts.AssetSkuStatus `json:"status" dc:"状态"` + Status consts.AssetSkuStatusType `json:"status" dc:"状态"` } // DeleteAssetSkuReq 删除SKU请求 type DeleteAssetSkuReq struct { g.Meta `path:"/deleteAssetSku" method:"delete" tags:"SKU管理" summary:"删除SKU" dc:"删除SKU"` - Id *bson.ObjectID `json:"id" v:"required" dc:"SKU ID"` + Id int64 `json:"id" v:"required" dc:"SKU ID"` } // GetAssetSkuModuleReq 获取SKU详情请求 type GetAssetSkuModuleReq struct { g.Meta `path:"/getAssetSkuModule" method:"get" tags:"SKU管理" summary:"获取SKU模块详情" dc:"获取SKU模块详情"` - Id *bson.ObjectID `json:"id" v:"required" dc:"SKU ID"` + Id int64 `json:"id" v:"required" dc:"SKU ID"` } // GetAssetSkuModuleRes 获取SKU详情响应 type GetAssetSkuModuleRes struct { - AssetId *bson.ObjectID `json:"assetId"` - ExpireAt *gtime.Time `json:"expireAt"` + AssetId int64 `json:"assetId"` + ExpireAt *gtime.Time `json:"expireAt"` } // GetAssetSkuReq 获取SKU详情请求 type GetAssetSkuReq struct { g.Meta `path:"/getAssetSku" method:"get" tags:"SKU管理" summary:"获取SKU详情" dc:"获取SKU详情"` - Id *bson.ObjectID `json:"id" v:"required" dc:"SKU ID"` + Id int64 `json:"id" v:"required" dc:"SKU ID"` } // GetAssetSkuRes 获取SKU详情响应 type GetAssetSkuRes struct { - *entity.AssetSku + *AssetSkuItem ImgAddressPrefix string `json:"imgAddressPrefix"` } @@ -87,25 +86,24 @@ type GetAssetSkuRes struct { type ListAssetSkuReq struct { g.Meta `path:"/listAssetSkus" method:"get" tags:"SKU管理" summary:"获取SKU列表" dc:"分页查询SKU列表,支持多条件筛选"` *beans.Page - OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"` - Id *bson.ObjectID `json:"id" dc:"SKU ID"` - AssetId *bson.ObjectID `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:"分类路径"` + 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:"分类路径"` } // ListAssetSkuRes 获取SKU列表响应 type ListAssetSkuRes struct { - List []*AssetSkuListResItem `json:"list" dc:"SKU列表"` - Total int64 `json:"total" dc:"总数"` + List []AssetSkuItem `json:"list" dc:"SKU列表"` + Total int `json:"total" dc:"总数"` } -type AssetSkuListResItem struct { - Id *bson.ObjectID `json:"id"` // SKU ID - AssetId *bson.ObjectID `json:"assetId"` +type AssetSkuItem struct { + Id int64 `json:"id"` // SKU ID + AssetId int64 `json:"assetId"` AssetName string `json:"assetName"` // 资产名称 SkuName string `json:"skuName"` // SKU名称 SpecsCount int `json:"specsCount"` // 规格数量 @@ -115,7 +113,7 @@ type AssetSkuListResItem struct { UnlimitedStock bool `json:"unlimitedStock"` // 是否无库存限制 Stock int `json:"stock"` // 库存数量 Sort int `json:"sort"` // 排序 - Status *consts.AssetSkuStatus `json:"status"` // 状态:active/inactive/disabled + Status consts.AssetSkuStatusType `json:"status"` // 状态:active/inactive/disabled StockMode stock.StockMode `json:"stockMode"` // 库存管理模式:1-明细模式 2-批次模式 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 1dc64c0..8d17b11 100644 --- a/model/dto/asset/category_dto.go +++ b/model/dto/asset/category_dto.go @@ -11,32 +11,32 @@ import ( // CreateCategoryReq 创建分类请求 type CreateCategoryReq struct { - g.Meta `path:"/createCategory" method:"post" tags:"分类管理" summary:"创建分类" dc:"创建新的分类"` - Name string `json:"name" v:"required" dc:"分类名称"` - ParentId string `json:"parentId" dc:"父分类ID"` - 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:"分类属性"` + 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:"分类属性"` } // CreateCategoryRes 创建分类响应 type CreateCategoryRes struct { - Bid string `json:"bid" dc:"分类ID"` + Id int64 `json:"id,string" dc:"分类ID"` } // UpdateCategoryReq 更新分类请求 type UpdateCategoryReq struct { g.Meta `path:"/updateCategory" method:"put" tags:"分类管理" summary:"更新分类" dc:"更新分类信息"` - Id uint64 `json:"id" v:"required-without:Bid|integer#Id不能为空|Id必须是整数" dc:"分类ID"` - Bid string `json:"bid" v:"required-without:Id|string#Bid不能为空|Bid必须是字符串" dc:"分类ID"` + Id int64 `json:"id" v:"required" dc:"分类ID"` Name string `json:"name" dc:"分类名称"` - ParentId string `json:"parentId" dc:"父分类ID"` + ParentId int64 `json:"parentId" dc:"父分类ID"` Image string `json:"image" dc:"分类图片"` Sort int `json:"sort" dc:"排序"` - IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"` + IsLeafNode *bool `json:"isLeafNode" dc:"是否叶子节点"` Attrs []entity.CategoryAttr `json:"attrs" dc:"分类属性"` Status consts.CategoryStatusType `json:"status" dc:"状态:1启用0禁用"` } @@ -44,14 +44,14 @@ type UpdateCategoryReq struct { // UpdateCategoryStatusReq 更新分类状态请求 type UpdateCategoryStatusReq struct { g.Meta `path:"/updateCategoryStatus" method:"put" tags:"分类管理" summary:"更新分类状态" dc:"更新分类状态"` - Id string `json:"id" v:"required" dc:"分类ID"` + Id int64 `json:"id" v:"required" dc:"分类ID"` Status consts.CategoryStatusType `json:"status" v:"in:1,0" dc:"状态:1启用0禁用"` } // DeleteCategoryReq 删除分类请求 type DeleteCategoryReq struct { g.Meta `path:"/deleteCategory" method:"delete" tags:"分类管理" summary:"删除分类" dc:"删除分类"` - Bid string `json:"bid" v:"required" dc:"分类ID"` + Id int64 `json:"id" v:"required" dc:"分类ID"` } // GetCategoryTreeReq 获取分类树请求 @@ -67,8 +67,7 @@ type GetCategoryTreeRes struct { // CategoryTreeNode 分类树节点 type CategoryTreeNode struct { - Id uint64 `json:"id" dc:"分类ID"` - Bid string `json:"bid" dc:"分类ID"` + Id int64 `json:"id,string" dc:"分类ID"` Name string `json:"name" dc:"分类名称"` Level int `json:"level" dc:"分类层级"` Type string `json:"type" dc:"分类类型"` @@ -85,8 +84,7 @@ type CategoryTreeNode struct { type ListCategoryReq struct { g.Meta `path:"/listCategories" method:"get" tags:"分类管理" summary:"获取分类列表" dc:"获取分类列表"` *beans.Page - OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"` - ParentId string `json:"parentId" dc:"父分类ID"` + ParentId int64 `json:"parentId" dc:"父分类ID"` Status consts.CategoryStatusType `json:"status" dc:"状态:1启用0禁用"` Keyword string `json:"keyword" dc:"关键词搜索"` } @@ -100,16 +98,14 @@ type ListCategoryRes struct { // GetCategoryReq 获取分类详情请求 type GetCategoryReq struct { g.Meta `path:"/getCategory" method:"get" tags:"分类管理" summary:"获取分类详情" dc:"获取分类详情"` - Id uint64 `json:"id" v:"required-without:Bid|integer#Id不能为空|Id必须是整数" dc:"分类ID"` - Bid string `json:"bid" v:"required-without:Id|string#Bid不能为空|Bid必须是字符串" dc:"分类ID"` + Id int64 `json:"id" v:"required" dc:"分类ID"` } // GetCategoryRes 获取分类详情响应 type GetCategoryRes struct { - Id uint64 `json:"id" dc:"分类ID"` - Bid string `json:"bid" dc:"分类ID"` + Id int64 `json:"id,string" dc:"分类ID"` Name string `json:"name" dc:"分类名称"` - ParentId string `json:"parentId" dc:"父分类ID"` + ParentId int64 `json:"parentId,string" dc:"父分类ID"` Path string `json:"path" dc:"分类路径"` Level int `json:"level" dc:"分类层级"` IsLeafNode bool `json:"isLeafNode" dc:"是否叶子节点"` diff --git a/model/dto/enum/enum_dto.go b/model/dto/enum/enum_dto.go index 77f8101..e9ec5af 100644 --- a/model/dto/enum/enum_dto.go +++ b/model/dto/enum/enum_dto.go @@ -2,6 +2,7 @@ package dto import ( "assets/consts/asset" + "github.com/gogf/gf/v2/frame/g" ) @@ -39,7 +40,7 @@ type GetSpecsUnitRes struct { // GetTenantModuleTypeReq 获取租户模块类型请求 type GetTenantModuleTypeReq struct { g.Meta `path:"/getTenantModuleType" method:"get" tags:"枚举管理" summary:"获取租户模块类型" dc:"获取租户模块类型"` - AssetId string `json:"assetId" v:"required|in:physical,virtual,service" dc:"资产id"` + AssetId int64 `json:"assetId" v:"required|in:physical,virtual,service" dc:"资产id"` } // GetTenantModuleTypeRes 获取租户模块类型响应 diff --git a/model/dto/stock/stock_batch_dto.go b/model/dto/stock/stock_batch_dto.go index 223bc5a..e2b9816 100644 --- a/model/dto/stock/stock_batch_dto.go +++ b/model/dto/stock/stock_batch_dto.go @@ -21,8 +21,8 @@ type CommonResp struct { type CreateBatchReq struct { g.Meta `path:"/createBatch" method:"post" tags:"库存批次管理" summary:"创建批次" dc:"创建新的库存批次"` - AssetId *bson.ObjectID `json:"assetId" v:"required" dc:"资产ID"` - AssetSkuId *bson.ObjectID `json:"assetSkuId" v:"required" dc:"SKU ID"` + AssetId int64 `json:"assetId" v:"required" dc:"资产ID"` + AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"SKU ID"` BatchNo string `json:"batchNo" v:"required" dc:"批次号"` BatchQty int `json:"batchQty" v:"required|min:1" dc:"批次数量"` AvailableQty int `json:"availableQty" v:"required|min:1" dc:"可用数量"` @@ -42,9 +42,9 @@ type CreateBatchRes struct { type UpdateBatchReq struct { g.Meta `path:"/updateBatch" method:"put" tags:"库存批次管理" summary:"更新批次" dc:"更新批次信息"` - Id *bson.ObjectID `json:"id" v:"required" dc:"批次ID"` - BatchQty int `json:"batchQty" v:"required|min:1" dc:"批次数量"` - AvailableQty int `json:"availableQty" v:"required|min:1" dc:"可用数量"` + 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 删除批次请求 diff --git a/model/dto/stock/stock_details_dto.go b/model/dto/stock/stock_details_dto.go index a3d23cd..50a6f91 100644 --- a/model/dto/stock/stock_details_dto.go +++ b/model/dto/stock/stock_details_dto.go @@ -37,8 +37,8 @@ type ListStockDetailsReq struct { *beans.Page OrderBy []beans.OrderBy `json:"orderBy" dc:"排序规则"` - AssetId *bson.ObjectID `json:"assetId" dc:"资产ID"` - AssetSkuId *bson.ObjectID `json:"assetSkuId" dc:"SKU 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:"状态"` } diff --git a/model/dto/stock/stock_manage_dto.go b/model/dto/stock/stock_manage_dto.go index fb70548..05e4242 100644 --- a/model/dto/stock/stock_manage_dto.go +++ b/model/dto/stock/stock_manage_dto.go @@ -11,8 +11,8 @@ import ( type StockOperationReq struct { g.Meta `path:"/stockOperation" method:"post" tags:"库存管理" summary:"库存操作(创建/修改)" dc:"库存操作(创建/修改)"` - AssetSkuId *bson.ObjectID `json:"assetSkuId" v:"required" dc:"关联资产SKU ID"` - Stock int `json:"stock" v:"required|min:1" dc:"库存数量"` + AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"关联资产SKU ID"` + Stock int `json:"stock" v:"required|min:1" dc:"库存数量"` // 批次模式专用字段 BatchNo string `json:"batchNo" dc:"批次号(批次模式必填)"` ProductionDate *gtime.Time `json:"productionDate" dc:"生产日期(批次模式,格式:2006-01-02)"` @@ -22,8 +22,8 @@ type StockOperationReq struct { // StockPublishMessage 库存发布消息 type StockPublishMessage struct { - AssetId string `json:"assetId"` - AssetSkuId string `json:"assetSkuId"` + AssetId int64 `json:"assetId"` + AssetSkuId int64 `json:"assetSkuId"` TenantId interface{} `json:"tenantId"` UserName interface{} `json:"userName"` StockCount int `json:"stockCount"` @@ -41,7 +41,7 @@ type StockPublishMessage struct { type GetStockFormFieldsReq struct { g.Meta `path:"/getStockFormFields" method:"get" tags:"库存管理" summary:"获取库存操作表单字段" dc:"根据资产SKU的库存管理模式动态返回表单字段"` - AssetSkuId *bson.ObjectID `json:"assetSkuId" v:"required" dc:"关联资产ID"` + AssetSkuId int64 `json:"assetSkuId" v:"required" dc:"关联资产ID"` } // GetStockFormFieldsRes 获取库存表单字段响应 diff --git a/model/entity/asset/asset.go b/model/entity/asset/asset.go index 7009863..aba8447 100644 --- a/model/entity/asset/asset.go +++ b/model/entity/asset/asset.go @@ -5,30 +5,74 @@ import ( "assets/consts/stock" "gitea.com/red-future/common/beans" - "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/os/gtime" ) +type assetCol struct { + beans.SQLBaseCol + Name string + Description string + Type string + CategoryId string + CategoryPath string + ImageURL string + Images string + Status string + BasePrice string + Currency string + UnlimitedStock string + StockMode string + OnlineTime string + OfflineTime string + PhysicalAssetConfig string + ServiceAssetConfig string + VirtualAssetConfig string + Metadata string + TenantModuleType string +} + +var AssetCol = assetCol{ + SQLBaseCol: beans.DefSQLBaseCol, + Name: "name", + Description: "description", + Type: "type", + CategoryId: "category_id", + CategoryPath: "category_path", + ImageURL: "image_url", + Images: "images", + Status: "status", + BasePrice: "base_price", + Currency: "currency", + UnlimitedStock: "unlimited_stock", + StockMode: "stock_mode", + OnlineTime: "online_time", + OfflineTime: "offline_time", + PhysicalAssetConfig: "physical_asset_config", + ServiceAssetConfig: "service_asset_config", + VirtualAssetConfig: "virtual_asset_config", + Metadata: "metadata", + TenantModuleType: "tenant_module_type", +} + // Asset 资产实体 type Asset struct { - beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, IsDeleted + 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 uint64 `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.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:"下线时间"` + 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:"下线时间"` // 上线和下线时间配置(由定时任务处理资产状态) // 类型专用配置 - 实物资产配置(JSONB) PhysicalAssetConfig *gjson.Json `orm:"physical_asset_config" json:"physicalAssetConfig" description:"实物资产配置(JSONB)"` @@ -37,7 +81,7 @@ type Asset struct { // 类型专用配置 - 虚拟资产配置(JSONB) VirtualAssetConfig *gjson.Json `orm:"virtual_asset_config" json:"virtualAssetConfig" description:"虚拟资产配置(JSONB)"` // 扩展字段(JSONB) - Metadata *gjson.Json `orm:"metadata" json:"metadata" description:"动态元数据(JSONB)"` + Metadata []gjson.Json `orm:"metadata" json:"metadata" description:"动态元数据(JSONB)"` - TenantModuleType string `orm:"tenant_module_type" json:"tenantModuleType" description:"租户模块类型"` + 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 4987075..5df9bb0 100644 --- a/model/entity/asset/asset_sku.go +++ b/model/entity/asset/asset_sku.go @@ -2,43 +2,81 @@ package entity import ( consts "assets/consts/asset" - "assets/consts/public" "assets/consts/stock" "assets/model/config" "gitea.com/red-future/common/beans" - "go.mongodb.org/mongo-driver/v2/bson" + "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 + 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", + TenantModuleType: "tenant_module_type", +} + // AssetSku 资产SKU实体 type AssetSku struct { - beans.MongoBaseDO `bson:",inline"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, TenantId, IsDeleted - AssetId *bson.ObjectID `bson:"assetId" json:"assetId"` // 关联资产ID - AssetName string `bson:"assetName" json:"assetName"` // 资产名称 - SkuName string `bson:"skuName" json:"skuName"` // SKU名称 - ImageURL string `bson:"imageUrl,omitempty" json:"imageUrl"` // SKU主图 - SpecValues []map[string]interface{} `bson:"specValues" json:"specValues"` // 规格值:{"颜色":"红色","尺寸":"L","时长":"1个月","平台":"抖音"} - Price int `bson:"price" json:"price"` // 价格(分为单位) - UnlimitedStock bool `bson:"unlimitedStock" json:"unlimitedStock"` // 是否无库存限制 - Stock int `bson:"stock" json:"stock"` // 库存数量 - SpecsCount int `bson:"specsCount" json:"specsCount"` // 规格数量 - SpecsUnit *SpecsUnitKeyValue `bson:"specsUnit" json:"specsUnit"` // 规格单位 - Sort int `bson:"sort" json:"sort"` // 排序 - Status *consts.AssetSkuStatus `bson:"status" json:"status"` // 状态:active/inactive/disabled - StockMode stock.StockMode `bson:"stockMode" json:"stockMode"` // 库存管理模式:1-明细模式 2-批次模式 - CategoryId *bson.ObjectID `bson:"categoryId" json:"categoryId"` // 分类ID - CategoryPath string `bson:"categoryPath" json:"categoryPath"` // 分类路径 - CapacityUnitType stock.CapacityUnitType `bson:"capacityUnitType" json:"capacityUnitType"` // 容量单位类型 - Capacity config.Capacity `bson:"capacity" json:"capacity"` //容量 - TenantModuleType beans.TenantModuleType `bson:"tenantModuleType" 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 []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"` // 租户模块类型 } type SpecsUnitKeyValue struct { Key string `bson:"key" json:"key"` // 对应原有常量值 Value string `bson:"value" json:"value"` // 对应描述信息 } - -// CollectionName 获取集合名称 -func (AssetSku) CollectionName() string { - return public.AssetSkuCollection -} diff --git a/model/entity/asset/category.go b/model/entity/asset/category.go index 8817b24..aa8e05f 100644 --- a/model/entity/asset/category.go +++ b/model/entity/asset/category.go @@ -4,7 +4,6 @@ import ( consts "assets/consts/category" "gitea.com/red-future/common/beans" - "github.com/gogf/gf/v2/encoding/gjson" ) type categoryCol struct { @@ -26,7 +25,7 @@ var CategoryCol = categoryCol{ ParentId: "parent_id", Path: "path", Level: "level", - IsLeafNode: "isLeaf_node", + IsLeafNode: "is_leaf_node", Sort: "sort", Image: "image", Attrs: "attrs", @@ -35,15 +34,16 @@ var CategoryCol = categoryCol{ // Category 分类实体 type Category struct { - beans.SQLBaseDO `orm:",inherit"` // 嵌入基础字段:Id, Creator, CreatedAt, Updater, UpdatedAt, IsDeleted - Name string `orm:"name" json:"name"` // 分类名称 - ParentId string `orm:"parent_id" json:"parentId"` // 父分类ID,为空表示根分类 - Path string `orm:"path" json:"path"` // 分类路径,如:/root/parent/child - Level int `orm:"level" json:"level"` // 分类层级 - IsLeafNode bool `orm:"isLeaf_node" json:"isLeafNode"` // 是叶子节点 - Sort int `orm:"sort" json:"sort"` // 排序 - Image string `orm:"image" json:"image"` // 分类图片 - Attrs []gjson.Json `orm:"attrs" json:"attrs,omitempty"` // 分类属性 + 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 // 使用场景说明: // 1. 商品分类属性:为该分类下的商品定义标准化的属性模板,如服装分类可定义尺寸、颜色、材质等属性 // 2. 服务分类属性:为服务类目定义特性参数,如咨询服务可定义服务时长、服务方式、专业领域等 @@ -51,20 +51,18 @@ type Category struct { // 4. 搜索筛选:基于分类属性进行商品筛选和搜索,提升用户体验 // 5. 数据标准化:确保同一分类下的商品具有统一的属性结构,便于数据管理 // 支持的属性类型:文本(text)、数字(number)、日期(date)、单选(select)、多选(multi_select)、布尔(boolean)、图片(image) - Status consts.CategoryStatusType `orm:"status" json:"status"` // 状态:1启用/0禁用 } // CategoryAttr 分类属性 -// 用于定义分类下商品或服务的标准化属性模板,确保同类商品属性统一 +// Attrs 用于定义分类下商品或服务的标准化属性模板,确保同类商品属性统一 type CategoryAttr struct { - Name string `json:"name"` // 属性名称,如:尺寸、颜色、品牌等 - Type string `json:"type"` // 属性类型:text文本/number数字/date日期/select选择/multi_select多选/boolean布尔/image图片 - DictType string `json:"dictType"` // 字典类型,如果是select/multi_select类型时有效 - Required bool `json:"required"` // 是否必填,true表示商品发布时必须填写此属性 - Options []FieldOption `json:"options"` // 选项配置,JSON字符串格式,用于select/multi_select类型的可选值列表 - // 示例:'{"options":[{"label":"红色","value":"red"},{"label":"蓝色","value":"blue"}]}' - Description string `json:"description"` // 属性描述,向用户说明此属性的具体含义和填写要求 - Sort int `json:"sort"` // 排序权重,数值越小排序越靠前,用于属性在界面的显示顺序 + Name string `json:"name"` // 属性名称,如:尺寸、颜色、品牌等 + Type string `json:"type"` // 属性类型:text文本/number数字/date日期/select选择/multi_select多选/boolean布尔/image图片 + DictType string `json:"dictType"` // 字典类型,如果是select/multi_select类型时有效 + Required bool `json:"required"` // 是否必填,true表示商品发布时必须填写此属性 + Options []FieldOption `json:"options"` // 选项配置,JSON字符串格式,用于select/multi_select类型的可选值列表 // 示例:'{"options":[{"label":"红色","value":"red"},{"label":"蓝色","value":"blue"}]}' + Description string `json:"description"` // 属性描述,向用户说明此属性的具体含义和填写要求 + Sort int `json:"sort"` // 排序权重,数值越小排序越靠前,用于属性在界面的显示顺序 } // FieldOption 字段选项 diff --git a/model/entity/stock/stock_details.go b/model/entity/stock/stock_details.go index a456137..0b2a6f5 100644 --- a/model/entity/stock/stock_details.go +++ b/model/entity/stock/stock_details.go @@ -13,8 +13,8 @@ import ( type StockDetails 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 + 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"` // 锁定过期时间 diff --git a/service/asset/asset_service.go b/service/asset/asset_service.go index b002345..5850fef 100644 --- a/service/asset/asset_service.go +++ b/service/asset/asset_service.go @@ -3,18 +3,19 @@ package service import ( "assets/consts/stock" dao "assets/dao/asset" - "assets/dao/base" dto "assets/model/dto/asset" + enumDto "assets/model/dto/enum" + entity "assets/model/entity/asset" + service "assets/service/enum" "context" "errors" - "fmt" + "gitea.com/red-future/common/http" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" "gitea.com/red-future/common/beans" "gitea.com/red-future/common/minio" - "gitea.com/red-future/common/utils" ) type asset struct{} @@ -45,38 +46,8 @@ func (s *asset) Create(ctx context.Context, req *dto.CreateAssetReq) (res *dto.C if err = http.Get(ctx, "admin-go/api/v1/system/user/checkIsSuperAdmin", headers, &isSuperAdmin); err != nil { return } - if !isSuperAdmin { req.StockMode = stock.StockModeDetail - - //var getUserInfo beans.User - //getUserInfo, err = utils.GetUserInfo(ctx) - //if err != nil { - // return - //} - //var get *gvar.Var - //get, err = message.GetRedisClientTest("test").Get(ctx, fmt.Sprintf("module_tenant:tenantId-%v", getUserInfo.TenantId)) - //if err != nil { - // return - //} - //if !g.IsEmpty(get.String()) { - // list := new(beans.ModuleTenant) - // if err = json.Unmarshal(get.Bytes(), &list); err != nil { - // return - // } - // req.TenantModuleType = list.TenantModuleType - //} else { - // moduleTenantRes := new(beans.ModuleTenant) - // err = message.CallRPC(ctx, "moduleService.AddRedisByTenantId", map[string]interface{}{"tenantId": getUserInfo.TenantId}, moduleTenantRes) - // if err != nil { - // return - // } - // if !g.IsEmpty(moduleTenantRes.TenantModuleType) { - // req.TenantModuleType = moduleTenantRes.TenantModuleType - // } else { - // return nil, errors.New("您未开通此模块,请开通后再使用") - // } - //} } else { req.TenantModuleType = beans.TenantModuleTypePlatform } @@ -87,7 +58,7 @@ func (s *asset) Create(ctx context.Context, req *dto.CreateAssetReq) (res *dto.C return } res = &dto.CreateAssetRes{ - Id: gconv.Uint64(id), + Id: id, } return } @@ -98,79 +69,88 @@ func (s *asset) List(ctx context.Context, req *dto.ListAssetReq) (res *dto.ListA if err != nil { return } - user, err := utils.GetUserInfo(ctx) - if err != nil { - return - } - fmt.Println(user) res = &dto.ListAssetRes{ Total: total, } - err = utils.Struct(assetList, &res.List) + err = gconv.Struct(assetList, &res.List) return } // GetOne 获取单个资产 func (s *asset) GetOne(ctx context.Context, req *dto.GetAssetReq) (res *dto.GetAssetRes, err error) { - assetOne, err := dao.Asset.GetOne(ctx, req) + var assetOne *entity.Asset + if assetOne, err = dao.Asset.GetOne(ctx, req); err != nil { + return + } + var assetListItem *dto.AssetItem + if err = gconv.Struct(assetOne, assetListItem); err != nil { + return + } + getCategoryRes, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{ + Id: assetOne.CategoryId, + }) if err != nil { return } - // TODO: CategoryId类型不匹配,需要同步修改category为uint64 - // getCategoryRes, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{ - // Id: assetOne.CategoryId, - // }) - // if err != nil { - // return - // } return &dto.GetAssetRes{ - Asset: assetOne, - CategoryName: "", // getCategoryRes.Name, + AssetItem: assetListItem, + CategoryName: getCategoryRes.Name, ImgAddressPrefix: minio.GetFileAddressPrefix(ctx), }, nil } // GetAssetAndSku 获取资产和Sku详情 func (s *asset) GetAssetAndSku(ctx context.Context, req *dto.GetAssetAndSkuReq) (res *dto.GetAssetAndSkuRes, err error) { - // 跳过租户ID过滤获取资产 - // TODO: AssetId 类型不匹配,bson.ObjectID 需要转换为 uint64 - // 使用 SkipTenantId 跳过租户ID过滤 - assetOne, err := dao.Asset.GetOneById(base.SkipTenantId(ctx), 0) - _ = req.AssetId + var updateReq *dto.GetAssetReq + if err = gconv.Struct(req, &updateReq); err != nil { + return + } + assetOne, err := dao.Asset.GetOne(ctx, updateReq) if err != nil { return } - // TODO: AssetId类型不匹配,需要适配 - // moduleType, err := service.Enum.GetTenantModuleType(ctx, &enumDto.GetTenantModuleTypeReq{AssetId: req.AssetId.Hex()}) - // if err != nil { - // return - // } - // TODO: AssetId类型不匹配,需要同步修改AssetSku为uint64 - // skus, _, err := dao.AssetSku.List(ctx, &dto.ListAssetSkuReq{AssetId: req.AssetId}, true) - // if err != nil { - // return - // } + var assetListItem *dto.AssetItem + if err = gconv.Struct(assetOne, assetListItem); err != nil { + return + } + moduleType, err := service.Enum.GetTenantModuleType(ctx, &enumDto.GetTenantModuleTypeReq{AssetId: assetOne.Id}) + if err != nil { + return + } + skus, _, err := dao.AssetSku.List(ctx, &dto.ListAssetSkuReq{AssetId: assetOne.Id}) + if err != nil { + return + } + var assetSkuListResItem []dto.AssetSkuItem + if err = gconv.Structs(skus, assetSkuListResItem); err != nil { + return + } return &dto.GetAssetAndSkuRes{ - Asset: assetOne, - Skus: nil, // skus, - TenantModuleType: nil, // moduleType.Options, + AssetItem: assetListItem, + Skus: assetSkuListResItem, + TenantModuleType: moduleType.Options, ImgAddressPrefix: minio.GetFileAddressPrefix(ctx), }, nil } // Update 更新资产 -func (s *asset) Update(ctx context.Context, req *dto.UpdateAssetReq) error { - return dao.Asset.Update(ctx, req) +func (s *asset) Update(ctx context.Context, req *dto.UpdateAssetReq) (err error) { + _, err = dao.Asset.Update(ctx, req) + return } // UpdateStatus 更新资产状态 func (s *asset) UpdateStatus(ctx context.Context, req *dto.UpdateAssetStatusReq) (err error) { var updateReq *dto.UpdateAssetReq - err = utils.Struct(req, &updateReq) - return dao.Asset.Update(ctx, updateReq) + if err = gconv.Struct(req, &updateReq); err != nil { + return err + } + _, err = dao.Asset.Update(ctx, updateReq) + return } // Delete 删除资产 -func (s *asset) Delete(ctx context.Context, req *dto.DeleteAssetReq) error { - return dao.Asset.DeleteFake(ctx, req) +func (s *asset) Delete(ctx context.Context, req *dto.DeleteAssetReq) (err error) { + _, err = dao.Asset.Delete(ctx, req) + return } diff --git a/service/asset/asset_sku_service.go b/service/asset/asset_sku_service.go index 7a6fc2d..09bef4c 100644 --- a/service/asset/asset_sku_service.go +++ b/service/asset/asset_sku_service.go @@ -13,7 +13,6 @@ import ( "gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/util/gconv" - "go.mongodb.org/mongo-driver/v2/bson" ) type assetSku struct{} @@ -28,7 +27,7 @@ func (s *assetSku) CreateAssetSku(ctx context.Context, req *dto.CreateAssetSkuRe return nil, errors.New("关联资产不存在") } // 根据资产ID查询SKU列表(用于下面验证,自定义属性和sku名称重不重复) - skusList, _, err := dao.AssetSku.List(ctx, &dto.ListAssetSkuReq{AssetId: req.AssetId}, false) + skusList, _, err := dao.AssetSku.List(ctx, &dto.ListAssetSkuReq{AssetId: assetEntity.Id}) if err != nil { return } @@ -39,26 +38,23 @@ func (s *assetSku) CreateAssetSku(ctx context.Context, req *dto.CreateAssetSkuRe } req.UnlimitedStock = assetEntity.UnlimitedStock req.StockMode = assetEntity.StockMode - // TODO: 类型不匹配 uint64 vs *bson.ObjectID - // req.CategoryId = assetEntity.CategoryId + req.CategoryId = assetEntity.CategoryId req.CategoryPath = assetEntity.CategoryPath - // TODO: 类型不匹配 string vs beans.TenantModuleType - // req.TenantModuleType = assetEntity.TenantModuleType + req.TenantModuleType = assetEntity.TenantModuleType // 插入数据库 - ids, err := dao.AssetSku.Insert(ctx, req) + id, err := dao.AssetSku.Insert(ctx, req) if err != nil { return } - id := ids[0].(bson.ObjectID) res = &dto.CreateAssetSkuRes{ - Id: &id, + Id: id, } return } // UpdateAssetSku 更新SKU -func (s *assetSku) UpdateAssetSku(ctx context.Context, req *dto.UpdateAssetSkuReq) error { - getOne, err := dao.AssetSku.GetOne(ctx, &dto.GetAssetSkuReq{Id: req.Id}, false) +func (s *assetSku) UpdateAssetSku(ctx context.Context, req *dto.UpdateAssetSkuReq) (err error) { + getOne, err := dao.AssetSku.GetOne(ctx, &dto.GetAssetSkuReq{Id: req.Id}) if err != nil { return errors.New("SUK不存在") } @@ -78,7 +74,8 @@ func (s *assetSku) UpdateAssetSku(ctx context.Context, req *dto.UpdateAssetSkuRe return err } // 更新数据库 - return dao.AssetSku.Update(ctx, req) + _, err = dao.AssetSku.Update(ctx, req) + return } func (s *assetSku) parameterValidation(ctx context.Context, assetEntity *entity.Asset, list []entity.AssetSku, skuName string, specValues []map[string]interface{}) (err error) { @@ -112,7 +109,8 @@ func (s *assetSku) parameterValidation(ctx context.Context, assetEntity *entity. for key, subValue := range specValues { // 1. 检查请求参数 map 中是否存在该键 for _, subValues := range list.SpecValues { - parentValue, ok := subValues[gconv.String(key)] + mapSubValues := gconv.Map(subValues) + parentValue, ok := mapSubValues[gconv.String(key)] if ok { // 2. 检查对应的值是否相等 if reflect.DeepEqual(parentValue, subValue) { @@ -146,13 +144,14 @@ func (s *assetSku) parameterValidation(ctx context.Context, assetEntity *entity. } // DeleteAssetSku 删除SKU(软删除) -func (s *assetSku) DeleteAssetSku(ctx context.Context, req *dto.DeleteAssetSkuReq) error { - return dao.AssetSku.DeleteFake(ctx, req) +func (s *assetSku) DeleteAssetSku(ctx context.Context, req *dto.DeleteAssetSkuReq) (err error) { + _, err = dao.AssetSku.Delete(ctx, req) + return } // GetAssetSku 获取SKU详情 func (s *assetSku) GetAssetSku(ctx context.Context, req *dto.GetAssetSkuReq) (res *dto.GetAssetSkuRes, err error) { - one, err := dao.AssetSku.GetOne(ctx, req, false) + one, err := dao.AssetSku.GetOne(ctx, req) if err != nil { return } @@ -163,7 +162,7 @@ func (s *assetSku) GetAssetSku(ctx context.Context, req *dto.GetAssetSkuReq) (re // ListAssetSkus 获取SKU列表 func (s *assetSku) ListAssetSkus(ctx context.Context, req *dto.ListAssetSkuReq) (res *dto.ListAssetSkuRes, err error) { // 查询数据库 - list, total, err := dao.AssetSku.List(ctx, req, false) + list, total, err := dao.AssetSku.List(ctx, req) if err != nil { return } @@ -176,14 +175,19 @@ func (s *assetSku) ListAssetSkus(ctx context.Context, req *dto.ListAssetSkuReq) // GetAssetSkuModule 获取SKU详情 func (s *assetSku) GetAssetSkuModule(ctx context.Context, req *dto.GetAssetSkuModuleReq) (res *dto.GetAssetSkuModuleRes, err error) { - one, err := dao.AssetSku.GetOne(ctx, &dto.GetAssetSkuReq{Id: req.Id}, true) + one, err := dao.AssetSku.GetOne(ctx, &dto.GetAssetSkuReq{Id: req.Id}) if err != nil { return } res = &dto.GetAssetSkuModuleRes{} // 计算到期时间 if one.SpecsUnit != nil && one.SpecsCount > 0 { - durationType := public.DurationType(one.SpecsUnit.Key) + var specsUnit *entity.SpecsUnitKeyValue + err = gconv.Struct(one.SpecsUnit, &specsUnit) + if err != nil { + return + } + durationType := public.DurationType(specsUnit.Key) res.ExpireAt = durationType.AddTime(one.SpecsCount) res.AssetId = one.AssetId } diff --git a/service/asset/category_service.go b/service/asset/category_service.go index 1b76b04..f1c8f04 100644 --- a/service/asset/category_service.go +++ b/service/asset/category_service.go @@ -8,7 +8,6 @@ import ( "errors" "gitea.com/red-future/common/db/gfdb" - "gitea.com/red-future/common/utils" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/util/gconv" @@ -29,22 +28,20 @@ var Category = new(CategoryService) func (s *CategoryService) Create(ctx context.Context, req *dto.CreateCategoryReq) (res *dto.CreateCategoryRes, err error) { // 构建分类路径和层级 - parent, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{Bid: req.ParentId}) + parent, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{Id: req.ParentId}) if err != nil { return nil, err } - req.Path = parent.Path + DefaultPathSeparator + req.ParentId + if g.IsEmpty(parent) { + return nil, errors.New("父分类不存在") + } + req.Path = parent.Path + DefaultPathSeparator + gconv.String(req.ParentId) req.Level = parent.Level + 1 err = gfdb.DB(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { - var r *entity.Category - - if r, err = dao.Category.Insert(ctx, req); err != nil { - return err - } - - // 更新新创建分类的 IsLeafNode 为 true - if err = s.updateLeafNode(ctx, r.Bid, true); err != nil { + var id int64 + req.IsLeafNode = gconv.PtrBool(true) + if id, err = dao.Category.Insert(ctx, req); err != nil { return err } @@ -54,7 +51,7 @@ func (s *CategoryService) Create(ctx context.Context, req *dto.CreateCategoryReq } res = &dto.CreateCategoryRes{ - Bid: r.Bid, + Id: id, } return nil @@ -64,11 +61,12 @@ func (s *CategoryService) Create(ctx context.Context, req *dto.CreateCategoryReq } // updateLeafNode 更新分类的 IsLeafNode 字段 -func (s *CategoryService) updateLeafNode(ctx context.Context, categoryId string, isLeaf bool) error { - return dao.Category.Update(ctx, &dto.UpdateCategoryReq{ - Bid: categoryId, - IsLeafNode: isLeaf, +func (s *CategoryService) updateLeafNode(ctx context.Context, categoryId int64, isLeaf bool) (err error) { + _, err = dao.Category.Update(ctx, &dto.UpdateCategoryReq{ + Id: categoryId, + IsLeafNode: &isLeaf, }) + return } // GetOne 获取单个分类 @@ -78,11 +76,12 @@ func (s *CategoryService) GetOne(ctx context.Context, req *dto.GetCategoryReq) ( return nil, err } res := new(dto.GetCategoryRes) - err = utils.Struct(one, &res) - if err != nil { - return nil, err + + if err = gconv.Scan(one, &res); err != nil { + panic(err) } - return res, nil + + return res, err } // List 获取分类列表 @@ -107,7 +106,7 @@ func (s *CategoryService) GetTree(ctx context.Context, req *dto.GetCategoryTreeR if err != nil { return nil, err } - tree, err := s.buildTree(ctx, list, "") + tree, err := s.buildTree(ctx, list, 0) if err != nil { return nil, err } @@ -115,7 +114,7 @@ func (s *CategoryService) GetTree(ctx context.Context, req *dto.GetCategoryTreeR } // buildTree 构建树形结构 -func (s *CategoryService) buildTree(ctx context.Context, categories []entity.Category, parentId string) ([]*dto.CategoryTreeNode, error) { +func (s *CategoryService) buildTree(ctx context.Context, categories []entity.Category, parentId int64) ([]*dto.CategoryTreeNode, error) { tree := make([]*dto.CategoryTreeNode, 0) for _, cat := range categories { if !s.isChildOf(cat.ParentId, parentId) { @@ -131,7 +130,7 @@ func (s *CategoryService) buildTree(ctx context.Context, categories []entity.Cat } // isChildOf 判断分类是否为指定父节点的子节点 -func (s *CategoryService) isChildOf(childParentId, parentId string) bool { +func (s *CategoryService) isChildOf(childParentId, parentId int64) bool { if g.IsEmpty(childParentId) && g.IsEmpty(parentId) { return true } @@ -147,7 +146,7 @@ func (s *CategoryService) convertToTreeNode(ctx context.Context, category *entit if err := gconv.Struct(&category, &res); err != nil { return res, err } - children, err := s.buildTree(ctx, allCategories, category.Bid) + children, err := s.buildTree(ctx, allCategories, category.Id) if err != nil { return res, err } @@ -157,7 +156,7 @@ func (s *CategoryService) convertToTreeNode(ctx context.Context, category *entit } // hasChildren 检查分类是否有子分类 -func (s *CategoryService) hasChildren(ctx context.Context, parentId string) (bool, error) { +func (s *CategoryService) hasChildren(ctx context.Context, parentId int64) (bool, error) { count, err := dao.Category.Count(ctx, &dto.ListCategoryReq{ ParentId: parentId, }) @@ -165,7 +164,7 @@ func (s *CategoryService) hasChildren(ctx context.Context, parentId string) (boo } // updateLeafNodeIfNoChildren 如果父分类没有子分类了,更新为叶子节点 -func (s *CategoryService) updateLeafNodeIfNoChildren(ctx context.Context, parentId string) error { +func (s *CategoryService) updateLeafNodeIfNoChildren(ctx context.Context, parentId int64) error { hasChildren, err := s.hasChildren(ctx, parentId) if err != nil { return err @@ -174,12 +173,13 @@ func (s *CategoryService) updateLeafNodeIfNoChildren(ctx context.Context, parent } // UpdateStatus 更新分类状态 -func (s *CategoryService) UpdateStatus(ctx context.Context, req *dto.UpdateCategoryStatusReq) error { +func (s *CategoryService) UpdateStatus(ctx context.Context, req *dto.UpdateCategoryStatusReq) (err error) { var updateReq *dto.UpdateCategoryReq - if err := gconv.Struct(req, &updateReq); err != nil { - return err + if err = gconv.Struct(req, &updateReq); err != nil { + return } - return dao.Category.Update(ctx, updateReq) + _, err = dao.Category.Update(ctx, updateReq) + return } // Update 更新分类 @@ -189,7 +189,7 @@ func (s *CategoryService) Update(ctx context.Context, req *dto.UpdateCategoryReq return err } err = gfdb.DB(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { - if err = dao.Category.Update(ctx, req); err != nil { + if rows, err := dao.Category.Update(ctx, req); err != nil && rows > 0 { return err } @@ -213,7 +213,7 @@ func (s *CategoryService) Update(ctx context.Context, req *dto.UpdateCategoryReq } // parentIdChanged 判断父分类是否发生变化 -func (s *CategoryService) parentIdChanged(newParentId, oldParentId string) bool { +func (s *CategoryService) parentIdChanged(newParentId, oldParentId int64) bool { if g.IsEmpty(newParentId) && g.IsEmpty(oldParentId) { return false } @@ -226,7 +226,7 @@ func (s *CategoryService) parentIdChanged(newParentId, oldParentId string) bool // Delete 删除分类 func (s *CategoryService) Delete(ctx context.Context, req *dto.DeleteCategoryReq) error { // 检查是否有子分类 - hasChildren, err := s.hasChildren(ctx, req.Bid) + hasChildren, err := s.hasChildren(ctx, req.Id) if err != nil { return err } @@ -236,7 +236,7 @@ func (s *CategoryService) Delete(ctx context.Context, req *dto.DeleteCategoryReq // 检查是否有资产 if count, err := dao.Asset.Count(ctx, &dto.ListAssetReq{ - CategoryId: req.Bid, + CategoryId: req.Id, }); err != nil { return err } else if count > 0 { @@ -244,13 +244,13 @@ func (s *CategoryService) Delete(ctx context.Context, req *dto.DeleteCategoryReq } // 获取分类信息用于后续操作 - category, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{Bid: req.Bid}) + category, err := dao.Category.GetOne(ctx, &dto.GetCategoryReq{Id: req.Id}) if err != nil { return err } err = gfdb.DB(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { // 删除分类 - if err := dao.Category.DeleteFake(ctx, req); err != nil { + if rows, err := dao.Category.Delete(ctx, req); err != nil && rows > 0 { return err } diff --git a/service/stock/stock_manage_service.go b/service/stock/stock_manage_service.go index c6ccf26..181333b 100644 --- a/service/stock/stock_manage_service.go +++ b/service/stock/stock_manage_service.go @@ -39,7 +39,7 @@ var StockManage = new(stockManage) // GetStockFormFields 获取库存操作表单字段 func (s *stockManage) GetStockFormFields(ctx context.Context, req *stockDto.GetStockFormFieldsReq) (*stockDto.GetStockFormFieldsRes, error) { // 获取资产SKU信息 - assetSku, err := assetDao.AssetSku.GetOne(ctx, &assetDto.GetAssetSkuReq{Id: req.AssetSkuId}, false) + assetSku, err := assetDao.AssetSku.GetOne(ctx, &assetDto.GetAssetSkuReq{Id: req.AssetSkuId}) if err != nil { return nil, err } @@ -89,7 +89,7 @@ func (s *stockManage) GetStockFormFields(ctx context.Context, req *stockDto.GetS // StockOperation 库存操作入口(入库/出库) // 根据SKU的StockMode区分明细模式和批次模式,计算差值后发布消息到NATS func (s *stockManage) StockOperation(ctx context.Context, req *stockDto.StockOperationReq) (err error) { - assetSku, err := assetDao.AssetSku.GetOne(ctx, &assetDto.GetAssetSkuReq{Id: req.AssetSkuId}, false) + assetSku, err := assetDao.AssetSku.GetOne(ctx, &assetDto.GetAssetSkuReq{Id: req.AssetSkuId}) if err != nil { return } @@ -145,13 +145,13 @@ func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEn return } publishMessage := stockDto.StockPublishMessage{ - AssetId: assetSku.AssetId.Hex(), - AssetSkuId: assetSku.Id.Hex(), + AssetId: assetSku.AssetId, + AssetSkuId: assetSku.Id, TenantId: user.TenantId, UserName: user.UserName, StockCount: stockCount, OperationType: operationType, - Metadata: assetSku.SpecValues, + Metadata: gconv.Maps(assetSku.SpecValues), StockMode: int(assetSku.StockMode), BatchNo: req.BatchNo, ProductionDate: req.ProductionDate, @@ -186,21 +186,9 @@ func (s *stockManage) stockPublishMessage(ctx context.Context, assetSku *assetEn // AddStock NATS消费者调用,执行实际的入库/出库操作 // 使用Redis分布式锁防止并发冲突,支持明细模式和批次模式 func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) error { - assetId, err := bson.ObjectIDFromHex(gconv.String(msg["assetId"])) - if err != nil { - return err - } - assetSkuId, err := bson.ObjectIDFromHex(gconv.String(msg["assetSkuId"])) - if err != nil { - return err - } - stockId := bson.ObjectID{} - if !g.IsEmpty(msg["stockId"]) { - stockId, err = bson.ObjectIDFromHex(gconv.String(msg["stockId"])) - if err != nil { - return err - } - } + 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"]) @@ -219,9 +207,9 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) success, err := redis.Lock(ctx, fileLockKey, int64(60), func(ctx context.Context) error { if operationType == "add" { if stockMode == stock.StockModeBatch { - if !stockId.IsZero() { + if !g.IsEmpty(stockId) { batch := stockDto.UpdateBatchReq{ - Id: &stockId, + Id: stockId, BatchQty: stockCount, AvailableQty: stockCount, } @@ -230,8 +218,8 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) } } else { batch := stockDto.CreateBatchReq{ - AssetId: &assetId, - AssetSkuId: &assetSkuId, + AssetId: assetId, + AssetSkuId: assetSkuId, Status: stock.BatchStatusActive, Metadata: metadata, BatchNo: batchNo, @@ -251,14 +239,14 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) var stockInterfaces []interface{} for i := 0; i < stockCount; i++ { stockInterfaces = append(stockInterfaces, entity.StockDetails{ - AssetId: &assetId, - AssetSkuId: &assetSkuId, + AssetId: assetId, + AssetSkuId: assetSkuId, Status: stock.StockStatusAvailable, Metadata: metadata, }) } // 批量插入数据库 - if _, err = dao.StockDetails.BatchInsert(ctx, stockInterfaces); err != nil { + if _, err := dao.StockDetails.BatchInsert(ctx, stockInterfaces); err != nil { return err } } @@ -268,7 +256,7 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) stockCount = 0 - stockCount // 更新批次 batch := stockDto.UpdateBatchReq{ - Id: &stockId, + Id: stockId, BatchQty: stockCount, AvailableQty: stockCount, } @@ -283,7 +271,7 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) for pageNum := int64(1); ; pageNum++ { details, total, err := dao.StockDetails.List(ctx, &stockDto.ListStockDetailsReq{ - AssetSkuId: &assetSkuId, + AssetSkuId: assetSkuId, Status: stock.StockStatusAvailable, Page: &beans.Page{PageNum: pageNum, PageSize: pageSize}, }) @@ -317,7 +305,8 @@ func (s *stockManage) AddStock(ctx context.Context, msg map[string]interface{}) stockCount = 0 - stockCount } } - return assetDao.AssetSku.Update(ctx, &assetDto.UpdateAssetSkuReq{Id: &assetSkuId, Stock: stockCount}) + _, err := assetDao.AssetSku.Update(ctx, &assetDto.UpdateAssetSkuReq{Id: assetSkuId, Stock: stockCount}) + return err }) if err != nil { return err diff --git a/update.sql b/update.sql index 5dca35e..23430b9 100644 --- a/update.sql +++ b/update.sql @@ -1,20 +1,17 @@ -----------张斌2025-06-16 15:00:00-------------- --------------------pgsql创建assets_category表语句--------------------------- - -- 分类主表 CREATE TABLE IF NOT EXISTS assets_category ( -- 基础字段 - id BIGSERIAL PRIMARY KEY, + id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT,取消自增 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, - deleter VARCHAR(64), deleted_at timestamp(6), - -- 分类核心字段 - bid VARCHAR(64) NOT NULL, + -- 分类核心字段(移除bid字段) name VARCHAR(128) NOT NULL, parent_id VARCHAR(64) DEFAULT '', path VARCHAR(512) DEFAULT '', @@ -23,27 +20,23 @@ CREATE TABLE IF NOT EXISTS assets_category ( sort INT NOT NULL DEFAULT 0, image VARCHAR(256) DEFAULT '', attrs JSONB DEFAULT '[]'::JSONB, - status SMALLINT NOT NULL DEFAULT 1, - - -- 唯一索引 & 普通索引 - CONSTRAINT uk_category_id UNIQUE (bid) + status SMALLINT NOT NULL DEFAULT 1 ); --- 为分类表添加索引(PostgreSQL 索引单独创建) + +-- 为分类表添加索引(移除原uk_category_id唯一索引,保留其他索引) CREATE INDEX idx_category_parent_id ON assets_category(parent_id); CREATE INDEX idx_category_level ON assets_category(level); CREATE INDEX idx_category_status ON assets_category(status); CREATE INDEX idx_category_is_leaf_node ON assets_category(is_leaf_node); --- 分类表字段注释 +-- 分类表字段注释(移除bid字段注释) COMMENT ON TABLE assets_category IS '商品/服务分类表'; -COMMENT ON COLUMN assets_category.id IS '主键ID'; +COMMENT ON COLUMN assets_category.id IS '主键ID(非自增)'; COMMENT ON COLUMN assets_category.creator IS '创建人'; COMMENT ON COLUMN assets_category.created_at IS '创建时间'; COMMENT ON COLUMN assets_category.updater IS '更新人'; COMMENT ON COLUMN assets_category.updated_at IS '更新时间'; -COMMENT ON COLUMN assets_category.deleter IS '删除人(软删)'; COMMENT ON COLUMN assets_category.deleted_at IS '删除时间(软删)'; -COMMENT ON COLUMN assets_category.bid IS '业务ID'; COMMENT ON COLUMN assets_category.name IS '分类名称'; COMMENT ON COLUMN assets_category.parent_id IS '父分类ID,为空表示根分类'; COMMENT ON COLUMN assets_category.path IS '分类路径,如:/root/parent/child'; @@ -61,20 +54,18 @@ COMMENT ON COLUMN assets_category.status IS '状态:1启用/0禁用'; -- 资产表(asset) CREATE TABLE IF NOT EXISTS assets_asset ( -- 嵌入基础字段(复用 SQLBaseDO 结构) - id BIGSERIAL PRIMARY KEY, + id BIGINT PRIMARY KEY, -- 从BIGSERIAL改为BIGINT,取消自增 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, - deleter VARCHAR(64), deleted_at timestamp(6), - -- 基础信息字段 - bid VARCHAR(64) NOT NULL, + -- 基础信息字段(移除bid字段) name VARCHAR(128) NOT NULL, description TEXT DEFAULT '', type VARCHAR(32) NOT NULL, -- 资产类型:physical实物/virtual虚拟/service服务 - category_id BIGINT NOT NULL, -- 分类ID(对应分类表category_id,实体中定义为uint64,PG用BIGINT适配) + category_id BIGINT NOT NULL, -- 分类ID(对应category分类表id) category_path VARCHAR(512) DEFAULT '', image_url VARCHAR(512) DEFAULT '', images JSONB DEFAULT '[]'::JSONB, -- 图片列表(字符串数组,JSONB存储) @@ -93,13 +84,10 @@ CREATE TABLE IF NOT EXISTS assets_asset ( metadata JSONB, -- 扩展字段(动态元数据) -- 租户相关 - tenant_module_type VARCHAR(64) DEFAULT '', + tenant_module_type VARCHAR(64) DEFAULT '' + ); - -- 唯一索引 - CONSTRAINT uk_asset_id UNIQUE (bid) -); - --- 为资产表添加索引(优化查询性能) +-- 为资产表添加索引(移除原uk_asset_id唯一索引,保留其他索引) CREATE INDEX idx_asset_category_id ON assets_asset(category_id); CREATE INDEX idx_asset_type ON assets_asset(type); CREATE INDEX idx_asset_status ON assets_asset(status); @@ -107,20 +95,18 @@ CREATE INDEX idx_asset_online_time ON assets_asset(online_time); CREATE INDEX idx_asset_offline_time ON assets_asset(offline_time); CREATE INDEX idx_asset_tenant_module_type ON assets_asset(tenant_module_type); --- 为资产表添加注释(PostgreSQL 专属语法) +-- 为资产表添加注释(移除bid字段注释,更新id注释) COMMENT ON TABLE assets_asset IS '资产主表'; -COMMENT ON COLUMN assets_asset.id IS '主键ID'; +COMMENT ON COLUMN assets_asset.id IS '主键ID(非自增)'; COMMENT ON COLUMN assets_asset.creator IS '创建人'; COMMENT ON COLUMN assets_asset.created_at IS '创建时间'; COMMENT ON COLUMN assets_asset.updater IS '更新人'; COMMENT ON COLUMN assets_asset.updated_at IS '更新时间'; -COMMENT ON COLUMN assets_asset.deleter IS '删除人(软删)'; COMMENT ON COLUMN assets_asset.deleted_at IS '删除时间(软删)'; -COMMENT ON COLUMN assets_asset.bid IS '业务ID'; COMMENT ON COLUMN assets_asset.name IS '资产名称'; COMMENT ON COLUMN assets_asset.description IS '资产描述'; COMMENT ON COLUMN assets_asset.type IS '资产类型:physical实物/virtual虚拟/service服务'; -COMMENT ON COLUMN assets_asset.category_id IS '分类ID'; +COMMENT ON COLUMN assets_asset.category_id IS '分类ID(关联assets_category.id)'; COMMENT ON COLUMN assets_asset.category_path IS '分类路径'; COMMENT ON COLUMN assets_asset.image_url IS '主图URL'; COMMENT ON COLUMN assets_asset.images IS '图片列表(JSONB)';