Merge branch 'ldm-v1.01' into feature/mhw-v1.01
This commit is contained in:
commit
6e89f318fd
6
constants/min_purchase_box.go
Normal file
6
constants/min_purchase_box.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package constants
|
||||
|
||||
type Purchase int64
|
||||
|
||||
// 最低购买箱数
|
||||
const MIN_PURCHASE_QUANTITY Purchase = 3
|
35
model/gmodel/fs_orders_trade_gen.go
Normal file
35
model/gmodel/fs_orders_trade_gen.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package gmodel
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// fs_orders_trade 订单交易记录表
|
||||
type FsOrdersTrade struct {
|
||||
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` // 订单交易ID
|
||||
UserId *int64 `gorm:"index;default:0;" json:"user_id"` // 用户ID
|
||||
OrderNo *string `gorm:"default:'';" json:"order_no"` //
|
||||
OrderSource *string `gorm:"default:'';" json:"order_source"` //
|
||||
TradeNo *string `gorm:"index;default:'';" json:"trade_no"` //
|
||||
PayAmount *int64 `gorm:"default:0;" json:"pay_amount"` // 支付金额 (分)
|
||||
PayStatus *int64 `gorm:"default:0;" json:"pay_status"` // 支付状态:1=未成功,2=已成功
|
||||
PaymentMethod *int64 `gorm:"default:0;" json:"payment_method"` // 支付方式:1=stripe,2=paypal
|
||||
PayStage *int64 `gorm:"default:0;" json:"pay_stage"` // 支付阶段:1=首付,2=尾款
|
||||
RefundStatus *int64 `gorm:"default:0;" json:"refund_status"` // 退款状态:1=未退款,2=已退款
|
||||
CardNo *string `gorm:"default:'';" json:"card_no"` //
|
||||
CardBrand *string `gorm:"default:'';" json:"card_brand"` //
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
Country *string `gorm:"default:'';" json:"country"` //
|
||||
Currency *string `gorm:"default:'';" json:"currency"` //
|
||||
Metadata *[]byte `gorm:"default:'';" json:"metadata"` //
|
||||
}
|
||||
type FsOrdersTradeModel struct {
|
||||
db *gorm.DB
|
||||
name string
|
||||
}
|
||||
|
||||
func NewFsOrdersTradeModel(db *gorm.DB) *FsOrdersTradeModel {
|
||||
return &FsOrdersTradeModel{db: db, name: "fs_orders_trade"}
|
||||
}
|
2
model/gmodel/fs_orders_trade_logic.go
Normal file
2
model/gmodel/fs_orders_trade_logic.go
Normal file
|
@ -0,0 +1,2 @@
|
|||
package gmodel
|
||||
// TODO: 使用model的属性做你想做的
|
|
@ -17,8 +17,6 @@ type FsShoppingCart struct {
|
|||
PurchaseQuantity *int64 `gorm:"default:0;" json:"purchase_quantity"` // 购买数量
|
||||
Snapshot *string `gorm:"default:'';" json:"snapshot"` //
|
||||
IsHighlyCustomized *int64 `gorm:"default:0;" json:"is_highly_customized"` // 是否高度定制 0非 1是(针对客人高度定制只能后台增加如购物车)
|
||||
Status *int64 `gorm:"default:0;" json:"status"` // 0未下单 1已下单
|
||||
IsEffective *int64 `gorm:"default:1;" json:"is_effective"` // 是否有效 0非 1是(针对对购物车下单,此前数据表更失效)
|
||||
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
|
||||
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
|
||||
}
|
||||
|
|
|
@ -1,2 +1,88 @@
|
|||
package gmodel
|
||||
// TODO: 使用model的属性做你想做的
|
||||
|
||||
import "context"
|
||||
|
||||
// 获取单个
|
||||
func (s *FsShoppingCartModel) FindOne(ctx context.Context, id int64, fields ...string) (resp *FsShoppingCart, err error) {
|
||||
db := s.db.WithContext(ctx).Where("id = ?", id)
|
||||
if len(fields) > 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
err = db.Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// 获取用户购物车指定item
|
||||
func (s *FsShoppingCartModel) FineOneUserCart(ctx context.Context, id, userId int64, fields ...string) (resp *FsShoppingCart, err error) {
|
||||
db := s.db.WithContext(ctx).Where("user_id = ? and id = ?", userId, id)
|
||||
if len(fields) > 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
err = db.Take(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// 创建
|
||||
func (s *FsShoppingCartModel) Create(ctx context.Context, data *FsShoppingCart) error {
|
||||
return s.db.WithContext(ctx).Create(&data).Error
|
||||
}
|
||||
|
||||
// 更新
|
||||
func (s *FsShoppingCartModel) Update(ctx context.Context, id, userId int64, data *FsShoppingCart) error {
|
||||
return s.db.WithContext(ctx).Where("user_id = ? and id = ?", userId, id).Updates(&data).Error
|
||||
}
|
||||
|
||||
// 获取用户购物车数量
|
||||
func (s *FsShoppingCartModel) CountUserCart(ctx context.Context, userId int64) (total int64, err error) {
|
||||
err = s.db.WithContext(ctx).Where("user_id = ?", userId).Limit(1).Count(&total).Error
|
||||
return total, err
|
||||
}
|
||||
|
||||
// 获取多个
|
||||
func (s *FsShoppingCartModel) GetAllByIds(ctx context.Context, ids []int64, sort string, fields ...string) (resp []FsShoppingCart, err error) {
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
}
|
||||
db := s.db.WithContext(ctx).Where("id in (?)", ids)
|
||||
if len(fields) > 0 {
|
||||
db = db.Select(fields[0])
|
||||
}
|
||||
if sort != "" {
|
||||
db = db.Order(sort)
|
||||
}
|
||||
err = db.Find(&resp).Error
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// 获取用户所有的购物车
|
||||
type GetAllCartsByParamReq struct {
|
||||
Ids []int64 //id集合
|
||||
UserId int64 //用户id
|
||||
Fields string //筛选的字段
|
||||
Sort string //排序
|
||||
Page int //当前页
|
||||
Limit int //每页数量
|
||||
}
|
||||
|
||||
func (s *FsShoppingCartModel) GetAllCartsByParam(ctx context.Context, req GetAllCartsByParamReq) (resp []FsShoppingCart, total int64, err error) {
|
||||
db := s.db.WithContext(ctx)
|
||||
if req.UserId > 0 {
|
||||
db = db.Where("user_id = ?", req.UserId)
|
||||
}
|
||||
if len(req.Ids) > 0 {
|
||||
db = db.Where("id in (?)", req.Ids)
|
||||
}
|
||||
if req.Fields != "" {
|
||||
db = db.Select(req.Fields)
|
||||
}
|
||||
if req.Sort != "" {
|
||||
db = db.Order(req.Sort)
|
||||
}
|
||||
//查询数量
|
||||
if err = db.Limit(1).Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
offset := (req.Page - 1) * req.Limit
|
||||
err = db.Offset(offset).Limit(req.Limit).Find(&resp).Error
|
||||
return resp, total, err
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ type AllModelsGen struct {
|
|||
FsOrderDetail *FsOrderDetailModel // fs_order_detail 订单详细表
|
||||
FsOrderDetailTemplate *FsOrderDetailTemplateModel // fs_order_detail_template 订单模板详细表
|
||||
FsOrderRemark *FsOrderRemarkModel // fs_order_remark 订单备注表
|
||||
FsOrdersTrade *FsOrdersTradeModel // fs_orders_trade 订单交易记录表
|
||||
FsPay *FsPayModel // fs_pay 支付记录
|
||||
FsPayEvent *FsPayEventModel // fs_pay_event 支付回调事件日志
|
||||
FsProduct *FsProductModel // fs_product 产品表
|
||||
|
@ -167,6 +168,7 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
|
|||
FsOrderDetail: NewFsOrderDetailModel(gdb),
|
||||
FsOrderDetailTemplate: NewFsOrderDetailTemplateModel(gdb),
|
||||
FsOrderRemark: NewFsOrderRemarkModel(gdb),
|
||||
FsOrdersTrade: NewFsOrdersTradeModel(gdb),
|
||||
FsPay: NewFsPayModel(gdb),
|
||||
FsPayEvent: NewFsPayEventModel(gdb),
|
||||
FsProduct: NewFsProductModel(gdb),
|
||||
|
|
12
server/shopping-cart/etc/shopping-cart.yaml
Normal file
12
server/shopping-cart/etc/shopping-cart.yaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
Name: shopping-cart
|
||||
Host: 0.0.0.0
|
||||
Port: 9918
|
||||
Timeout: 15000 #服务超时时间(毫秒)
|
||||
SourceMysql: fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen
|
||||
SourceRabbitMq: amqp://rabbit001:rabbit001129@110.41.19.98:5672
|
||||
Log:
|
||||
Stat: false
|
||||
Auth:
|
||||
AccessSecret: fusen2023
|
||||
AccessExpire: 2592000
|
||||
RefreshAfter: 1592000
|
13
server/shopping-cart/internal/config/config.go
Normal file
13
server/shopping-cart/internal/config/config.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
SourceMysql string
|
||||
Auth types.Auth
|
||||
SourceRabbitMq string
|
||||
}
|
35
server/shopping-cart/internal/handler/addtocarthandler.go
Normal file
35
server/shopping-cart/internal/handler/addtocarthandler.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/logic"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
)
|
||||
|
||||
func AddToCartHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.AddToCartReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewAddToCartLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.AddToCart(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
35
server/shopping-cart/internal/handler/deletecarthandler.go
Normal file
35
server/shopping-cart/internal/handler/deletecarthandler.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/logic"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
)
|
||||
|
||||
func DeleteCartHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.DeleteCartReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewDeleteCartLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.DeleteCart(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
35
server/shopping-cart/internal/handler/getcartshandler.go
Normal file
35
server/shopping-cart/internal/handler/getcartshandler.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/logic"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
)
|
||||
|
||||
func GetCartsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.GetCartsReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewGetCartsLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.GetCarts(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/logic"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
)
|
||||
|
||||
func ModifyCartPurchaseQuantityHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req types.ModifyCartPurchaseQuantityReq
|
||||
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建一个业务逻辑层实例
|
||||
l := logic.NewModifyCartPurchaseQuantityLogic(r.Context(), svcCtx)
|
||||
|
||||
rl := reflect.ValueOf(l)
|
||||
basic.BeforeLogic(w, r, rl)
|
||||
|
||||
resp := l.ModifyCartPurchaseQuantity(&req, userinfo)
|
||||
|
||||
if !basic.AfterLogic(w, r, rl, resp) {
|
||||
basic.NormalAfterLogic(w, r, resp)
|
||||
}
|
||||
}
|
||||
}
|
37
server/shopping-cart/internal/handler/routes.go
Normal file
37
server/shopping-cart/internal/handler/routes.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/shopping-cart/add_to_cart",
|
||||
Handler: AddToCartHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/shopping-cart/delete_cart",
|
||||
Handler: DeleteCartHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/api/shopping-cart/modify_cart_purchase_quantity",
|
||||
Handler: ModifyCartPurchaseQuantityHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/shopping-cart/get_carts",
|
||||
Handler: GetCartsHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
213
server/shopping-cart/internal/logic/addtocartlogic.go
Normal file
213
server/shopping-cart/internal/logic/addtocartlogic.go
Normal file
|
@ -0,0 +1,213 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/shopping_cart"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AddToCartLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAddToCartLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddToCartLogic {
|
||||
return &AddToCartLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *AddToCartLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *AddToCartLogic) AddToCart(req *types.AddToCartReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in")
|
||||
}
|
||||
//校验参数
|
||||
if err := l.AddToCartParamVerify(req); err != nil {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, err.Error())
|
||||
}
|
||||
//查询该用户购物车数量
|
||||
cartCount, err := l.svcCtx.AllModels.FsShoppingCart.CountUserCart(l.ctx, userinfo.UserId)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get the count of your shopping cart")
|
||||
}
|
||||
if cartCount >= 100 {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "sorry,the count of your carts can`t greater than 100")
|
||||
}
|
||||
//获取产品是否存在
|
||||
productInfo, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists")
|
||||
}
|
||||
logx.Error("获取产品信息错误:", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info")
|
||||
}
|
||||
var (
|
||||
templateJson string //模板表的记录中的json设计信息
|
||||
templateTag string //模板表的模板标签
|
||||
fittingJson string //配件的json设计信息
|
||||
)
|
||||
//有模板
|
||||
if req.TemplateId > 0 {
|
||||
templateInfo, err := l.svcCtx.AllModels.FsProductTemplateV2.FindOne(l.ctx, req.TemplateId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the template is not exists")
|
||||
}
|
||||
logx.Error("获取模板信息错误:", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template info")
|
||||
}
|
||||
if *templateInfo.IsDel == 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template is deleted")
|
||||
}
|
||||
if *templateInfo.Status != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template`s status is unNormal")
|
||||
}
|
||||
if templateInfo.TemplateInfo == nil || *templateInfo.TemplateInfo == "" {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template`s design info is empty")
|
||||
}
|
||||
templateJson = *templateInfo.TemplateInfo
|
||||
templateTag = *templateInfo.TemplateTag
|
||||
}
|
||||
//有配件
|
||||
if req.FittingId > 0 {
|
||||
fittingInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, req.FittingId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the fitting is not exists")
|
||||
}
|
||||
logx.Error("获取配件信息错误:", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting info")
|
||||
}
|
||||
if *fittingInfo.Status != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the fitting`s status is unNormal")
|
||||
}
|
||||
if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the fitting`s design info is empty")
|
||||
}
|
||||
fittingJson = *fittingInfo.ModelInfo
|
||||
}
|
||||
//获取尺寸信息
|
||||
sizeInfo, err := l.svcCtx.AllModels.FsProductSize.FindOne(l.ctx, req.SizeId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the size is not exists")
|
||||
}
|
||||
logx.Error("获取尺寸信息错误:", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get size info")
|
||||
}
|
||||
//状态
|
||||
if *sizeInfo.Status != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "size info status is not normal")
|
||||
}
|
||||
//获取模型信息
|
||||
modelInfo, err := l.svcCtx.AllModels.FsProductModel3d.GetOneBySizeIdTag(l.ctx, sizeInfo.Id, constants.TAG_MODEL)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the template`s model is not exists")
|
||||
}
|
||||
logx.Error("获取模型信息错误:", err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template`s model info")
|
||||
}
|
||||
if *modelInfo.Status != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model` status is unNormal")
|
||||
}
|
||||
//如果模型是配件则返回
|
||||
if *modelInfo.Tag != 1 {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model your post is not a model but fitting")
|
||||
}
|
||||
if modelInfo.ModelInfo == nil || *modelInfo.ModelInfo == "" {
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model`s design info is empty")
|
||||
}
|
||||
var sizeTitleInfo shopping_cart.SizeInfo
|
||||
if err = json.Unmarshal([]byte(*sizeInfo.Title), &sizeTitleInfo); err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse size info`s title ")
|
||||
}
|
||||
//快照数据
|
||||
snapshot := shopping_cart.CartSnapshot{
|
||||
Logo: req.Logo,
|
||||
CombineImage: req.CombineImage,
|
||||
RenderImage: req.RenderImage,
|
||||
TemplateInfo: shopping_cart.TemplateInfo{
|
||||
TemplateJson: templateJson,
|
||||
TemplateTag: templateTag,
|
||||
},
|
||||
ModelInfo: shopping_cart.ModelInfo{
|
||||
ModelJson: *modelInfo.ModelInfo,
|
||||
},
|
||||
FittingInfo: shopping_cart.FittingInfo{
|
||||
FittingJson: fittingJson,
|
||||
},
|
||||
SizeInfo: sizeTitleInfo,
|
||||
ProductInfo: shopping_cart.ProductInfo{
|
||||
ProductName: *productInfo.Title,
|
||||
ProductSn: *productInfo.Sn,
|
||||
},
|
||||
UserDiyInformation: shopping_cart.UserDiyInformation{
|
||||
Phone: req.DiyInfo.Phone,
|
||||
Address: req.DiyInfo.Address,
|
||||
Website: req.DiyInfo.Website,
|
||||
Qrcode: req.DiyInfo.Qrcode,
|
||||
Slogan: req.DiyInfo.Slogan,
|
||||
},
|
||||
}
|
||||
snapshotJsonBytes, _ := json.Marshal(snapshot)
|
||||
snapshotJsonStr := string(snapshotJsonBytes)
|
||||
now := time.Now().UTC()
|
||||
err = l.svcCtx.AllModels.FsShoppingCart.Create(l.ctx, &gmodel.FsShoppingCart{
|
||||
UserId: &userinfo.UserId,
|
||||
ProductId: &req.ProductId,
|
||||
TemplateId: &req.TemplateId,
|
||||
ModelId: &modelInfo.Id,
|
||||
SizeId: &req.SizeId,
|
||||
FittingId: &req.FittingId,
|
||||
PurchaseQuantity: &req.PurchaseQuantity,
|
||||
Snapshot: &snapshotJsonStr,
|
||||
Ctime: &now,
|
||||
Utime: &now,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "system err:failed to add to cart ")
|
||||
}
|
||||
return resp.SetStatus(basic.CodeOK, "success")
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
func (l *AddToCartLogic) AddToCartParamVerify(req *types.AddToCartReq) error {
|
||||
if req.ProductId <= 0 {
|
||||
return errors.New("product_id is required")
|
||||
}
|
||||
if req.SizeId <= 0 {
|
||||
return errors.New("product size is required")
|
||||
}
|
||||
if req.PurchaseQuantity <= 0 {
|
||||
return errors.New("purchase quantity can not less than 0 or equal 0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *AddToCartLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
43
server/shopping-cart/internal/logic/deletecartlogic.go
Normal file
43
server/shopping-cart/internal/logic/deletecartlogic.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type DeleteCartLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDeleteCartLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCartLogic {
|
||||
return &DeleteCartLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *DeleteCartLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *DeleteCartLogic) DeleteCart(req *types.DeleteCartReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
|
||||
// userinfo 传入值时, 一定不为null
|
||||
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *DeleteCartLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
127
server/shopping-cart/internal/logic/getcartslogic.go
Normal file
127
server/shopping-cart/internal/logic/getcartslogic.go
Normal file
|
@ -0,0 +1,127 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fusenapi/constants"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"fusenapi/utils/shopping_cart"
|
||||
"math"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetCartsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetCartsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCartsLogic {
|
||||
return &GetCartsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *GetCartsLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *GetCartsLogic) GetCarts(req *types.GetCartsReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if req.CurrentPage <= 0 {
|
||||
req.CurrentPage = constants.DEFAULT_PAGE
|
||||
}
|
||||
limit := 10
|
||||
//获取用户购物车列表
|
||||
carts, total, err := l.svcCtx.AllModels.FsShoppingCart.GetAllCartsByParam(l.ctx, gmodel.GetAllCartsByParamReq{
|
||||
UserId: userinfo.UserId,
|
||||
Fields: "",
|
||||
Sort: "id DESC",
|
||||
Page: req.CurrentPage,
|
||||
Limit: limit,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "system err:failed to get your shopping carts")
|
||||
}
|
||||
if len(carts) == 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetCartsRsp{
|
||||
Meta: types.Meta{
|
||||
TotalCount: total,
|
||||
PageCount: int64(math.Ceil(float64(total) / float64(limit))),
|
||||
CurrentPage: req.CurrentPage,
|
||||
PerPage: limit,
|
||||
},
|
||||
CartList: nil,
|
||||
})
|
||||
}
|
||||
lenCarts := len(carts)
|
||||
templateIds := make([]int64, 0, lenCarts)
|
||||
modelIds := make([]int64, 0, lenCarts) //模型 + 配件
|
||||
sizeIds := make([]int64, 0, lenCarts)
|
||||
for index := range carts {
|
||||
templateIds = append(templateIds, *carts[index].TemplateId)
|
||||
modelIds = append(modelIds, *carts[index].ModelId, *carts[index].FittingId)
|
||||
sizeIds = append(sizeIds, *carts[index].SizeId)
|
||||
}
|
||||
//获取尺寸列表
|
||||
sizeList, err := l.svcCtx.AllModels.FsProductSize.GetAllByIds(l.ctx, sizeIds, "")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get size list")
|
||||
}
|
||||
mapSize := make(map[int64]gmodel.FsProductSize)
|
||||
for _, v := range sizeList {
|
||||
mapSize[v.Id] = v
|
||||
}
|
||||
//获取模型和配件信息
|
||||
modelList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIds(l.ctx, modelIds, "")
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model list")
|
||||
}
|
||||
mapModel := make(map[int64]gmodel.FsProductModel3d)
|
||||
for _, v := range modelList {
|
||||
mapModel[v.Id] = v
|
||||
}
|
||||
//获取模板列表
|
||||
templateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByIds(l.ctx, templateIds)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template list")
|
||||
}
|
||||
mapTemplate := make(map[int64]gmodel.FsProductTemplateV2)
|
||||
for _, v := range templateList {
|
||||
mapTemplate[v.Id] = v
|
||||
}
|
||||
//定义map收集变更信息
|
||||
mapCartChange := make(map[int64]string)
|
||||
//校验购物车数据是否变更
|
||||
err = shopping_cart.VerifyShoppingCartSnapshotDataChange(shopping_cart.VerifyShoppingCartSnapshotDataChangeReq{
|
||||
Carts: carts,
|
||||
MapSize: mapSize,
|
||||
MapModel: mapModel,
|
||||
MapTemplate: mapTemplate,
|
||||
MapCartChange: mapCartChange,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error("VerifyShoppingCartSnapshotDataChange err:", err.Error())
|
||||
return resp.SetStatusWithMessage(basic.CodeServiceErr, "system err:failed to check shopping cart change data")
|
||||
}
|
||||
/*list := make([]types.CartItem, 0, lenCarts)
|
||||
for index := range carts {
|
||||
|
||||
}*/
|
||||
return resp.SetStatus(basic.CodeOK)
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *GetCartsLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
|
@ -0,0 +1,69 @@
|
|||
package logic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/auth"
|
||||
"fusenapi/utils/basic"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"context"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
"fusenapi/server/shopping-cart/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ModifyCartPurchaseQuantityLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewModifyCartPurchaseQuantityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModifyCartPurchaseQuantityLogic {
|
||||
return &ModifyCartPurchaseQuantityLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// 处理进入前逻辑w,r
|
||||
// func (l *ModifyCartPurchaseQuantityLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
|
||||
// }
|
||||
|
||||
func (l *ModifyCartPurchaseQuantityLogic) ModifyCartPurchaseQuantity(req *types.ModifyCartPurchaseQuantityReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
||||
if !userinfo.IsUser() {
|
||||
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please sign in")
|
||||
}
|
||||
if req.Id <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "cart id is required")
|
||||
}
|
||||
if req.PurchaseQuantity <= 0 {
|
||||
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "purchase quantity can not less than 0 or equal to 0")
|
||||
}
|
||||
//查询购物车
|
||||
_, err := l.svcCtx.AllModels.FsShoppingCart.FineOneUserCart(l.ctx, req.Id, userinfo.UserId, "id")
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the shopping cart is not exists")
|
||||
}
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "system err:failed to get shopping cart info ")
|
||||
}
|
||||
//修改数量
|
||||
err = l.svcCtx.AllModels.FsShoppingCart.Update(l.ctx, req.Id, userinfo.UserId, &gmodel.FsShoppingCart{
|
||||
PurchaseQuantity: &req.PurchaseQuantity,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "system err:failed to modify cart purchase quantity")
|
||||
}
|
||||
return resp.SetStatus(basic.CodeOK, "success")
|
||||
}
|
||||
|
||||
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
|
||||
// func (l *ModifyCartPurchaseQuantityLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
|
||||
// // httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
// }
|
26
server/shopping-cart/internal/svc/servicecontext.go
Normal file
26
server/shopping-cart/internal/svc/servicecontext.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package svc
|
||||
|
||||
import (
|
||||
"fusenapi/initalize"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/server/shopping-cart/internal/config"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
MysqlConn *gorm.DB
|
||||
AllModels *gmodel.AllModelsGen
|
||||
RabbitMq *initalize.RabbitMqHandle
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
conn := initalize.InitMysql(c.SourceMysql)
|
||||
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
MysqlConn: conn,
|
||||
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
|
||||
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
|
||||
}
|
||||
}
|
148
server/shopping-cart/internal/types/types.go
Normal file
148
server/shopping-cart/internal/types/types.go
Normal file
|
@ -0,0 +1,148 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
package types
|
||||
|
||||
import (
|
||||
"fusenapi/utils/basic"
|
||||
)
|
||||
|
||||
type AddToCartReq struct {
|
||||
ProductId int64 `json:"product_id"` //产品id
|
||||
TemplateId int64 `json:"template_id,optional"` //模板id(不可定制的不传)
|
||||
SizeId int64 `json:"size_id"` //尺寸id
|
||||
FittingId int64 `json:"fitting_id,optional"` //配件id(没有可以不传)
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量
|
||||
Logo string `json:"logo,optional"` //logo地址(没有可以不传)
|
||||
CombineImage string `json:"combine_image,optional"` //合图地址 (没有可以不传)
|
||||
RenderImage string `json:"render_image,optional"` //渲染结果图 (没有可以不传)
|
||||
DiyInfo DiyInfo `json:"diy_info,optional"` //用户diy数据(可选)
|
||||
}
|
||||
|
||||
type DiyInfo struct {
|
||||
Phone string `json:"phone,optional"` //电话(可选)
|
||||
Address string `json:"address,optional"` //地址 (可选)
|
||||
Website string `json:"website,optional"` //网站 (可选)
|
||||
Qrcode string `json:"qrcode,optional"` //二维码 (可选)
|
||||
Slogan string `json:"slogan,optional"` //slogan (可选)
|
||||
}
|
||||
|
||||
type DeleteCartReq struct {
|
||||
Id int64 `json:"id"` //购物车id
|
||||
}
|
||||
|
||||
type ModifyCartPurchaseQuantityReq struct {
|
||||
Id int64 `json:"id"` //购物车id
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"` //数量
|
||||
}
|
||||
|
||||
type GetCartsReq struct {
|
||||
CurrentPage int `form:"current_page"` //当前页
|
||||
}
|
||||
|
||||
type GetCartsRsp struct {
|
||||
Meta Meta `json:"meta"` //分页信息
|
||||
CartList []CartItem `json:"cart_list"`
|
||||
}
|
||||
|
||||
type CartItem struct {
|
||||
ProductId int64 `json:"product_id"` //产品id
|
||||
SizeInfo SizeInfo `json:"size_info"` //尺寸信息
|
||||
FittingInfo FittingInfo `json:"fitting_info"` //配件信息
|
||||
ItemPrice string `json:"item_price"` //单价
|
||||
TotalPrice string `json:"totalPrice"` //单价X数量=总价
|
||||
DiyInformation DiyInformation `json:"diy_information"` //diy信息
|
||||
StepNum []int64 `json:"step_num"` //阶梯数量
|
||||
IsInvalid bool `json:"is_invalid"` //是否无效
|
||||
InvalidDescription string `json:"invalid_description"` //无效原因
|
||||
}
|
||||
|
||||
type SizeInfo struct {
|
||||
SizeId int64 `json:"size_id"` //尺寸id
|
||||
Capacity string `json:"capacity"` //尺寸名称
|
||||
Title SizeTitle `json:"title"`
|
||||
}
|
||||
|
||||
type FittingInfo struct {
|
||||
FittingId int64 `json:"fitting_id"` //配件id
|
||||
FittingName string `json:"fitting_name"` //配件名称
|
||||
}
|
||||
|
||||
type SizeTitle struct {
|
||||
Cm string `json:"cm"`
|
||||
Inch string `json:"inch"`
|
||||
}
|
||||
|
||||
type DiyInformation struct {
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
Website string `json:"website"`
|
||||
Qrcode string `json:"qrcode"`
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
AccessSecret string `json:"accessSecret"`
|
||||
AccessExpire int64 `json:"accessExpire"`
|
||||
RefreshAfter int64 `json:"refreshAfter"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Filename string `fsfile:"filename"`
|
||||
Header map[string][]string `fsfile:"header"`
|
||||
Size int64 `fsfile:"size"`
|
||||
Data []byte `fsfile:"data"`
|
||||
}
|
||||
|
||||
type Meta struct {
|
||||
TotalCount int64 `json:"total_count"`
|
||||
PageCount int64 `json:"page_count"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
||||
|
||||
// Set 设置Response的Code和Message值
|
||||
func (resp *Response) Set(Code int, Message string) *Response {
|
||||
return &Response{
|
||||
Code: Code,
|
||||
Message: Message,
|
||||
}
|
||||
}
|
||||
|
||||
// Set 设置整个Response
|
||||
func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response {
|
||||
return &Response{
|
||||
Code: Code,
|
||||
Message: Message,
|
||||
Data: Data,
|
||||
}
|
||||
}
|
||||
|
||||
// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数
|
||||
func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response {
|
||||
newResp := &Response{
|
||||
Code: sr.Code,
|
||||
}
|
||||
if len(data) == 1 {
|
||||
newResp.Data = data[0]
|
||||
}
|
||||
return newResp
|
||||
}
|
||||
|
||||
// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数
|
||||
func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response {
|
||||
newResp := &Response{
|
||||
Code: sr.Code,
|
||||
Message: msg,
|
||||
}
|
||||
if len(data) == 1 {
|
||||
newResp.Data = data[0]
|
||||
}
|
||||
return newResp
|
||||
}
|
36
server/shopping-cart/shopping-cart.go
Normal file
36
server/shopping-cart/shopping-cart.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"fusenapi/utils/auth"
|
||||
|
||||
"fusenapi/server/shopping-cart/internal/config"
|
||||
"fusenapi/server/shopping-cart/internal/handler"
|
||||
"fusenapi/server/shopping-cart/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/conf"
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/shopping-cart.yaml", "the config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c config.Config
|
||||
conf.MustLoad(*configFile, &c)
|
||||
c.Timeout = int64(time.Second * 15)
|
||||
server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) {
|
||||
}))
|
||||
defer server.Stop()
|
||||
|
||||
ctx := svc.NewServiceContext(c)
|
||||
handler.RegisterHandlers(server, ctx)
|
||||
|
||||
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||
server.Start()
|
||||
}
|
|
@ -36,8 +36,8 @@ type File {
|
|||
|
||||
// 统一分页
|
||||
type Meta struct {
|
||||
TotalCount int64 `json:"totalCount"`
|
||||
PageCount int64 `json:"pageCount"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
PerPage int `json:"perPage"`
|
||||
TotalCount int64 `json:"total_count"`
|
||||
PageCount int64 `json:"page_count"`
|
||||
CurrentPage int `json:"current_page"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
91
server_api/shopping-cart.api
Normal file
91
server_api/shopping-cart.api
Normal file
|
@ -0,0 +1,91 @@
|
|||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "shopping-cart"// TODO: add title
|
||||
desc: "购物车服务"// TODO: add description
|
||||
author: ""
|
||||
email: ""
|
||||
)
|
||||
|
||||
import "basic.api"
|
||||
service shopping-cart {
|
||||
//加入购物车
|
||||
@handler AddToCartHandler
|
||||
post /api/shopping-cart/add_to_cart(AddToCartReq) returns (response);
|
||||
//删除购物车
|
||||
@handler DeleteCartHandler
|
||||
post /api/shopping-cart/delete_cart(DeleteCartReq) returns (response);
|
||||
//修改购物车购买数量
|
||||
@handler ModifyCartPurchaseQuantityHandler
|
||||
post /api/shopping-cart/modify_cart_purchase_quantity(ModifyCartPurchaseQuantityReq) returns (response);
|
||||
//获取购物车列表
|
||||
@handler GetCartsHandler
|
||||
get /api/shopping-cart/get_carts(GetCartsReq) returns (response);
|
||||
}
|
||||
|
||||
//加入购物车
|
||||
type AddToCartReq {
|
||||
ProductId int64 `json:"product_id"` //产品id
|
||||
TemplateId int64 `json:"template_id,optional"` //模板id(不可定制的不传)
|
||||
SizeId int64 `json:"size_id"` //尺寸id
|
||||
FittingId int64 `json:"fitting_id,optional"` //配件id(没有可以不传)
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量
|
||||
Logo string `json:"logo,optional"` //logo地址(没有可以不传)
|
||||
CombineImage string `json:"combine_image,optional"` //合图地址 (没有可以不传)
|
||||
RenderImage string `json:"render_image,optional"` //渲染结果图 (没有可以不传)
|
||||
DiyInfo DiyInfo `json:"diy_info,optional"` //用户diy数据(可选)
|
||||
}
|
||||
type DiyInfo {
|
||||
Phone string `json:"phone,optional"` //电话(可选)
|
||||
Address string `json:"address,optional"` //地址 (可选)
|
||||
Website string `json:"website,optional"` //网站 (可选)
|
||||
Qrcode string `json:"qrcode,optional"` //二维码 (可选)
|
||||
Slogan string `json:"slogan,optional"` //slogan (可选)
|
||||
}
|
||||
//删除购物车
|
||||
type DeleteCartReq {
|
||||
Id int64 `json:"id"` //购物车id
|
||||
}
|
||||
//修改购物车购买数量
|
||||
type ModifyCartPurchaseQuantityReq {
|
||||
Id int64 `json:"id"` //购物车id
|
||||
PurchaseQuantity int64 `json:"purchase_quantity"` //数量
|
||||
}
|
||||
//获取购物车列表
|
||||
type GetCartsReq {
|
||||
CurrentPage int `form:"current_page"` //当前页
|
||||
}
|
||||
type GetCartsRsp {
|
||||
Meta Meta `json:"meta"` //分页信息
|
||||
CartList []CartItem `json:"cart_list"`
|
||||
}
|
||||
type CartItem {
|
||||
ProductId int64 `json:"product_id"` //产品id
|
||||
SizeInfo SizeInfo `json:"size_info"` //尺寸信息
|
||||
FittingInfo FittingInfo `json:"fitting_info"` //配件信息
|
||||
ItemPrice string `json:"item_price"` //单价
|
||||
TotalPrice string `json:"totalPrice"` //单价X数量=总价
|
||||
DiyInformation DiyInformation `json:"diy_information"` //diy信息
|
||||
StepNum []int64 `json:"step_num"` //阶梯数量
|
||||
IsInvalid bool `json:"is_invalid"` //是否无效
|
||||
InvalidDescription string `json:"invalid_description"` //无效原因
|
||||
}
|
||||
type SizeInfo {
|
||||
SizeId int64 `json:"size_id"` //尺寸id
|
||||
Capacity string `json:"capacity"` //尺寸名称
|
||||
Title SizeTitle `json:"title"`
|
||||
}
|
||||
type FittingInfo {
|
||||
FittingId int64 `json:"fitting_id"` //配件id
|
||||
FittingName string `json:"fitting_name"` //配件名称
|
||||
}
|
||||
type SizeTitle {
|
||||
Cm string `json:"cm"`
|
||||
Inch string `json:"inch"`
|
||||
}
|
||||
type DiyInformation {
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"address"`
|
||||
Website string `json:"website"`
|
||||
Qrcode string `json:"qrcode"`
|
||||
}
|
39
utils/shopping_cart/shopping_cart_snapshot.go
Normal file
39
utils/shopping_cart/shopping_cart_snapshot.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
package shopping_cart
|
||||
|
||||
// 购物车快照数据结构
|
||||
type CartSnapshot struct {
|
||||
Logo string `json:"logo"` //logo地址
|
||||
CombineImage string `json:"combine_image"` //刀版图地址
|
||||
RenderImage string `json:"render_image"` //渲染结果图
|
||||
TemplateInfo TemplateInfo `json:"template_info"` //模板数据
|
||||
ModelInfo ModelInfo `json:"model_info"` //模型的数据
|
||||
FittingInfo FittingInfo `json:"fitting_info"` //配件信息
|
||||
SizeInfo SizeInfo `json:"size_info"` //尺寸基本信息
|
||||
ProductInfo ProductInfo `json:"product_info"` //产品基本信息(只记录不要使用)
|
||||
UserDiyInformation UserDiyInformation `json:"user_diy_information"` //用户diy数据
|
||||
}
|
||||
type ProductInfo struct {
|
||||
ProductName string `json:"product_name"`
|
||||
ProductSn string `json:"product_sn"`
|
||||
}
|
||||
type ModelInfo struct {
|
||||
ModelJson string `json:"model_json"` //模型设计json数据
|
||||
}
|
||||
type FittingInfo struct {
|
||||
FittingJson string `json:"fitting_json"` //配件设计json数据
|
||||
}
|
||||
type TemplateInfo struct {
|
||||
TemplateJson string `json:"template_json"` //模板设计json数据
|
||||
TemplateTag string `json:"template_tag"` //模板标签
|
||||
}
|
||||
type SizeInfo struct {
|
||||
Inch string `json:"inch"`
|
||||
Cm string `json:"cm"`
|
||||
}
|
||||
type UserDiyInformation struct {
|
||||
Phone string `json:"phone"` //电话
|
||||
Address string `json:"address"` //地址
|
||||
Website string `json:"website"` //网站
|
||||
Qrcode string `json:"qrcode"` //二维码
|
||||
Slogan string `json:"slogan"` //slogan
|
||||
}
|
95
utils/shopping_cart/verify_shopping_cart_channged.go
Normal file
95
utils/shopping_cart/verify_shopping_cart_channged.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
package shopping_cart
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fusenapi/model/gmodel"
|
||||
"fusenapi/utils/hash"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 校验购物车快照数据跟目前是否一致
|
||||
type VerifyShoppingCartSnapshotDataChangeReq struct {
|
||||
Carts []gmodel.FsShoppingCart
|
||||
MapSize map[int64]gmodel.FsProductSize
|
||||
MapModel map[int64]gmodel.FsProductModel3d //模型跟配件都在
|
||||
MapTemplate map[int64]gmodel.FsProductTemplateV2
|
||||
MapCartChange map[int64]string
|
||||
}
|
||||
|
||||
func VerifyShoppingCartSnapshotDataChange(req VerifyShoppingCartSnapshotDataChangeReq) error {
|
||||
for _, cartInfo := range req.Carts {
|
||||
var snapShotParseInfo CartSnapshot
|
||||
if err := json.Unmarshal([]byte(*cartInfo.Snapshot), &snapShotParseInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
//快照中模板设计json数据哈希值
|
||||
snapshotTemplateJsonHash := hash.JsonHashKey(snapShotParseInfo.TemplateInfo.TemplateJson)
|
||||
//快照中模型设计json数据哈希值
|
||||
snapshotModelJsonHash := hash.JsonHashKey(snapShotParseInfo.ModelInfo.ModelJson)
|
||||
//快照中配件设计json数据哈希值
|
||||
snapshotFittingJsonHash := hash.JsonHashKey(snapShotParseInfo.FittingInfo.FittingJson)
|
||||
descrptionBuilder := strings.Builder{}
|
||||
//有模板验证模板相关
|
||||
if *cartInfo.TemplateId > 0 {
|
||||
if curTemplateInfo, ok := req.MapTemplate[*cartInfo.TemplateId]; !ok {
|
||||
descrptionBuilder.WriteString("<p>the template is lose</p>")
|
||||
} else {
|
||||
//当前模板设计json数据哈希值
|
||||
curTemplateJsonHash := hash.JsonHashKey(*curTemplateInfo.TemplateInfo)
|
||||
//模板设计信息改变了
|
||||
if snapshotTemplateJsonHash != curTemplateJsonHash {
|
||||
descrptionBuilder.WriteString("<p>the template design info has changed</p>")
|
||||
}
|
||||
//模板标签改变了
|
||||
if snapShotParseInfo.TemplateInfo.TemplateTag != *curTemplateInfo.TemplateTag {
|
||||
descrptionBuilder.WriteString("<p>the template`s template tag has changed</p>")
|
||||
}
|
||||
}
|
||||
}
|
||||
//有模型验证模型相关
|
||||
if *cartInfo.ModelId > 0 {
|
||||
if curModelInfo, ok := req.MapModel[*cartInfo.ModelId]; !ok { //不存在
|
||||
descrptionBuilder.WriteString("<p>the model is lose</p>")
|
||||
} else {
|
||||
//当前模型设计json数据哈希值
|
||||
curModelJsonHash := hash.JsonHashKey(*curModelInfo.ModelInfo)
|
||||
if snapshotModelJsonHash != curModelJsonHash {
|
||||
descrptionBuilder.WriteString("<p>the model design info has changed</p>")
|
||||
}
|
||||
}
|
||||
}
|
||||
//有配件验证配件相关
|
||||
if *cartInfo.FittingId > 0 {
|
||||
if curFittingInfo, ok := req.MapModel[*cartInfo.FittingId]; !ok { //不存在
|
||||
descrptionBuilder.WriteString("<p>the fitting is lose</p>")
|
||||
} else {
|
||||
//当前配件设计json数据哈希值
|
||||
curFittingJsonHash := hash.JsonHashKey(*curFittingInfo.ModelInfo)
|
||||
if snapshotFittingJsonHash != curFittingJsonHash {
|
||||
descrptionBuilder.WriteString("<p>the fitting design info has changed</p>")
|
||||
}
|
||||
}
|
||||
}
|
||||
//验证尺寸相关
|
||||
if *cartInfo.SizeId > 0 {
|
||||
curSize, ok := req.MapSize[*cartInfo.SizeId]
|
||||
if !ok {
|
||||
descrptionBuilder.WriteString("<p>the size is lose</p>")
|
||||
} else {
|
||||
var curSizeTitle SizeInfo
|
||||
if err := json.Unmarshal([]byte(*curSize.Title), &curSizeTitle); err != nil {
|
||||
return err
|
||||
}
|
||||
if snapShotParseInfo.SizeInfo.Inch != curSizeTitle.Inch || snapShotParseInfo.SizeInfo.Cm != curSizeTitle.Cm {
|
||||
descrptionBuilder.WriteString("<p>the size design info has changed</p>")
|
||||
}
|
||||
}
|
||||
}
|
||||
//收集错误
|
||||
descrption := descrptionBuilder.String()
|
||||
if descrption != "" {
|
||||
req.MapCartChange[cartInfo.Id] = descrption
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user