feat: import services and standardize Go 1.26.5

This commit is contained in:
2026-08-09 10:43:45 +08:00
parent 689c74b28f
commit 86024fa81d
1456 changed files with 220765 additions and 2 deletions

View File

@@ -0,0 +1,71 @@
package product
import (
"context"
"encoding/json"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
)
// CreateComment 评论
func CommentCreate(ctx context.Context, in *pb.CommentItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
RoleValve := &service.ParseOptions{RoleValue: "Mall_Admin"}
if in.GetIsComment() == true {
RoleValve = nil
}
auth, err := service.ParseMetaCtx(ctx, RoleValve)
if err != nil {
return nil, err
}
if in.GetComment() == "" || in.GetNickName() == "" || in.GetProductIdentity() == "" || in.GetStoreIdentity() == "" || in.GetSpecIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
// 组装model
data, err := itemToCommentModel(in)
if err != nil {
return nil, errcode.ErrInternal
}
data.OwnerID = auth.ID
data.OwnerIdentity = auth.Identity
data.ProductIdentity = in.ProductIdentity
data.SpecIdentity = in.SpecIdentity
data.StoreIdentity = in.StoreIdentity
data.Identity = utils.UUID()
err = impl.DBService.Create(data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Identity: data.Identity,
Timeseq: time.Now().UnixMilli(),
}, nil
}
func itemToCommentModel(in *pb.CommentItem) (*models.MallProductComment, error) {
var commentProduct = models.MallProductComment{}
data, err := json.Marshal(in)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &commentProduct)
if err != nil {
return nil, err
}
return &commentProduct, err
}

View File

@@ -0,0 +1,40 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 删除评论
func CommentDelete(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Where("id=? or identity=? or comment_identity=?", in.GetId(), in.GetIdentity(), in.GetIdentity()).Delete(&models.MallProductComment{}).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,91 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
)
// 产品的评论列表
func CommentFetch(ctx context.Context, in *pb.FetchRequest) (reply *pb.CommentListReply, err error) {
// valildate request id,identity.
if in.GetStoreIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
var (
cnt int64 = 0
pageNo int64 = in.GetPageNo()
pageSize int64 = in.GetPageSize()
offset int64 = (pageNo - 1) * pageSize
params = map[string]string{
"store_identity": in.GetStoreIdentity(),
}
data = make([]models.MallProductComment, 0)
res = make([]*pb.CommentItemRep, 0)
)
// vlidate request page_no,page_size.
if pageNo < 1 {
pageNo = 1
offset = 0
}
if pageSize < 50 {
pageSize = 50
offset = (pageNo - 1) * pageSize
}
if err := impl.DBService.Model(&models.MallProductComment{}).Preload("List").Where(params).
Order("created_at desc").Count(&cnt).Offset(int(offset)).Limit(int(pageSize)).Find(&data).Error; err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
for _, val := range data {
line := &pb.CommentItemRep{
Id: int64(val.ID),
Identity: val.Identity,
CreatedAt: val.CreatedAt.Format(time.DateTime),
NickName: val.Nickname,
Score: int32(val.Score),
Comment: val.Comment,
Reply: val.Reply,
ProductIdentity: val.ProductIdentity,
StoreIdentity: val.StoreIdentity,
SpecIdentity: val.SpecIdentity,
CommentIdentity: val.CommentIdentity,
Product: val.Product.Title,
ProductSpec: val.ProductSpec.Title,
}
if len(val.List) > 0 {
for _, v := range val.List {
line.List = append(line.List, &pb.CommentItem{
Id: int64(v.ID),
Identity: v.Identity,
CreatedAt: v.CreatedAt.Format(time.DateTime),
NickName: v.Nickname,
Score: int32(v.Score),
Comment: v.Comment,
Reply: v.Reply,
ProductIdentity: v.ProductIdentity,
StoreIdentity: v.StoreIdentity,
SpecIdentity: v.SpecIdentity,
CommentIdentity: v.CommentIdentity,
Product: v.Product.Title,
ProductSpec: v.ProductSpec.Title,
})
}
}
res = append(res, line)
}
return &pb.CommentListReply{
Data: res,
Count: cnt,
}, nil
}

