feat: product number
This commit is contained in:
@@ -101,7 +101,7 @@ func (l *PolicyLogic) Policy(in *chore.PolicyReq) (*chore.Response, error) {
|
||||
region = "oss-cn-hangzhou"
|
||||
}
|
||||
if endpoint == utils.StringEmpty {
|
||||
endpoint = "https://lone-images.oss-accelerate.aliyuncs.com"
|
||||
endpoint = "https://oss-accelerate.aliyuncs.com"
|
||||
}
|
||||
if host == utils.StringEmpty {
|
||||
host = "https://images.ailuowan.com"
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
roleSessionName = "oss-upload"
|
||||
region = "oss-cn-hangzhou"
|
||||
bucketName = "lone-images"
|
||||
endpoint = "https://lone-images.oss-accelerate.aliyuncs.com"
|
||||
# SDK 会拼成 {bucket}.{endpoint},这里不要再带 bucket 名
|
||||
# 错误示例: lone-images.oss-accelerate... → 实际请求 lone-images.lone-images.oss-accelerate...
|
||||
endpoint = "https://oss-accelerate.aliyuncs.com"
|
||||
host = "https://images.ailuowan.com"
|
||||
dir = "upload/"
|
||||
expireSeconds = 3600
|
||||
|
||||
@@ -11,6 +11,12 @@ const (
|
||||
ProductTryName = "多次试用"
|
||||
)
|
||||
|
||||
// 库存变更类型(服务间 Number 接口)
|
||||
const (
|
||||
NumberTypeAdd uint32 = 1 // 增加
|
||||
NumberTypeSub uint32 = 2 // 减少
|
||||
)
|
||||
|
||||
// 销售模式
|
||||
const (
|
||||
ProductSalesModelOffline = 1 // 线下
|
||||
@@ -109,6 +115,11 @@ type ProductCheckExist struct {
|
||||
Status uint8 `gorm:"column:status"`
|
||||
}
|
||||
|
||||
type ProductNumberInfo struct {
|
||||
Id int `gorm:"column:id"`
|
||||
Number uint `gorm:"column:number"`
|
||||
}
|
||||
|
||||
type ProductVerify struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"lone-services/pkg/utils"
|
||||
"lone-services/pkg/validate"
|
||||
product "lone-services/rpc/product/pb"
|
||||
"lone-services/services/product/internal/dao"
|
||||
"lone-services/services/product/internal/svc"
|
||||
"lone-services/services/product/validator"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type NumberAddLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewNumberAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NumberAddLogic {
|
||||
return &NumberAddLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *NumberAddLogic) NumberAdd(in *product.NumberAddReq) (*product.Response, error) {
|
||||
var req validator.ProductNumberAddValidator
|
||||
if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty {
|
||||
return outResponse(utils.ErrorParams, msg), nil
|
||||
}
|
||||
|
||||
adminInfo := utils.GetUserFromCtx(l.ctx)
|
||||
if adminInfo.ID < utils.NumberOne {
|
||||
return failResponse(utils.ErrorNoLoginInfo), nil
|
||||
}
|
||||
|
||||
return changeProductNumber(l.Logger, req.Id, dao.NumberTypeAdd, req.Number)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"lone-services/pkg/modelbase"
|
||||
"lone-services/pkg/utils"
|
||||
"lone-services/pkg/validate"
|
||||
product "lone-services/rpc/product/pb"
|
||||
"lone-services/services/product/internal/dao"
|
||||
"lone-services/services/product/internal/model"
|
||||
"lone-services/services/product/internal/svc"
|
||||
"lone-services/services/product/validator"
|
||||
"strconv"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type NumberLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewNumberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NumberLogic {
|
||||
return &NumberLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// Number 服务间增减库存:type=1 增加,type=2 减少
|
||||
func (l *NumberLogic) Number(in *product.NumberReq) (*product.Response, error) {
|
||||
var req validator.ProductNumberValidator
|
||||
if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty {
|
||||
return outResponse(utils.ErrorParams, msg), nil
|
||||
}
|
||||
|
||||
return changeProductNumber(l.Logger, req.Id, req.Type, req.Number)
|
||||
}
|
||||
|
||||
func changeProductNumber(logger logx.Logger, id int64, typ uint32, number uint32) (*product.Response, error) {
|
||||
var info dao.ProductNumberInfo
|
||||
w := modelbase.Params{
|
||||
Eq: map[string]string{"id": strconv.FormatInt(id, 10)},
|
||||
}
|
||||
m := model.ProductModel{}.Init()
|
||||
if err := m.GetOne(w, &info); err != nil {
|
||||
logger.Errorf("product number get: %v", err)
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
if info.Id < 1 {
|
||||
return failResponse(utils.ErrorNotFund), nil
|
||||
}
|
||||
|
||||
var (
|
||||
rows int64
|
||||
err error
|
||||
)
|
||||
switch typ {
|
||||
case dao.NumberTypeAdd:
|
||||
rows, err = m.IncrNumber(id, number)
|
||||
case dao.NumberTypeSub:
|
||||
rows, err = m.DecrNumber(id, number)
|
||||
default:
|
||||
return failResponse(utils.ErrorParams), nil
|
||||
}
|
||||
if err != nil {
|
||||
logger.Errorf("product number change: %v", err)
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
if rows < 1 {
|
||||
if typ == dao.NumberTypeSub {
|
||||
return failResponse(utils.ErrorStockNotEnough), nil
|
||||
}
|
||||
return failResponse(utils.Fail), nil
|
||||
}
|
||||
|
||||
return okResponse(utils.StringEmpty), nil
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package model
|
||||
import (
|
||||
"lone-services/pkg/modelbase"
|
||||
"lone-services/services/product/internal/dao"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ProductModel struct {
|
||||
@@ -21,3 +23,19 @@ func (m ProductModel) Init() ProductModel {
|
||||
func (m ProductModel) Create(data *dao.ProductCreate) error {
|
||||
return m.Base.Create(data)
|
||||
}
|
||||
|
||||
// IncrNumber 原子增加库存
|
||||
func (m ProductModel) IncrNumber(id int64, n uint32) (int64, error) {
|
||||
ret := modelbase.DB().Table(m.TableName()).
|
||||
Where("id = ?", id).
|
||||
Update("number", gorm.Expr("number + ?", n))
|
||||
return ret.RowsAffected, ret.Error
|
||||
}
|
||||
|
||||
// DecrNumber 原子减少库存(库存不足时 RowsAffected=0)
|
||||
func (m ProductModel) DecrNumber(id int64, n uint32) (int64, error) {
|
||||
ret := modelbase.DB().Table(m.TableName()).
|
||||
Where("id = ? AND number >= ?", id, n).
|
||||
Update("number", gorm.Expr("number - ?", n))
|
||||
return ret.RowsAffected, ret.Error
|
||||
}
|
||||
|
||||
@@ -85,3 +85,13 @@ func (s *ProductServer) EditSusceptible(ctx context.Context, in *product.EditSus
|
||||
l := logic.NewEditSusceptibleLogic(ctx, s.svcCtx)
|
||||
return l.EditSusceptible(in)
|
||||
}
|
||||
|
||||
func (s *ProductServer) Number(ctx context.Context, in *product.NumberReq) (*product.Response, error) {
|
||||
l := logic.NewNumberLogic(ctx, s.svcCtx)
|
||||
return l.Number(in)
|
||||
}
|
||||
|
||||
func (s *ProductServer) NumberAdd(ctx context.Context, in *product.NumberAddReq) (*product.Response, error) {
|
||||
l := logic.NewNumberAddLogic(ctx, s.svcCtx)
|
||||
return l.NumberAdd(in)
|
||||
}
|
||||
|
||||
@@ -218,3 +218,34 @@ func (p ProductEditSusceptibleValidator) GetMessage() validate.ValidatorMessages
|
||||
"Type.oneof": "类型不对",
|
||||
}
|
||||
}
|
||||
|
||||
type ProductNumberValidator struct {
|
||||
Id int64 `validate:"required,gt=0"`
|
||||
Type uint32 `validate:"required,oneof=1 2"`
|
||||
Number uint32 `validate:"required,gt=0"`
|
||||
}
|
||||
|
||||
func (p ProductNumberValidator) GetMessage() validate.ValidatorMessages {
|
||||
return validate.ValidatorMessages{
|
||||
"Id.required": "ID不能为空",
|
||||
"Id.gt": "ID必须大于0",
|
||||
"Type.required": "类型不能为空",
|
||||
"Type.oneof": "类型不对",
|
||||
"Number.required": "数量不能为空",
|
||||
"Number.gt": "数量必须大于0",
|
||||
}
|
||||
}
|
||||
|
||||
type ProductNumberAddValidator struct {
|
||||
Id int64 `validate:"required,gt=0"`
|
||||
Number uint32 `validate:"required,gt=0"`
|
||||
}
|
||||
|
||||
func (p ProductNumberAddValidator) GetMessage() validate.ValidatorMessages {
|
||||
return validate.ValidatorMessages{
|
||||
"Id.required": "ID不能为空",
|
||||
"Id.gt": "ID必须大于0",
|
||||
"Number.required": "数量不能为空",
|
||||
"Number.gt": "数量必须大于0",
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user