View File

@@ -0,0 +1,43 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// ModifyComment 修改评论
func CommentModify(ctx context.Context, in *pb.CommentItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
if in.GetIdentity() == "" || in.GetComment() == "" || in.GetNickName() == "" {
return nil, errcode.ErrInvalidArgument
}
// 参数转换
data, err := itemToCommentModel(in)
if err != nil {
return nil, errcode.ErrInternal
}
err = impl.DBService.Select("score", "reply", "product_identity", "store_identity", "spec_identity").Where("identity = ?", in.Identity).Updates(data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,49 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils"
)
// ReComment 回复评论
func CommentRe(ctx context.Context, in *pb.CommentItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
if in.GetProductIdentity() == "" || in.GetStoreIdentity() == "" || in.GetSpecIdentity() == "" || in.GetComment() == "" || in.GetCommentIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
comment := models.MallProductComment{
ProductIdentity: in.ProductIdentity,
SpecIdentity: in.SpecIdentity,
StoreIdentity: in.StoreIdentity,
CommentIdentity: in.Identity,
Nickname: in.NickName,
Score: int8(in.Score),
Comment: in.Comment,
Std_Owner: types.Std_Owner{OwnerID: auth.ID, OwnerIdentity: auth.Identity},
Std_Identity: types.Std_Identity{Identity: utils.ULID()},
}
if err := impl.DBService.Create(&comment).Error; err != nil {
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
Identity: comment.Identity,
}, nil
}

View File

@@ -0,0 +1,39 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// Forbidden 批量操作
func ItemBatchOp(ctx context.Context, in *pb.OpRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
if len(in.GetIdentity()) == 0 {
return nil, errcode.ErrInvalidArgument
}
// TODO: add your logic code & delete this line.
err = impl.DBService.Model(&models.MallProduct{}).Where("identity in ?", in.Identity).Update("status", in.Status).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,225 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/crypto/token"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils"
)
// ItemCreate 创建或更新产品
func ItemCreate(ctx context.Context, in *pb.ProductItem) (reply *pb.StatusReply, err error) {
// 解析授权信息
auth, err := service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 参数校验
err = checkParam(in)
if err != nil {
return nil, err
}
// 数据转换和组装
data, specId, photo, categoryId, err := transitionData(in, auth)
if err != nil {
return nil, err
}
// 根据是否有Identity判断是创建还是更新
if in.Identity == "" {
// 新建产品 - 创建产品及其关联数据
err = models.CreateProduct(data, specId, photo, categoryId)
} else {
// 更新产品 - 修改现有产品信息
err = models.ModifyProduct(data, specId, photo, categoryId)
}
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Identity: data.Identity,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}
// checkParam 参数校验
func checkParam(in *pb.ProductItem) error {
// 保存为草稿状态时,可以跳过部分参数验证
if in.GetStatus() == 4 {
return nil
}
// 必填字段校验
if len(in.GetCategoryId()) == 0 {
return errcode.ErrInvalidArgument
}
if in.GetTitle() == "" {
return errcode.ErrInvalidArgument
}
if in.GetCoverImage() == "" {
return errcode.ErrInvalidArgument
}
if in.GetMeasuringName() == "" {
return errcode.ErrInvalidArgument
}
if in.GetContent() == "" {
return errcode.ErrInvalidArgument
}
// 数值范围校验
if in.GetSellMin() < 0 || in.GetSellMax() < 0 {
return errcode.ErrInvalidArgument
}
if in.GetSellMin() > in.GetSellMax() {
return errcode.ErrInvalidArgument
}
return nil
}
// transitionData 数据转换和组装
func transitionData(in *pb.ProductItem, auth *token.Claims) (*models.MallProduct, []*models.ProductSpec, []*models.MallProductPhotos, []*models.ProductCategory, error) {
// 转换产品基本信息
data, err := itemToModel(in)
if err != nil {
return nil, nil, nil, nil, errcode.ErrInternal
}
// 新建产品时设置默认值
if data.Identity == "" {
data.Identity = utils.UUID()
owner := auth.Owner.(map[string]any)
data.Store_ID = uint(owner["store_id"].(float64))
data.Store_Identity = owner["store_identity"].(string)
}
// 组装分类关联数据
categoryId := make([]*models.ProductCategory, 0, len(in.CategoryId))
for _, v := range in.CategoryId {
categoryId = append(categoryId, &models.ProductCategory{
Std_IICUDS: types.Std_IICUDS{Identity: utils.UUID()},
CategoryId: v,
})
}
// 组装规格关联数据
specId := make([]*models.ProductSpec, 0, len(in.SpecId))
for _, v := range in.SpecId {
specId = append(specId, &models.ProductSpec{
Std_IICUDS: types.Std_IICUDS{Identity: utils.UUID()},
SpecId: v,
})
}
// 转换产品图片数据
photo := itemToModelPhoto(data.Identity, in.Images)
return data, specId, photo, categoryId, nil
}
// itemToModel 将请求数据转换为模型数据
func itemToModel(in *pb.ProductItem) (*models.MallProduct, error) {
mallProduct := models.MallProduct{
SerialId: in.SerialId,
SupplyId: in.SupplyId,
Title: in.Title,
MeasuringName: in.MeasuringName,
SellMax: int32(in.SellMax),
SellMin: int32(in.SellMin),
Wastage: int32(in.Wastage),
StandardNumber: in.StandardNumber,
Brand: in.Brand,
StockType: int32(in.StockType),
Status: in.Status,
PutawayTime: in.PutawayTime,
CoverImage: in.CoverImage,
TemplateID: int64(in.TemplateId),
RecentNumber: in.RecentNumber,
Limitation: in.Limitation,
LiTemplateID: in.LiTemplateId,
Content: in.Content,
Notes: in.Note,
SaleTotal: int32(in.SaleTotal),
GasType: int32(in.GasTypes),
Recommend: 1, // 默认推荐状态
}
// 更新操作时设置Identity
if in.Identity != "" {
mallProduct.Identity = in.Identity
}
// 根据序列号设置气体类型
if in.SerialId == "gas_by_kg" {
mallProduct.GasType = 2
} else if in.SerialId == "gas_by_bottle" {
mallProduct.GasType = 1
}
return &mallProduct, nil
}
func itemToModelSpec(identity string) ([]*models.MallProductSpec, error) {
var specification = make([]*models.MallProductSpec, 0)
// for _, v := range in {
// data := models.MallProductSpec{
// Title: v.Title,
// StockType: v.StockType,
// Stock: v.Stock,
// Price: v.Price,
// DirectSales: v.DirectSales,
// DsTpType: v.DsTpType,
// TpType: v.TpType,
// Img: v.Img,
// ProductIdentity: identity,
// }
// if v.Identity == "" {
// data.Identity = utils.UUID()
// } else {
// data.ID = uint(v.Id)
// data.Identity = v.Identity
// }
// specification = append(specification, &data)
// }
return specification, nil
}
// itemToModelPhoto 转换产品图片数据
func itemToModelPhoto(identity string, in []*pb.PhotoItem) []*models.MallProductPhotos {
photo := make([]*models.MallProductPhotos, 0, len(in))
for _, v := range in {
img := &models.MallProductPhotos{
Url: v.Url,
ProductIdentity: identity,
Name: v.Name,
}
// 更新操作时设置ID和Identity
if v.Identity != "" {
img.ID = uint(v.Id)
img.Identity = v.Identity
} else {
// 新建时生成新的Identity
img.Identity = utils.ULID()
}
photo = append(photo, img)
}
return photo
}

View File

@@ -0,0 +1,40 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 删除产品
func ItemDelete(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Where("id=? or identity=?", in.GetId(), in.GetIdentity()).Delete(&models.MallProduct{}).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,46 @@
package product
import (
"context"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
)
// Detail 获取产品详情
func ItemDetail(ctx context.Context, in *pb.IdentRequest) (reply *pb.ProductItem, err error) {
if in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
var data = &models.MallProduct{}
err = impl.DBService.Preload("Specs.Spec").Preload("Images").Preload("Categories.Category").Where("identity = ?", in.Identity).First(data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
reply, err = ModelToProductItem(data)
if err != nil {
return nil, err
}
if reply.SupplyId != 0 {
supply := map[string]any{}
if err := impl.DBService.Table("market_supply").Take(&supply, "id = ?", reply.SupplyId).Error; err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
reply.SupplyName = supply["name"].(string)
}
for _, v := range data.Categories {
reply.CategoryId = append(reply.CategoryId, int64(v.CategoryId))
}
for _, v := range data.Specs {
reply.SpecId = append(reply.SpecId, int64(v.SpecId))
}
return reply, nil
}

View File

@@ -0,0 +1,37 @@
package product
import (
"context"
"errors"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"gorm.io/gorm"
)
// Detail 通过产品序列获取产品详情
func ItemDetailBySerial(ctx context.Context, in *pb.StoreSerialRequest) (reply *pb.ListReply, err error) {
if len(in.SerialId) == 0 || in.StoreIdentity == "" {
return nil, errcode.ErrInvalidArgument
}
data := make([]*models.MallProduct, 0)
err = impl.DBService.Preload("Spec").Preload("Images").Preload("Category").Where("store_identity=? and serial_id in ?", in.StoreIdentity, in.SerialId).Find(&data).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errcode.ErrNotFound(404, "Product")
}
printer.Error(err.Error())
return nil, errcode.ErrDB
}
resp := ModelsToProductItems(data)
return &pb.ListReply{
Count: int64(len(resp)),
Data: resp,
}, nil
}

View File

@@ -0,0 +1,21 @@
package product
import (
"context"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
)
// DetailBySpec 通过规格编号获取产品详情
func ItemDetailBySpec(ctx context.Context, in *pb.DetailBySpecRequest) (reply *pb.ListItem, err error) {
if in.GetSpecNo() == "" {
return nil, errcode.ErrInvalidArgument
}
// TODO: valid code
// TODO: add your logic code & delete this line.
return
}

View File

@@ -0,0 +1,100 @@
package product
import (
"context"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"gorm.io/gorm"
)
// 获取产品列表
func ItemFetch(ctx context.Context, in *pb.FetchRequest) (reply *pb.ListReply, err error) {
if in.GetStoreIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
var (
cnt int64 = 0
pageNo int64 = in.GetPageNo()
pageSize int64 = in.GetPageSize()
offset int64 = (pageNo - 1) * pageSize
params = map[string]string{
"mall_product.store_identity": in.GetStoreIdentity(),
}
idList = make([]uint, 0)
product []*models.MallProduct
)
// vlidate request page_no,page_size.
if pageNo < 1 {
pageNo = 1
offset = 0
}
if pageSize <= 0 {
pageSize = 10
offset = (pageNo - 1) * pageSize
}
if err := impl.DBService.Model(&models.MallProduct{}).Where(params).Preload("Images").Preload("Specs.Spec").Preload("Categories.Category").
Order("created_at desc").Count(&cnt).Offset(int(offset)).Limit(int(pageSize)).Find(&product).Error; err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
tx := impl.DBService.Model(&models.MallProduct{})
// 根据传入的分类id进行过滤
if len(in.GetCategoryId()) != 0 {
tx = tx.Where("product_category.category_id in ?", idList).
Joins("left join product_category on mall_product.id = product_category.product_id").
Joins("left join mall_category on mall_category.id = product_category.category_id")
}
// 根据传入的关键字进行模糊搜索
if in.GetKeyword() != "" {
tx = tx.Where("mall_product.title like ?", "%"+in.GetKeyword()+"%")
}
// 根据传入的价格区间进行价格过滤
if in.GetMinPrice() != 0 || in.GetMaxPrice() != 0 {
tx = tx.Joins("left join product_spec on product_spec.product_id = mall_product.id").
Joins("left join mall_product_spec on mall_product_spec.id = product_spec.spec_id").
Where("mall_product_spec.price between ? and ?", in.GetMinPrice(), in.GetMaxPrice())
}
// 根据传入sort排序
switch in.GetSort() {
case "1":
tx = tx.Order("mall_product.title asc")
case "2":
tx = tx.Order("mall_product.title desc")
case "3":
tx = tx.Order("mall_product.sales_price asc")
default:
tx = tx.Order("mall_product.created_at desc")
}
if err := tx.Where(params).Preload("Images").
Preload("Specs.Spec", func(db *gorm.DB) *gorm.DB { return db.Order("mall_product_spec.price") }).
Preload("Categories.Category").Count(&cnt).Offset(int(offset)).Limit(int(pageSize)).
Find(&product).Error; err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
// 将数据库中的数据转换成pb.ProductItem
data := ModelsToProductItems(product)
for _, val := range data {
for _, v := range val.Categories {
val.CategoryId = append(val.CategoryId, v.Id)
}
}
for _, val := range data {
for _, v := range val.Specification {
val.SpecId = append(val.SpecId, v.Id)
}
}
return &pb.ListReply{
Count: cnt,
Data: data,
}, nil
}

View File

@@ -0,0 +1,39 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// Modify 发布/取消发布 产品
func ItemModify(ctx context.Context, in *pb.ModifyRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 检测参数
if in.GetIdentity() == "" || in.GetStatus() == 0 {
return nil, errcode.ErrInvalidArgument
}
// TODO: add your logic code & delete this line.
if err := impl.DBService.Model(&models.MallProduct{}).Where("identity = ?", in.Identity).Update("status", in.Status).Error; err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -0,0 +1,48 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
)
// 添加产品图片
func PhotoCreate(ctx context.Context, in *pb.PhotoItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 参数检测
if in.GetUrl() == "" || in.GetProductIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
// 数据组装
var photo = models.MallProductPhotos{
Name: in.Name,
ProductIdentity: in.ProductIdentity,
Url: in.Url,
}
photo.Identity = utils.UUID()
tx := impl.DBService.Create(&photo)
cnt, err := tx.RowsAffected, tx.Error
if cnt == 0 || err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,42 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 删除产品图片
func PhotoDelete(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Where("id=? or identity=?", in.GetId(), in.GetIdentity()).Delete(&models.MallProductPhotos{}).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
// TODO: add your logic code & delete this line.
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,43 @@
package product
import (
"context"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
)
// 图片列表
func PhotoList(ctx context.Context, in *pb.PhotoItem) (reply *pb.PhotoReply, err error) {
if in.GetProductIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
var cnt int64 = 0
data := make([]*models.MallProductPhotos, 0)
err = impl.DBService.Where("product_identity = ?", in.ProductIdentity).Order("created_at desc").Find(&data).Count(&cnt).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.PhotoReply{Count: cnt, Data: ModelToReplyPhotoList(data)}, nil
}
func ModelToReplyPhotoList(data []*models.MallProductPhotos) []*pb.PhotoItem {
var list = make([]*pb.PhotoItem, 0)
for _, v := range data {
low := &pb.PhotoItem{
Name: v.Name,
Identity: v.Identity,
ProductIdentity: v.ProductIdentity,
Url: v.Url,
}
list = append(list, low)
}
return list
}

View File

@@ -0,0 +1,189 @@
package product
import (
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
)
func ModelsToProductItems(data []*models.MallProduct) (list []*pb.ProductItem) {
if len(data) == 0 {
return
}
for _, v := range data {
line := pb.ProductItem{
Id: int64(v.ID),
Identity: v.Identity,
SupplyId: v.SupplyId,
Title: v.Title,
MeasuringName: v.MeasuringName,
SellMax: int64(v.SellMax),
SellMin: int64(v.SellMin),
Wastage: int64(v.Wastage),
StandardNumber: v.StandardNumber,
Brand: v.Brand,
StockType: int64(v.StockType),
Status: v.Status,
PutawayTime: v.PutawayTime,
CoverImage: v.CoverImage,
Content: v.Content,
SerialId: v.SerialId,
CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05"),
SaleTotal: int64(v.SaleTotal),
RecentNumber: v.RecentNumber,
GasTypes: int64(v.GasType),
}
for _, image := range v.Images {
line.Images = append(line.Images, &pb.PhotoItem{
Id: int64(image.ID),
Identity: image.Identity,
Name: image.Name,
ProductIdentity: image.ProductIdentity,
Sort: image.Sort,
Url: image.Url,
})
}
for _, specs := range v.Specs {
line.Specification = append(line.Specification, &pb.SpecItem{
Id: int64(specs.Spec.ID),
Identity: specs.Identity,
ProductIdentity: v.Identity,
Title: specs.Spec.Title,
StockType: specs.Spec.StockType,
Stock: specs.Spec.Stock,
Price: specs.Spec.Price,
DirectSales: specs.Spec.DirectSales,
TpType: specs.Spec.TpType,
DsTpType: specs.Spec.DsTpType,
Img: specs.Spec.Img,
})
}
for _, categories := range v.Categories {
line.Categories = append(line.Categories, &pb.CategoriesItem{
Id: int64(categories.Category.ID),
Identity: categories.Identity,
Title: categories.Category.Title,
EnTitle: categories.Category.EnTitle,
ParentId: int64(categories.Category.ParentID),
Paths: categories.Category.Paths,
Intro: categories.Category.Intro,
Icon: categories.Category.Icon,
Sort: int32(categories.Category.Sort),
Status: int32(categories.Status),
Keys: categories.Category.Keys,
})
}
if len(line.Images) == 0 {
line.Images = make([]*pb.PhotoItem, 0)
}
if len(v.Specs) > 0 {
line.Price = v.Specs[0].Spec.Price
line.Stock = v.Specs[0].Spec.Stock
}
list = append(list, &line)
}
return
}
func ModelToProductItem(data *models.MallProduct) (*pb.ProductItem, error) {
var item = &pb.ProductItem{
Id: int64(data.ID),
Identity: data.Identity,
SupplyId: data.SupplyId,
SerialId: data.SerialId,
Title: data.Title,
MeasuringName: data.MeasuringName,
SellMax: int64(data.SellMax),
SellMin: int64(data.SellMin),
Wastage: int64(data.Wastage),
StandardNumber: data.StandardNumber,
Brand: data.Brand,
StockType: int64(data.StockType),
Status: data.Status,
PutawayTime: data.PutawayTime,
CoverImage: data.CoverImage,
Content: data.Content,
TemplateId: int32(data.TemplateID),
Note: data.Notes,
Images: []*pb.PhotoItem{},
Specification: []*pb.SpecItem{},
Categories: []*pb.CategoriesItem{},
RecentNumber: data.RecentNumber,
Limitation: data.Limitation,
LiTemplateId: data.LiTemplateID,
SaleTotal: int64(data.SaleTotal),
CreatedAt: data.CreatedAt.Format("2006-01-02 15:04:05"),
GasTypes: int64(data.GasType),
}
if len(data.Images) != 0 {
item.Images = make([]*pb.PhotoItem, 0)
for _, v := range data.Images {
item.Images = append(item.Images, &pb.PhotoItem{
Identity: v.Identity,
Url: v.Url,
Name: v.Name,
Id: int64(v.ID),
})
}
}
if len(data.Specs) != 0 {
item.Specification = make([]*pb.SpecItem, 0)
for _, specs := range data.Specs {
item.Specification = append(item.Specification, &pb.SpecItem{
Id: int64(specs.Spec.ID),
Identity: specs.Identity,
Title: specs.Spec.Title,
StockType: specs.Spec.StockType,
Stock: specs.Spec.Stock,
Img: specs.Spec.Img,
Price: specs.Spec.Price,
SpecNo: specs.Spec.SerialNumber,
Keyword: specs.Spec.Keyword,
PurchasingPrice: specs.Spec.PurchasingPrice,
Wholesale: specs.Spec.Wholesale,
})
}
}
if len(data.Categories) != 0 {
item.Categories = make([]*pb.CategoriesItem, 0)
for _, categories := range data.Categories {
item.Categories = append(item.Categories, &pb.CategoriesItem{
Id: int64(categories.Category.ID),
Identity: categories.Identity,
Title: categories.Category.Title,
EnTitle: categories.Category.EnTitle,
ParentId: int64(categories.Category.ParentID),
Paths: categories.Category.Paths,
Intro: categories.Category.Intro,
Icon: categories.Category.Icon,
Sort: int32(categories.Category.Sort),
Keys: categories.Category.Keys,
})
}
}
return item, nil
}
func ModelToReplySpecList(data []*models.MallProductSpec) []*pb.SpecItem {
var res []*pb.SpecItem
for _, datum := range data {
res = append(res, &pb.SpecItem{
Id: int64(datum.ID),
Identity: datum.Identity,
Title: datum.Title,
StockType: datum.StockType,
Stock: datum.Stock,
Price: datum.Price,
DirectSales: datum.DirectSales,
TpType: datum.TpType,
DsTpType: datum.DsTpType,
Img: datum.Img,
SpecNo: datum.SpecNo,
Keyword: datum.Keyword,
Wholesale: datum.Wholesale,
})
}
return res
}

View File

@@ -0,0 +1,109 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
)
// CreateSpec 添加产品规格
func SpecCreate(ctx context.Context, in *pb.SpecItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 检测参数
err = checkParamSpecCreate(in)
if err != nil {
return nil, err
}
// 数据组装
data, err := requestToModelSpec(in)
if err != nil {
return nil, err
}
data.Identity = utils.UUID()
tx := impl.DBService.Create(data)
cnt, err := tx.RowsAffected, tx.Error
if cnt == 0 || err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Identity: data.Identity,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}
func checkParamSpecCreate(in *pb.SpecItem) error {
if in.GetTitle() == "" {
return errcode.ErrInvalidArgument
}
if in.GetImg() == "" {
return errcode.ErrInvalidArgument
}
if in.GetStock() == 0 {
return errcode.ErrInvalidArgument
}
if in.GetPrice() == 0 {
return errcode.ErrInvalidArgument
}
if in.GetSpecNo() == "" {
return errcode.ErrInvalidArgument
}
// if in.GetKeyword() == "" {
// return errcode.ErrInvalidArgument
// }
if in.GetPurchasingPrice() == 0 {
return errcode.ErrInvalidArgument
}
// if in.GetSupplyId() == 0 {
// return errcode.ErrInvalidArgument
// }
return nil
}
func requestToModelSpec(in *pb.SpecItem) (*models.MallProductSpec, error) {
var specification = &models.MallProductSpec{
SupplyId: in.SupplyId,
StoreIdentity: in.StoreIdentity,
Title: in.Title,
StockType: 2,
Stock: in.Stock,
Price: in.Price,
DirectSales: in.DirectSales,
TpType: 2,
DsTpType: 2,
Img: in.Img,
SpecNo: in.SpecNo,
Keyword: in.Keyword,
PurchasingPrice: in.PurchasingPrice,
Wholesale: in.Wholesale,
}
if in.StockType != 2 {
specification.Stock = int64(in.StockType)
}
if in.TpType != 2 {
specification.TpType = in.TpType
}
if in.DsTpType != 2 {
specification.DsTpType = in.DsTpType
}
if in.Identity != "" {
specification.Identity = in.Identity
}
return specification, nil
}

View File

@@ -0,0 +1,41 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 删除产品规格
func SpecDelete(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Where("id=? or identity=?", in.GetId(), in.GetIdentity()).Delete(&models.MallProductSpec{}).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
// TODO: add your logic code & delete this line.
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,41 @@
package product
import (
"context"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
)
// DetailSpec 产品详情
func SpecDetail(ctx context.Context, in *pb.IdentRequest) (reply *pb.SpecItem, err error) {
if in.GetIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
var data models.MallProductSpec
err = impl.DBService.Model(&models.MallProductSpec{}).Where("identity = ?", in.Identity).First(&data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.SpecItem{
Id: int64(data.ID),
Identity: data.Identity,
SupplyId: data.SupplyId,
Title: data.Title,
StockType: data.StockType,
Stock: data.Stock,
Price: data.Price,
DirectSales: data.DirectSales,
TpType: data.TpType,
DsTpType: data.DsTpType,
Img: data.Img,
PurchasingPrice: data.PurchasingPrice,
Wholesale: data.Wholesale,
}, nil
}

View File

@@ -0,0 +1,41 @@
package product
import (
"context"
"git.apinb.com/bsm-ec/mall/internal/impl"
"git.apinb.com/bsm-ec/mall/internal/models"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// 产品规格列表
func SpecFetch(ctx context.Context, in *pb.FetchRequest) (reply *pb.SpecReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
if in.StoreIdentity == "" {
return nil, errcode.ErrInvalidArgument
}
spec := make([]*models.MallProductSpec, 0)
tx := impl.DBService.Model(&models.MallProductSpec{}).Where("store_identity = ?", in.StoreIdentity)
if in.Keyword != "" {
tx = tx.Where("keyword like ?", "%"+in.Keyword+"%")
}
err = tx.Order("created_at desc").Find(&spec).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.SpecReply{
Count: int64(len(spec)),
Data: ModelToReplySpecList(spec),
}, nil
}

View File

@@ -0,0 +1,73 @@
package product
import (
"context"
"time"
"git.apinb.com/bsm-ec/mall/internal/impl"
pb "git.apinb.com/bsm-ec/mall/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
)
// ModifySpec 修改产品规格
func SpecModify(ctx context.Context, in *pb.SpecItem) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 检测参数
err = checkParamSpecModify(in)
if err != nil {
return nil, err
}
// 数据组装
data, err := requestToModelSpec(in)
if err != nil {
return nil, err
}
err = impl.DBService.Where("identity=?", data.Identity).Updates(data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Identity: data.Identity,
Message: "OK",
Timeseq: time.Now().UnixMilli(),
}, nil
}
func checkParamSpecModify(in *pb.SpecItem) error {
if in.GetIdentity() == "" {
return errcode.ErrInvalidArgument
}
// if in.GetProductIdentity() == "" {
// return errcode.ErrInvalidArgument
// }
if in.GetTitle() == "" {
return errcode.ErrInvalidArgument
}
if in.GetImg() == "" {
return errcode.ErrInvalidArgument
}
if in.GetStock() == 0 {
return errcode.ErrInvalidArgument
}
if in.GetPrice() == 0 {
return errcode.ErrInvalidArgument
}
if in.GetPurchasingPrice() == 0 {
return errcode.ErrInvalidArgument
}
return nil
}