删除无用的服务

This commit is contained in:
laodaming 2023-09-12 11:57:58 +08:00
parent 7c3bc74186
commit 0a7e56f726
62 changed files with 0 additions and 4483 deletions

View File

@ -1,6 +0,0 @@
FROM alpine
WORKDIR /www/fusenapi/
COPY ./bin/api-inventory-srv /www/fusenapi/
COPY ./etc /www/fusenapi/etc
CMD ["/www/fusenapi/api-inventory-srv"]

View File

@ -1,12 +0,0 @@
Name: inventory
Host: localhost
Port: 9905
ReplicaId: 35
Timeout: 15000 #服务超时时间
SourceMysql: "fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen"
Log:
Stat: false
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000

View File

@ -1,14 +0,0 @@
package config
import (
"fusenapi/server/inventory/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
ReplicaId uint64
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/inventory/internal/logic"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
)
func GetCloudListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetCloudListReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetCloudListLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetCloudList(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/inventory/internal/logic"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
)
func GetPickupListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetPickupListReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetPickupListLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetPickupList(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,37 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/inventory/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/inventory/take",
Handler: TakeHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/inventory/list",
Handler: GetCloudListHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/inventory/supplement",
Handler: SupplementHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/inventory/pick-up-list",
Handler: GetPickupListHandler(serverCtx),
},
},
)
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/inventory/internal/logic"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
)
func SupplementHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.SupplementReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewSupplementLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.Supplement(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/inventory/internal/logic"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
)
func TakeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.TakeReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewTakeLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.Take(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,268 +0,0 @@
package logic
import (
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/image"
"fusenapi/utils/step_price"
"math"
"strings"
"context"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetCloudListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetCloudListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCloudListLogic {
return &GetCloudListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetCloudListLogic) GetCloudList(req *types.GetCloudListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first")
}
if req.Page <= 0 {
req.Page = constants.DEFAULT_PAGE
}
if req.PageSize <= 0 || req.PageSize > constants.MAX_PAGE_SIZE {
req.PageSize = constants.DEFAULT_PAGE_SIZE
}
sizeFlag := false
if req.Size >= 200 {
sizeFlag = true
req.Size = int64(image.GetCurrentSize(uint32(req.Size)))
}
//获取个人云仓列表
getStockListStatus := int64(1)
stockList, total, err := l.svcCtx.AllModels.FsUserStock.GetStockList(l.ctx, gmodel.GetStockListReq{
UserId: userinfo.UserId,
Page: int(req.Page),
Limit: int(req.PageSize),
Status: &getStockListStatus,
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user stock list")
}
if len(stockList) == 0 {
return resp.SetStatusWithMessage(basic.CodeOK, "success")
}
designIds := make([]int64, 0, len(stockList))
for _, v := range stockList {
designIds = append(designIds, *v.DesignId)
}
//获取设计数据
productDesignList, err := l.svcCtx.AllModels.FsProductDesign.GetAllByIdsWithoutStatus(l.ctx, designIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product design list")
}
//尺寸ids
sizeIds := make([]int64, 0, len(productDesignList))
//产品ids
productIds := make([]int64, 0, len(productDesignList))
//模板ids
templateIds := make([]int64, 0, len(productDesignList))
//配件ids
optionalIds := make([]int64, 0, len(productDesignList))
mapProductDesign := make(map[int64]gmodel.FsProductDesign)
for _, v := range productDesignList {
sizeIds = append(sizeIds, *v.SizeId)
productIds = append(productIds, *v.ProductId)
templateIds = append(templateIds, *v.TemplateId)
optionalIds = append(optionalIds, *v.OptionalId)
mapProductDesign[v.Id] = v
}
//获取尺寸信息
sizeList, err := l.svcCtx.AllModels.FsProductSize.GetAllByIdsWithoutStatus(l.ctx, sizeIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product size list")
}
mapSize := make(map[int64]gmodel.FsProductSize)
for _, v := range sizeList {
mapSize[v.Id] = v
}
//获取产品信息
productList, err := l.svcCtx.AllModels.FsProduct.GetProductListByIdsWithoutStatus(l.ctx, productIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product list")
}
mapProduct := make(map[int64]gmodel.FsProduct)
for _, v := range productList {
mapProduct[v.Id] = v
}
//获取模板信息
productTemplateList, err := l.svcCtx.AllModels.FsProductTemplateV2.FindAllByIdsWithoutStatus(l.ctx, templateIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product template list")
}
mapTemplate := make(map[int64]gmodel.FsProductTemplateV2)
for _, v := range productTemplateList {
mapTemplate[v.Id] = v
}
//获取配件列表
productModel3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsWithoutStatus(l.ctx, optionalIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product 3d model list")
}
mapProductModel := make(map[int64]gmodel.FsProductModel3d)
for _, v := range productModel3dList {
mapProductModel[v.Id] = v
}
//根据产品ids获取产品价格
priceList, err := l.svcCtx.AllModels.FsProductPrice.GetPriceListByProductIds(l.ctx, productIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product price list")
}
//根据产品id,材质,尺寸存储价格
mapProductMaterialSizePrice := make(map[string][]types.PriceItem)
for _, v := range priceList {
if *v.StepNum == "" || *v.StepPrice == "" {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "price data`s step num or step price is empty")
}
stepNum, err := format.StrSlicToIntSlice(strings.Split(*v.StepNum, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "parse step num err")
}
stepPrice, err := format.StrSlicToIntSlice(strings.Split(*v.StepPrice, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "parse step price err")
}
lenStepPrice := len(stepPrice)
//不确定长度给20
for *v.MinBuyNum < int64(stepPrice[lenStepPrice-1]+5) {
mapKey := l.getMapProductMaterialSizePriceKey(*v.ProductId, *v.MaterialId, *v.SizeId)
mapProductMaterialSizePrice[mapKey] = append(mapProductMaterialSizePrice[mapKey], types.PriceItem{
Num: *v.MinBuyNum,
TotalNum: *v.MinBuyNum * (*v.EachBoxNum),
Price: step_price.GetCentStepPrice(int(*v.MinBuyNum), stepNum, stepPrice),
})
*v.MinBuyNum++
}
}
warehouseBoxes := int64(0)
transitBoxes := int64(0)
listDataRsp := make([]types.ListDataItem, 0, len(stockList))
for _, v := range stockList {
dataItem := types.ListDataItem{
Id: v.Id,
Production: *v.Production,
EachBoxNum: *v.EachBoxNum,
Stick: *v.Stick,
Type: 1,
TakeNum: 1, // 步数
}
//设计详情
designInfo, designOk := mapProductDesign[*v.DesignId]
sizeId := int64(0)
optionalId := int64(0)
if designOk {
mapKey := l.getMapProductMaterialSizePriceKey(*v.ProductId, *designInfo.MaterialId, *designInfo.SizeId)
dataItem.DesignSn = *designInfo.Sn
dataItem.Cover = *designInfo.Cover
sizeId = *designInfo.SizeId
optionalId = *designInfo.OptionalId
dataItem.PriceList = mapProductMaterialSizePrice[mapKey]
}
//模型信息
productModel3dInfo, model3dOk := mapProductModel[optionalId]
if model3dOk {
dataItem.Fitting = *productModel3dInfo.Title
//配件下架
if *productModel3dInfo.Status == 0 {
dataItem.IsStop = 3
}
}
//模板信息
templateInfo, templateOk := mapTemplate[*designInfo.TemplateId]
if templateOk {
//模板下架
if *templateInfo.IsDel == 1 || *templateInfo.Status == 0 {
dataItem.IsStop = 1
}
}
//尺寸信息
sizeInfo, sizeOk := mapSize[sizeId]
if sizeOk {
dataItem.Size = *sizeInfo.Capacity
//尺寸下架
if *sizeInfo.Status == 0 {
dataItem.IsStop = 1
}
}
//产品信息
productInfo, productOk := mapProduct[*v.ProductId]
if productOk {
dataItem.Sn = *productInfo.Sn
dataItem.Name = *productInfo.Title
if *productInfo.IsShelf == 0 || *productInfo.IsDel == 1 {
dataItem.IsStop = 2
}
}
if sizeFlag {
coverArr := strings.Split(*designInfo.Cover, ".")
if len(coverArr) < 2 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "cover split slice item count is less than 2")
}
dataItem.Cover = fmt.Sprintf("%s_%d.%s", coverArr[0], req.Size, coverArr[1])
}
//生产中的箱数
if *v.EachBoxNum > 0 {
dataItem.ProductionBox = *v.Production / *v.EachBoxNum
dataItem.StickBox = *v.Stick / *v.EachBoxNum
}
//判断提示类型1 2告急 3没有了
if *v.Stick <= 0 && *v.Production <= 0 {
dataItem.Type = 3
}
if (*v.Stick+*v.Production) / *v.EachBoxNum <= 3 {
dataItem.Type = 2
}
listDataRsp = append(listDataRsp, dataItem)
//累加在库数量和运输数量
if *v.EachBoxNum != 0 {
warehouseBoxes += *v.Stick / *v.EachBoxNum
transitBoxes += *v.TransNum / *v.EachBoxNum
}
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetCloudListRsp{
WarehouseBoxes: warehouseBoxes,
TransitBoxes: transitBoxes,
MinTakeNum: 3,
ListData: listDataRsp,
Meta: types.Meta{
TotalCount: total,
PageCount: int64(math.Ceil(float64(total) / float64(req.PageSize))),
CurrentPage: req.Page,
PerPage: req.PageSize,
},
})
}
func (l *GetCloudListLogic) getMapProductMaterialSizePriceKey(productId int64, materialId int64, sizeId int64) string {
return fmt.Sprintf("%d-%d-%d", productId, materialId, sizeId)
}

View File

@ -1,279 +0,0 @@
package logic
import (
"context"
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"gorm.io/gorm"
"math"
"strconv"
"time"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetPickupListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetPickupListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPickupListLogic {
return &GetPickupListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetPickupListLogic) GetPickupList(req *types.GetPickupListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first")
}
if req.Page <= 0 {
req.Page = constants.DEFAULT_PAGE
}
if req.PageSize <= 0 || req.PageSize > constants.MAX_PAGE_SIZE {
req.PageSize = constants.DEFAULT_PAGE_SIZE
}
//获取列表
pickListReq := gmodel.GetPickupListByParamReq{
UserId: &userinfo.UserId,
Page: req.Page,
Limit: req.PageSize,
}
//状态筛选
if req.Status != -1 {
pickListReq.Status = &req.Status
}
//空的就返回
pickupList, total, err := l.svcCtx.AllModels.FsCloudPickUp.GetPickupListByParam(l.ctx, pickListReq)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get pickup list")
}
pickupIds := make([]int64, 0, len(pickupList))
for _, v := range pickupList {
pickupIds = append(pickupIds, v.Id)
}
//获取详情数据
pickupDetailList, err := l.svcCtx.AllModels.FsCloudPickUpDetail.GetAllByIds(l.ctx, pickupIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get pickup detail list")
}
stockIds := make([]int64, 0, len(pickupList))
for _, v := range pickupDetailList {
stockIds = append(stockIds, *v.StockId)
}
stockList, _, err := l.svcCtx.AllModels.FsUserStock.GetStockList(l.ctx, gmodel.GetStockListReq{
UserId: userinfo.UserId,
Ids: stockIds,
Page: 1,
Limit: len(stockIds),
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get stock list")
}
designIds := make([]int64, 0, len(stockList))
mapStock := make(map[int64]int)
for k, v := range stockList {
designIds = append(designIds, *v.DesignId)
mapStock[v.Id] = k
}
//获取设计列表
designList, err := l.svcCtx.AllModels.FsProductDesign.GetAllByIdsWithoutStatus(l.ctx, designIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get design list")
}
productIds := make([]int64, 0, len(designList))
sizeIds := make([]int64, 0, len(designList))
optionalIds := make([]int64, 0, len(designList))
mapDesign := make(map[int64]int)
for k, v := range designList {
productIds = append(productIds, *v.ProductId)
sizeIds = append(sizeIds, *v.SizeId)
optionalIds = append(optionalIds, *v.OptionalId)
mapDesign[v.Id] = k
}
//获取产品信息
productList, err := l.svcCtx.AllModels.FsProduct.GetProductListByIdsWithoutStatus(l.ctx, productIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product list ")
}
mapProduct := make(map[int64]int)
for k, v := range productList {
mapProduct[v.Id] = k
}
//获取尺寸信息
sizeList, err := l.svcCtx.AllModels.FsProductSize.GetAllByIdsWithoutStatus(l.ctx, sizeIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product size list ")
}
mapSize := make(map[int64]int)
for k, v := range sizeList {
mapSize[v.Id] = k
}
//获取配件信息
model3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsWithoutStatus(l.ctx, optionalIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product 3d model list ")
}
mapModel3d := make(map[int64]int)
for k, v := range model3dList {
mapModel3d[v.Id] = k
}
//获取时间配置
var (
factoryDeliverDay int64 = 2
deliverUpsDay int64 = 35
upsTransDay int64 = 5
)
if timeSetting, err := l.svcCtx.AllModels.FsWebSet.FindValueByKey(l.ctx, "time_info"); err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get web setting:time_info")
}
} else { //存在记录
if timeSetting.Value != nil {
var timeInfo map[string]string
if err = json.Unmarshal([]byte(*timeSetting.Value), &timeInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse time_info ")
}
factoryDeliverDay, _ = strconv.ParseInt(timeInfo["factory_deliver_day"], 10, 64)
deliverUpsDay, _ = strconv.ParseInt(timeInfo["deliver_ups_day"], 10, 64)
upsTransDay, _ = strconv.ParseInt(timeInfo["ups_trans_day"], 10, 64)
}
}
//处理提货单列表详情数据
type mapPickupProductItem struct {
List []types.Product
PickNum int64
PickBoxes int64
}
mapPickupProduct := make(map[int64]*mapPickupProductItem)
for _, v := range pickupDetailList {
stockIndex, ok := mapStock[*v.StockId]
if !ok {
continue
}
designIndex, ok := mapDesign[*stockList[stockIndex].DesignId]
if !ok {
continue
}
designInfo := designList[designIndex]
productIndex, ok := mapProduct[*designInfo.ProductId]
if !ok {
continue
}
productInfo := productList[productIndex]
sizeIndex, ok := mapSize[*designInfo.SizeId]
if !ok {
continue
}
sizeInfo := sizeList[sizeIndex]
fitting := ""
if model3dIndex, ok := mapModel3d[*designInfo.OptionalId]; ok {
fitting = *model3dList[model3dIndex].Title
}
productItem := types.Product{
Id: v.Id,
PickId: *v.PickId,
StockId: *v.StockId,
Num: *v.Num,
Boxes: *v.Boxes,
Ctime: *v.Ctime,
ProductName: *productInfo.Title,
Pcs: *v.Num,
PcsBox: *v.Boxes,
Cover: *designInfo.Cover,
Size: *sizeInfo.Capacity,
Fitting: fitting,
}
//已经存在
if _, ok := mapPickupProduct[*v.PickId]; ok {
mapPickupProduct[*v.PickId].List = append(mapPickupProduct[*v.PickId].List, productItem)
mapPickupProduct[*v.PickId].PickNum += *v.Num
mapPickupProduct[*v.PickId].PickBoxes += *v.Boxes
} else { //不存在
mapPickupProduct[*v.PickId] = &mapPickupProductItem{
List: []types.Product{productItem},
PickNum: *v.Num,
PickBoxes: *v.Boxes,
}
}
}
//处理提货单数据
listRsp := make([]types.PickupItem, 0, len(pickupList))
for _, v := range pickupList {
//地址处理
address := ""
if *v.AddressInfo != "" {
var addressInfo map[string]interface{}
if err = json.Unmarshal([]byte(*v.AddressInfo), &addressInfo); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("failed to parse address,pickup_id = %d", v.Id))
}
address += addressInfo["street"].(string) + " " + addressInfo["suite"].(string) + ","
address += addressInfo["city"].(string) + "," + addressInfo["state"].(string) + " " + addressInfo["zip_code"].(string)
}
if *v.Status < int64(constants.STATUS_SHIPPING) {
*v.ShippingTime = *v.Ctime + factoryDeliverDay*24*3600
}
if *v.Status < int64(constants.STATUS_PICK_UP) {
*v.UpsTime = *v.ShippingTime + deliverUpsDay*24*3600
}
if *v.Status < int64(constants.STATUS_ARRIVAL) {
*v.ArrivalTime = *v.UpsTime + upsTransDay*24*3600
}
d := types.PickupItem{
Id: v.Id,
UserId: *v.UserId,
TrackNum: *v.TrackNum,
Ctime: time.Unix(*v.Ctime, 0).Format("2006-01-02 15:04:05"),
Status: *v.Status,
UpsSn: *v.UpsSn,
Address: address,
ProductList: nil,
Pcs: 0,
PcsBox: 0,
LogisticsStatus: *v.Status,
StatusTimes: []types.StatusTimesItem{
{Key: int64(constants.STATUS_ORDERD), Time: ""},
{Key: int64(constants.STATUS_SHIPPING), Time: time.Unix(*v.ShippingTime, 0).Format("2006-01-02 15:04:05")},
{Key: int64(constants.STATUS_PICK_UP), Time: time.Unix(*v.UpsTime, 0).Format("2006-01-02 15:04:05")},
{Key: int64(constants.STATUS_ARRIVAL), Time: time.Unix(*v.ArrivalTime, 0).Format("2006-01-02 15:04:05")},
},
}
if pickupProduct, ok := mapPickupProduct[v.Id]; ok {
d.ProductList = pickupProduct.List
d.Pcs = pickupProduct.PickNum
d.PcsBox = pickupProduct.PickBoxes
}
listRsp = append(listRsp, d)
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetPickupListRsp{
PickupList: listRsp,
Meta: types.Meta{
TotalCount: total,
PageCount: int64(math.Ceil(float64(total) / float64(req.PageSize))),
CurrentPage: req.Page,
PerPage: req.PageSize,
},
})
}

View File

@ -1,186 +0,0 @@
package logic
import (
"errors"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/id_generator"
"fusenapi/utils/step_price"
"math"
"strings"
"time"
"gorm.io/gorm"
"context"
"fusenapi/server/inventory/internal/svc"
"fusenapi/server/inventory/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SupplementLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSupplementLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SupplementLogic {
return &SupplementLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SupplementLogic) Supplement(req *types.SupplementReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first")
}
if req.Id <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param id must greater than 0")
}
if req.Num <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param num must greater than 0")
}
//获取云仓数据
stockInfo, err := l.svcCtx.AllModels.FsUserStock.FindOne(l.ctx, req.Id, userinfo.UserId, true)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "your stock info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get stock info")
}
//获取订单详细模板数据
orderDetailTemplateInfo, err := l.svcCtx.AllModels.FsOrderDetailTemplate.FindOneBySn(l.ctx, *stockInfo.OrderDetailTemplateSn)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order detail template info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get order detail template info")
}
//获取订单详细数据
orderDetailInfo, err := l.svcCtx.AllModels.FsOrderDetail.FindOneByOrderDetailTemplateId(l.ctx, orderDetailTemplateInfo.Id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order detail info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get order detail info")
}
//产品价格
productPriceByParamsReq := gmodel.FindOneProductPriceByParamsReq{
ProductId: orderDetailTemplateInfo.ProductId,
}
productPriceInfo, err := l.svcCtx.AllModels.FsProductPrice.FindOneProductPriceByParams(l.ctx, productPriceByParamsReq)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "product price info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product price info")
}
//获取阶梯价格和阶梯数量
stepNum, err := format.StrSlicToIntSlice(strings.Split(*productPriceInfo.StepNum, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "invalid step num format: "+*productPriceInfo.StepNum)
}
stepPrice, err := format.StrSlicToIntSlice(strings.Split(*productPriceInfo.StepPrice, ","))
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "invalid step price format: "+*productPriceInfo.StepPrice)
}
//附件价格信息
optionalPrice := int64(0)
if *orderDetailInfo.OptionPrice > 0 {
optionalPrice = *orderDetailInfo.OptionPrice
}
//获取总价
minByNum := math.Ceil(float64(req.Num) / float64(*productPriceInfo.EachBoxNum))
amount := step_price.GetCentStepPrice(int(minByNum), stepNum, stepPrice) + optionalPrice
totalAmount := amount * req.Num
newOrderSn := id_generator.GenSnNum()
now := time.Now().UTC().Unix()
deliveryMethod := int64(constants.DELIVERY_METHOD_CLOUD)
isSup := int64(1)
//生成雪花id
newOrderDetailTemplateSn, err := id_generator.GenSnowFlakeId()
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "gen order detail template sn err")
}
newOrderDetailSn, err := id_generator.GenSnowFlakeId()
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "gen order detail sn err")
}
//事务处理数据
err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error {
orderModel := gmodel.NewFsOrderModel(tx)
orderDetailModel := gmodel.NewFsOrderDetailModel(tx)
orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(tx)
//订单创建数据
orderAddData := gmodel.FsOrder{
Sn: &newOrderSn,
UserId: &userinfo.UserId,
TotalAmount: &totalAmount,
Ctime: &now,
Utime: &now,
DeliveryMethod: &deliveryMethod,
IsSup: &isSup,
}
if err = orderModel.Create(l.ctx, &orderAddData); err != nil {
return err
}
//添加订单详情模板数据
orderDetailTemplateAddData := gmodel.FsOrderDetailTemplate{
Sn: &newOrderDetailTemplateSn,
ProductId: orderDetailTemplateInfo.ProductId,
ModelId: orderDetailTemplateInfo.ModelId,
TemplateId: orderDetailTemplateInfo.TemplateId,
MaterialId: orderDetailTemplateInfo.MaterialId,
SizeId: orderDetailTemplateInfo.SizeId,
EachBoxNum: orderDetailTemplateInfo.EachBoxNum,
EachBoxWeight: orderDetailTemplateInfo.EachBoxWeight,
DesignId: orderDetailTemplateInfo.DesignId,
Ctime: &now,
}
if err = orderDetailTemplateModel.Create(l.ctx, &orderDetailTemplateAddData); err != nil {
return err
}
//添加订单详细数据
factoryId := int64(1)
isCloud := int64(1)
orderDetailAddData := gmodel.FsOrderDetail{
Sn: &newOrderDetailSn,
OrderId: &orderAddData.Id,
UserId: &userinfo.UserId,
FactoryId: &factoryId,
OrderDetailTemplateId: &orderDetailTemplateAddData.Id,
ProductId: orderDetailTemplateInfo.ProductId,
BuyNum: &req.Num,
Amount: &amount,
Cover: orderDetailInfo.Cover,
Ctime: &now,
OptionalId: orderDetailInfo.OptionalId,
OptionalTitle: orderDetailInfo.OptionalTitle,
OptionPrice: orderDetailInfo.OptionPrice,
IsCloud: &isCloud,
}
return orderDetailModel.Create(l.ctx, &orderDetailAddData)
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to supplement your stock")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.SupplementRsp{
Sn: newOrderSn,
})
}

View File

@ -1,131 +0,0 @@
package logic
import (
"context"
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/server/inventory/internal/types"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/id_generator"
"time"
"gorm.io/gorm"
"fusenapi/server/inventory/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type TakeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewTakeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TakeLogic {
return &TakeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *TakeLogic) Take(req *types.TakeReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "please login first")
}
if len(req.Form) == 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param err :form can`t be empty array")
}
if req.AddressId <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param err :address_id is required")
}
//获取地址信息
addressInfo, err := l.svcCtx.AllModels.FsAddress.GetOne(l.ctx, req.AddressId, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "your address is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get address info")
}
stockIds := make([]int64, 0, len(req.Form))
for _, v := range req.Form {
stockIds = append(stockIds, v.Id)
}
//提货单总单
addressInfoBytes, _ := json.Marshal(addressInfo)
addressInfoJson := string(addressInfoBytes)
trackNum := id_generator.GenSnNum()
status := int64(constants.STATUS_ORDERD)
now := time.Now().UTC().Unix()
pickUpData := gmodel.FsCloudPickUp{
UserId: &userinfo.UserId,
TrackNum: &trackNum,
AddressId: &req.AddressId,
AddressInfo: &addressInfoJson,
Status: &status,
Ctime: &now,
}
//箱数验证
boxes := int64(0)
//需要更新的库存信息
stockUpdateList := make([]gmodel.FsUserStock, 0, len(req.Form))
//需要新增的提货详情单
pickUpDetailAddList := make([]gmodel.FsCloudPickUpDetail, 0, len(req.Form))
for k, val := range req.Form {
formItem := val
//验证提取数量
if formItem.Num <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, fmt.Sprintf("row %d inventory data`s take num can`be less than 0", k+1))
}
//获取库存信息(枷锁)
stockInfo, err := l.svcCtx.AllModels.FsUserStock.FindOne(l.ctx, formItem.Id, userinfo.UserId, true)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, fmt.Sprintf("row %d inventory data is not availabled for you", k+1))
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, fmt.Sprintf("failed to get row %d`s stock info ", k+1))
}
//校验取货数量
if *stockInfo.Stick < formItem.Num {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, fmt.Sprintf("row %d inventory data is shortage", k+1))
}
if *stockInfo.EachBoxNum <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, fmt.Sprintf("row %d inventory data each box num can`t be less than 0", k+1))
}
boxes += (formItem.Num / *stockInfo.EachBoxNum)
//库存变更
newStick := *stockInfo.Stick - formItem.Num
newTransNum := *stockInfo.TransNum + formItem.Num
stockUpdateList = append(stockUpdateList, gmodel.FsUserStock{
Id: stockInfo.Id,
Stick: &newStick,
TransNum: &newTransNum,
})
//提货详情单
detailBoxes := formItem.Num / *stockInfo.EachBoxNum
pickUpDetailAddList = append(pickUpDetailAddList, gmodel.FsCloudPickUpDetail{
PickId: nil, //到model里方法会给他赋值pick总单id
StockId: &formItem.Id,
Num: &formItem.Num,
Boxes: &detailBoxes,
Ctime: &now,
})
}
if boxes < 3 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "Take out more than three boxes")
}
//事务处理数据
err = l.svcCtx.AllModels.FsCloudPickUp.SavePickUpWithTransaction(l.ctx, &pickUpData, stockUpdateList, pickUpDetailAddList)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to take your goods")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success")
}

View File

@ -1,66 +0,0 @@
package svc
import (
"errors"
"fmt"
"fusenapi/server/inventory/internal/config"
"fusenapi/shared"
"net/http"
"fusenapi/initalize"
"fusenapi/model/gmodel"
"github.com/golang-jwt/jwt"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
SharedState *shared.SharedState
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
// StateServer := shared.StartNode(c.ReplicaId, autoconfig.AutoGetAllServerConfig(), conn)
return &ServiceContext{
Config: c,
MysqlConn: conn,
SharedState: nil,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
}
}
func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if AuthKey == "" {
return nil, nil
}
AuthKey = AuthKey[7:]
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// 返回用于验证签名的密钥
return []byte(svcCtx.Config.Auth.AccessSecret), nil
})
if err != nil {
return nil, errors.New(fmt.Sprint("Error parsing token:", err))
}
// 验证成功返回
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New(fmt.Sprint("Invalid token", err))
}

View File

@ -1,180 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
type TakeReq struct {
Form []TakeForm `json:"form"`
AddressId int64 `json:"address_id"`
}
type TakeForm struct {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
type GetCloudListReq struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Size int64 `json:"size"`
}
type GetCloudListRsp struct {
WarehouseBoxes int64 `json:"warehouse_boxes"`
TransitBoxes int64 `json:"transit_boxes"`
MinTakeNum int64 `json:"minTakeNum"`
ListData []ListDataItem `json:"listData"`
Meta Meta `json:"_meta"`
}
type ListDataItem struct {
Id int64 `json:"id"`
Sn string `json:"sn"`
Cover string `json:"cover"`
Name string `json:"name"`
DesignSn string `json:"design_sn"`
Fitting string `json:"fitting"`
Production int64 `json:"production"`
ProductionBox int64 `json:"production_box"`
EachBoxNum int64 `json:"each_box_num"`
Stick int64 `json:"stick"`
StickBox int64 `json:"stick_box"`
Type int64 `json:"type"`
TakeNum int64 `json:"takeNum"`
Size string `json:"size"`
IsStop int64 `json:"is_stop"`
PriceList []PriceItem `json:"price"`
}
type PriceItem struct {
Num int64 `json:"num"`
TotalNum int64 `json:"total_num"`
Price int64 `json:"price"`
}
type SupplementReq struct {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
type SupplementRsp struct {
Sn string `json:"sn"`
}
type GetPickupListReq struct {
Status int64 `form:"status,options=-1|1|2|3|4"`
Page int `form:"page"`
PageSize int `form:"page_size"`
Size int `form:"size"`
}
type GetPickupListRsp struct {
PickupList []PickupItem `json:"items"`
Meta Meta `json:"_meta"`
}
type PickupItem struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
TrackNum string `json:"track_num"`
Ctime string `json:"ctime"`
Status int64 `json:"status"`
UpsSn string `json:"ups_sn"`
Address string `json:"address"`
ProductList []Product `json:"productList"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
LogisticsStatus int64 `json:"logistics_status"`
StatusTimes []StatusTimesItem `json:"status_times"`
}
type Product struct {
Id int64 `json:"id"`
PickId int64 `json:"pick_id"`
StockId int64 `json:"stock_id"`
Num int64 `json:"num"`
Boxes int64 `json:"boxes"`
Ctime int64 `json:"ctime"`
ProductName string `json:"product_name"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
Cover string `json:"cover"`
Size string `json:"size"`
Fitting string `json:"fitting"`
}
type StatusTimesItem struct {
Key int64 `json:"key"`
Time string `json:"time"`
}
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:"totalCount"`
PageCount int64 `json:"pageCount"`
CurrentPage int `json:"currentPage"`
PerPage int `json:"perPage"`
}
// 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
}

View File

@ -1,35 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"fusenapi/server/inventory/internal/config"
"fusenapi/server/inventory/internal/handler"
"fusenapi/server/inventory/internal/svc"
"fusenapi/utils/auth"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/inventory.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
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()
}

View File

@ -1,12 +0,0 @@
package main
import (
"testing"
)
// var configFile = flag.String("f", "etc/home-user-auth.yaml", "the config file")
func TestMain(t *testing.T) {
// log.Println(model.RawFieldNames[FsCanteenType]())
main()
}

View File

@ -1,6 +0,0 @@
FROM alpine
WORKDIR /www/fusenapi/
COPY ./bin/api-order-srv /www/fusenapi/
COPY ./etc /www/fusenapi/etc
CMD ["/www/fusenapi/api-order-srv"]

View File

@ -1,12 +0,0 @@
Name: orders
Host: localhost
Port: 9907
ReplicaId: 45
Timeout: 15000 #服务超时时间
SourceMysql: "fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen"
Log:
Stat: false
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000

View File

@ -1,14 +0,0 @@
package config
import (
"fusenapi/server/orders/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
ReplicaId uint64
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/orders/internal/logic"
"fusenapi/server/orders/internal/svc"
"fusenapi/server/orders/internal/types"
)
func GetOrderDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetOrderDetailReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetOrderDetailLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetOrderDetail(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/orders/internal/logic"
"fusenapi/server/orders/internal/svc"
"fusenapi/server/orders/internal/types"
)
func GetOrderInvoiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetOrderInvoiceReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetOrderInvoiceLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetOrderInvoice(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,27 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/orders/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/api/order/invoice",
Handler: GetOrderInvoiceHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/order/detail",
Handler: GetOrderDetailHandler(serverCtx),
},
},
)
}

View File

@ -1,221 +0,0 @@
package logic
import (
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/order"
"gorm.io/gorm"
"strings"
"time"
"context"
"fusenapi/server/orders/internal/svc"
"fusenapi/server/orders/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetOrderDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderDetailLogic {
return &GetOrderDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetOrderDetailLogic) GetOrderDetail(req *types.GetOrderDetailReq, userinfo *auth.UserInfo) (resp *basic.Response) {
//查询订单信息
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the order is not exists")
}
logx.Error(err)
return resp.SetStatus(basic.CodeServiceErr, "failed to get order info")
}
//获取订单详情
orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
orderDetails, err := orderDetailModel.GetOrderDetailsByOrderId(l.ctx, orderInfo.Id)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details")
}
if len(orderDetails) == 0 {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order details is empty")
}
optionalIds := make([]int64, 0, len(orderDetails))
productIds := make([]int64, 0, len(orderDetails))
orderDetailTemplateIds := make([]int64, 0, len(orderDetails))
for _, v := range orderDetails {
optionalIds = append(optionalIds, *v.OptionalId)
productIds = append(productIds, *v.ProductId)
orderDetailTemplateIds = append(orderDetailTemplateIds, *v.OrderDetailTemplateId)
}
//获取配件列表
productModel3dModel := gmodel.NewFsProductModel3dModel(l.svcCtx.MysqlConn)
productModel3dList, err := productModel3dModel.GetAllByIds(l.ctx, optionalIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product 3d models")
}
mapModel3d := make(map[int64]int)
for k, v := range productModel3dList {
mapModel3d[v.Id] = k
}
//获取产品列表
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
productList, err := productModel.GetProductListByIds(l.ctx, productIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order product list")
}
mapProduct := make(map[int64]int)
for k, v := range productList {
mapProduct[v.Id] = k
}
//获取模板列表
orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(l.svcCtx.MysqlConn)
detailTemplateList, err := orderDetailTemplateModel.GetListByIds(l.ctx, orderDetailTemplateIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order detail template list")
}
sizeIds := make([]int64, 0, len(detailTemplateList))
mapDetailTemplate := make(map[int64]int)
for k, v := range detailTemplateList {
sizeIds = append(sizeIds, *v.SizeId)
mapDetailTemplate[v.Id] = k
}
//获取尺寸信息
productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn)
productSizeList, err := productSizeModel.GetAllByIds(l.ctx, sizeIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product size list")
}
mapProductSize := make(map[int64]int)
for k, v := range productSizeList {
mapProductSize[v.Id] = k
}
//获取支付信息
payModel := gmodel.NewFsPayModel(l.svcCtx.MysqlConn)
payList, err := payModel.GetOrderPayList(l.ctx, *orderInfo.Sn, 1, 0)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get pay records")
}
mapPay := make(map[int64]int) //pay_stat作为索引
for k, v := range payList {
mapPay[*v.PayStage] = k
}
//处理订单状态
orderStatus := order.GetOrderStatus(constants.Order(*orderInfo.Status), constants.DeliveryMethod(*orderInfo.DeliveryMethod))
//组装
productListRsp := make([]*types.Product, 0, len(orderDetails))
for _, v := range orderDetails {
cover := *v.Cover
if req.Size >= 200 {
coverSlice := strings.Split(".", *v.Cover)
if len(coverSlice) >= 2 {
cover = fmt.Sprintf("%s_%d.%s", coverSlice[0], req.Size, coverSlice[1])
}
}
Fitting := ""
if model3dIndex, ok := mapModel3d[*v.OptionalId]; ok {
Fitting = *productModel3dList[model3dIndex].Title
}
pcBox := int64(0)
Size := ""
if detailTemplateIndex, ok := mapDetailTemplate[*v.OrderDetailTemplateId]; ok {
pcBox = *v.BuyNum / *detailTemplateList[detailTemplateIndex].EachBoxNum
if sizeIndex, ok := mapProductSize[*detailTemplateList[detailTemplateIndex].SizeId]; ok {
Size = *productSizeList[sizeIndex].Capacity
}
}
Title := ""
if productIndex, ok := mapProduct[*v.ProductId]; ok {
Title = *productList[productIndex].Title
}
productListRsp = append(productListRsp, &types.Product{
Cover: cover,
Fitting: Fitting,
OptionPrice: *v.OptionPrice,
OrderDetailTemplateId: *v.OrderDetailTemplateId,
OrderId: *v.OrderId,
Pcs: *v.BuyNum,
PcsBox: pcBox,
Price: *v.Amount,
ProductId: *v.ProductId,
Size: Size,
Title: Title,
})
}
data := types.GetOrderDetailRsp{
Id: orderInfo.Id,
TotalAmount: *orderInfo.TotalAmount,
Deposit: *orderInfo.TotalAmount / 2,
Remaining: *orderInfo.TotalAmount - *orderInfo.TotalAmount/2,
IsPayCompleted: *orderInfo.IsPayCompleted,
DeliveryMethod: *orderInfo.DeliveryMethod,
Sn: *orderInfo.Sn,
Status: int64(orderStatus),
Ctime: time.Unix(*orderInfo.Ctime, 0).Format("2006-01-02 15:04:05"),
Address: nil,
ProductList: productListRsp,
}
//直接邮寄才有地址信息
if *orderInfo.DeliveryMethod == int64(constants.DELIVERY_METHOD_ADDRESS) {
addressInfo, err := gmodel.NewFsAddressModel(l.svcCtx.MysqlConn).GetOne(l.ctx, *orderInfo.AddressId, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "address not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get address info")
}
data.Address = &types.Address{
Id: addressInfo.Id,
UserId: *addressInfo.UserId,
Name: *addressInfo.Name,
FirstName: *addressInfo.FirstName,
LastName: *addressInfo.LastName,
Mobile: *addressInfo.Mobile,
Street: *addressInfo.Street,
Suite: *addressInfo.Suite,
City: *addressInfo.City,
State: *addressInfo.State,
Country: *addressInfo.Country,
ZipCode: *addressInfo.ZipCode,
Status: *addressInfo.Status,
IsDefault: *addressInfo.IsDefault,
}
}
data.PayInfo = &types.PayInfo{}
//首款
if payIndex, ok := mapPay[1]; ok {
data.PayInfo.Deposit = types.Deposit{
Method: *payList[payIndex].Brand,
TransNo: *payList[payIndex].TradeNo,
}
}
//尾款
if payIndex, ok := mapPay[2]; ok {
data.PayInfo.Final = types.Deposit{
Method: *payList[payIndex].Brand,
TransNo: *payList[payIndex].TradeNo,
}
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", data)
}

View File

@ -1,189 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/pdf"
"gorm.io/gorm"
"strings"
"time"
"context"
"fusenapi/server/orders/internal/svc"
"fusenapi/server/orders/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetOrderInvoiceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetOrderInvoiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderInvoiceLogic {
return &GetOrderInvoiceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetOrderInvoiceLogic) GetOrderInvoice(req *types.GetOrderInvoiceReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
//获取用户信息
userModel := gmodel.NewFsUserModel(l.svcCtx.MysqlConn)
user, err := userModel.FindUserById(l.ctx, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "user not found")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get user info")
}
if req.Sn == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param sn is required")
}
//查询订单信息
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the order is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info")
}
//地址数据
var address gmodel.FsAddress
if err = json.Unmarshal([]byte(*orderInfo.AddressInfo), &address); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse address info")
}
userName := ""
if user.LastName != nil && user.FirstName != nil && *user.LastName != "" && *user.FirstName != "" {
userName = *user.LastName + " " + *user.FirstName
} else if address.LastName != nil && address.FirstName != nil && *address.LastName != "" && *address.FirstName != "" {
userName = *address.LastName + " " + *address.LastName
}
pdfFileName := *orderInfo.Sn + "_" + userName + "_FusenPack.pdf"
//首款
firstPayment := *orderInfo.TotalAmount / 2
amountDue := int64(0)
//未完全支付
if *orderInfo.IsPayCompleted == 0 {
amountDue = *orderInfo.TotalAmount - firstPayment
}
var (
secondPaymentHtml string
firstStyle1 = `style="padding-bottom: 20px; border-bottom: 1px solid #212121;"`
firstStyle2 = `style="width: 16.66%; padding-bottom: 20px; border-bottom: 1px solid #212121;"`
payHtml = strings.Builder{}
orderHTML strings.Builder
totalAmount float64
rowspan = `rowspan = "12"`
)
if *orderInfo.IsPayCompleted == 1 {
firstStyle1 = ""
firstStyle2 = ""
rowspan = `rowspan = "14"`
remainAmount := float64(*orderInfo.TotalAmount - firstPayment)
secondPaymentHtml = strings.ReplaceAll(constants.SECOND_PAYMENY_HTML, "{{remain_amount}}", fmt.Sprintf("%.2f", remainAmount/100))
}
//获取订单详情列表
orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
orderDetails, err := orderDetailModel.GetOrderDetailsByOrderId(l.ctx, orderInfo.Id)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details")
}
if len(orderDetails) == 0 {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order details is empty")
}
productIds := make([]int64, 0, len(orderDetails))
for _, v := range orderDetails {
productIds = append(productIds, *v.ProductId)
}
//获取产品列表
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
productList, err := productModel.GetProductListByIds(l.ctx, productIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product list")
}
mapProduct := make(map[int64]int)
for k, v := range productList {
mapProduct[v.Id] = k
}
payModel := gmodel.NewFsPayModel(l.svcCtx.MysqlConn)
payList, err := payModel.GetListByOrderNumber(l.ctx, *orderInfo.Sn)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get payment list")
}
for _, v := range payList {
tem := strings.ReplaceAll(constants.PAYMENT_HTML, "{{pay_amount}}", fmt.Sprintf("%.2f", float64(*v.PayAmount)/100))
tem = strings.ReplaceAll(tem, "{{brand}}", *v.Brand)
tem = strings.ReplaceAll(tem, "{{card_no}}", *v.CardNo)
payHtml.WriteString(tem)
}
detailCount := len(orderDetails)
for k, v := range orderDetails {
amount := float64(*v.Amount)
sumAmount := amount * float64(*v.BuyNum)
totalAmount += sumAmount
var style1, style2 string
if k == (detailCount - 1) {
style1 = "vertical-align: top;"
style2 = "padding-bottom: 20px; border-bottom: 1px solid #212121;"
}
tem := strings.ReplaceAll(constants.ORDER_HTML, "{{amount}}", fmt.Sprintf("%.2f", amount/100))
tem = strings.ReplaceAll(tem, "{{style1}}", style1)
tem = strings.ReplaceAll(tem, "{{style2}}", style2)
tem = strings.ReplaceAll(tem, "{{rowspan}}", rowspan)
tem = strings.ReplaceAll(tem, "{{buy_num}}", fmt.Sprintf("%d", *v.BuyNum))
tem = strings.ReplaceAll(tem, "{{sum_amount}}", fmt.Sprintf("%.2f", sumAmount/100))
if productIndex, ok := mapProduct[*v.ProductId]; ok {
tem = strings.ReplaceAll(tem, "{{product_title}}", *productList[productIndex].Title)
} else {
tem = strings.ReplaceAll(tem, "{{product_title}}", "")
}
orderHTML.WriteString(tem)
}
mainHtml := strings.ReplaceAll(constants.MAIN_INVOICE_HTML, "{{pay_html}}", payHtml.String())
mainHtml = strings.ReplaceAll(mainHtml, "{{amount_due}}", fmt.Sprintf("%.2f", float64(amountDue)/100))
mainHtml = strings.ReplaceAll(mainHtml, "{{second_payment_html}}", secondPaymentHtml)
mainHtml = strings.ReplaceAll(mainHtml, "{{total_amount}}", fmt.Sprintf("%.2f", totalAmount/100))
mainHtml = strings.ReplaceAll(mainHtml, "{{first_payment}}", fmt.Sprintf("%.2f", float64(firstPayment)/100))
mainHtml = strings.ReplaceAll(mainHtml, "{{orderHTML}}", orderHTML.String())
mainHtml = strings.ReplaceAll(mainHtml, "{{city}}", *address.City)
mainHtml = strings.ReplaceAll(mainHtml, "{{state}}", *address.State)
mainHtml = strings.ReplaceAll(mainHtml, "{{zip_code}}", *address.ZipCode)
mainHtml = strings.ReplaceAll(mainHtml, "{{street}}", *address.Street)
mainHtml = strings.ReplaceAll(mainHtml, "{{suite}}", *address.Suite)
mainHtml = strings.ReplaceAll(mainHtml, "{{name}}", userName)
mainHtml = strings.ReplaceAll(mainHtml, "{{first_style1}}", firstStyle1)
mainHtml = strings.ReplaceAll(mainHtml, "{{first_style2}}", firstStyle2)
mainHtml = strings.ReplaceAll(mainHtml, "{{h5Url}}", constants.H5_URL)
mainHtml = strings.ReplaceAll(mainHtml, "{{order_sn}}", *orderInfo.Sn)
mainHtml = strings.ReplaceAll(mainHtml, "{{order_expire_time}}", time.Unix(*orderInfo.Ctime, req.TimeZone*60).Format("02 Jan,2006"))
//html内容页面转pdf的base64
prfBase64, err := pdf.HtmlToPdfBase64(mainHtml, 2)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to generate pdf file")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetOrderInvoiceRsp{
FileName: pdfFileName,
Pdf: prfBase64,
})
}

View File

@ -1,66 +0,0 @@
package svc
import (
"errors"
"fmt"
"fusenapi/server/orders/internal/config"
"fusenapi/shared"
"net/http"
"fusenapi/initalize"
"fusenapi/model/gmodel"
"github.com/golang-jwt/jwt"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
SharedState *shared.SharedState
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
// StateServer := shared.StartNode(c.ReplicaId, autoconfig.AutoGetAllServerConfig(), conn)
return &ServiceContext{
Config: c,
MysqlConn: conn,
SharedState: nil,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
}
}
func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if AuthKey == "" {
return nil, nil
}
AuthKey = AuthKey[7:]
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// 返回用于验证签名的密钥
return []byte(svcCtx.Config.Auth.AccessSecret), nil
})
if err != nil {
return nil, errors.New(fmt.Sprint("Error parsing token:", err))
}
// 验证成功返回
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New(fmt.Sprint("Invalid token", err))
}

View File

@ -1,146 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
type GetOrderInvoiceReq struct {
Sn string `form:"sn"`
TimeZone int64 `form:"timeZone"`
}
type GetOrderInvoiceRsp struct {
FileName string `json:"file_name"`
Pdf string `json:"pdf"`
}
type GetOrderDetailReq struct {
Sn string `form:"sn"`
Size int64 `form:"size, optional"`
}
type GetOrderDetailRsp struct {
Id int64 `json:"id"`
TotalAmount int64 `json:"total_amount"`
Deposit int64 `json:"deposit"`
Remaining int64 `json:"remaining"`
IsPayCompleted int64 `json:"is_pay_completed"`
DeliveryMethod int64 `json:"delivery_method"`
Sn string `json:"sn"`
Status int64 `json:"status"`
Ctime string `json:"ctime"`
PayInfo *PayInfo `json:"pay_info"`
Address *Address `json:"address"`
ProductList []*Product `json:"productList"`
}
type Product struct {
Cover string `json:"cover"`
Fitting string `json:"fitting"`
OptionPrice int64 `json:"option_price"`
OrderDetailTemplateId int64 `json:"order_detail_template_id"`
OrderId int64 `json:"order_id"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
Price int64 `json:"price"`
ProductId int64 `json:"product_id"`
Size string `json:"size"`
Title string `json:"title"`
}
type Address struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
Name string `json:"name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Mobile string `json:"mobile"`
Street string `json:"street"`
Suite string `json:"suite"`
City string `json:"city"`
State string `json:"state"`
Country string `json:"country"`
ZipCode string `json:"zip_code"`
Status int64 `json:"status"`
IsDefault int64 `json:"is_default"`
}
type PayInfo struct {
Deposit Deposit `json:"Deposit"`
Final Deposit `json:"Final"`
}
type Deposit struct {
Method string `json:"method"`
TransNo string `json:"trans_no"`
}
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:"totalCount"`
PageCount int64 `json:"pageCount"`
CurrentPage int `json:"currentPage"`
PerPage int `json:"perPage"`
}
// 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
}

View File

@ -1,35 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"fusenapi/server/orders/internal/config"
"fusenapi/server/orders/internal/handler"
"fusenapi/server/orders/internal/svc"
"fusenapi/utils/auth"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/orders.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
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()
}

View File

@ -1,7 +0,0 @@
package main
import "testing"
func TestMain(t *testing.T) {
main()
}

View File

@ -1,6 +0,0 @@
FROM alpine
WORKDIR /www/fusenapi/
COPY ./bin/api-render-srv /www/fusenapi/
COPY ./etc /www/fusenapi/etc
CMD ["/www/fusenapi/api-render-srv"]

View File

@ -1,24 +0,0 @@
Name: render
Host: 0.0.0.0
Port: 9919
ReplicaId: 70
Timeout: 15000 #服务超时时间
SourceMysql: "fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen"
Log:
Stat: false
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000
SourceRabbitMq: "amqp://rabbit001:rabbit001129@110.41.19.98:5672"
AWS:
S3:
Credentials:
AccessKeyID: AKIAZB2JKUXDPNRP4YT2
Secret: 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
Token:
BLMService:
Url: "http://18.119.109.254:8999"
LogoCombine:
#Url: "http://192.168.1.7:8999/LogoCombine"
Url: "http://18.119.109.254:8999/LogoCombine"

View File

@ -1,30 +0,0 @@
package config
import (
"fusenapi/server/render/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
ReplicaId uint64
SourceRabbitMq string
AWS struct {
S3 struct {
Credentials struct {
AccessKeyID string
Secret string
Token string
}
}
}
BLMService struct {
Url string
LogoCombine struct {
Url string
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/render/internal/logic"
"fusenapi/server/render/internal/svc"
"fusenapi/server/render/internal/types"
)
func GetFaceSliceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewGetFaceSliceLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.GetFaceSlice(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,22 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/render/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/render/get_face_slice",
Handler: GetFaceSliceHandler(serverCtx),
},
},
)
}

View File

@ -1,70 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fusenapi/constants"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"strings"
"gorm.io/gorm"
"context"
"fusenapi/server/render/internal/svc"
"fusenapi/server/render/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetFaceSliceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetFaceSliceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFaceSliceLogic {
return &GetFaceSliceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 处理进入前逻辑w,r
// func (l *GetFaceSliceLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *GetFaceSliceLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }
func (l *GetFaceSliceLogic) GetFaceSlice(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
if !userinfo.IsUser() && !userinfo.IsGuest() {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login or access cookie")
}
//获取用户素材信息
materialInfo, err := l.svcCtx.AllModels.FsUserMaterial.FindLatestOne(l.ctx, userinfo.UserId, userinfo.GuestId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "user material info is not exists")
}
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get user material info")
}
if materialInfo.Metadata == nil {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "user material info`Metadata is empty")
}
var info map[string]interface{}
if err = json.Unmarshal([]byte(*materialInfo.Metadata), &info); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeJsonErr, "invalid json format of metadata")
}
str := strings.ReplaceAll(constants.RENDER_FACE_SLICE_TEMPLATE_JSON, "{{MainColorFill}}", info["main_color_fill"].(string))
str = strings.ReplaceAll(str, "{{SecondaryColorFill}}", info["secondary_color_fill"].(string))
str = strings.ReplaceAll(str, "{{LogoMaterial}}", info["logo_material"].(string))
var rspInfo interface{}
_ = json.Unmarshal([]byte(str), &rspInfo)
return resp.SetStatusWithMessage(basic.CodeOK, "success", rspInfo)
}

View File

@ -1,83 +0,0 @@
package svc
import (
"errors"
"fmt"
"fusenapi/server/render/internal/config"
"fusenapi/shared"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"fusenapi/initalize"
"fusenapi/model/gmodel"
"github.com/golang-jwt/jwt"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
SharedState *shared.SharedState
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
RabbitMq *initalize.RabbitMqHandle
AwsSession *session.Session
Repositories *initalize.Repositories
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
// StateServer := shared.StartNode(c.ReplicaId, autoconfig.AutoGetAllServerConfig(), conn)
config := aws.Config{
Credentials: credentials.NewStaticCredentials(c.AWS.S3.Credentials.AccessKeyID, c.AWS.S3.Credentials.Secret, c.AWS.S3.Credentials.Token),
}
return &ServiceContext{
Config: c,
MysqlConn: conn,
SharedState: nil,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
AwsSession: session.Must(session.NewSession(&config)),
Repositories: initalize.NewAllRepositories(&initalize.NewAllRepositorieData{
GormDB: initalize.InitMysql(c.SourceMysql),
BLMServiceUrl: &c.BLMService.Url,
AwsSession: session.Must(session.NewSession(&config)),
}),
}
}
func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if AuthKey == "" {
return nil, nil
}
AuthKey = AuthKey[7:]
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// 返回用于验证签名的密钥
return []byte(svcCtx.Config.Auth.AccessSecret), nil
})
if err != nil {
return nil, errors.New(fmt.Sprint("Error parsing token:", err))
}
// 验证成功返回
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New(fmt.Sprint("Invalid token", err))
}

View File

@ -1,75 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
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:"totalCount"`
PageCount int64 `json:"pageCount"`
CurrentPage int `json:"currentPage"`
PerPage int `json:"perPage"`
}
// 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
}

View File

@ -1,33 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"fusenapi/utils/auth"
"fusenapi/server/render/internal/config"
"fusenapi/server/render/internal/handler"
"fusenapi/server/render/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/render.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
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()
}

View File

@ -1,6 +0,0 @@
FROM alpine
WORKDIR /www/fusenapi/
COPY ./bin/api-shopping-cart-confirmation-srv /www/fusenapi/
COPY ./etc /www/fusenapi/etc
CMD ["/www/fusenapi/api-shopping-cart-confirmation-srv"]

View File

@ -1,12 +0,0 @@
Name: shopping-cart-confirmation
Host: localhost
Port: 9911
ReplicaId: 80
Timeout: 15000 #服务超时时间
SourceMysql: "fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen"
Log:
Stat: false
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000

View File

@ -1,14 +0,0 @@
package config
import (
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
ReplicaId uint64
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CartAddHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.CartAddReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCartAddLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CartAdd(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CartDeleteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.CartDeleteReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCartDeleteLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CartDelete(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CartListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.CartListReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCartListLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CartList(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CartNumberHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.Request
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCartNumberLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CartNumber(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CartOrderDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.CartOrderDetailReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCartOrderDetailLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CartOrderDetail(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func ChangeOrderMethodHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.ChangeOrderMethodReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewChangeOrderMethodLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.ChangeOrderMethod(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,35 +0,0 @@
package handler
import (
"net/http"
"reflect"
"fusenapi/utils/basic"
"fusenapi/server/shopping-cart-confirmation/internal/logic"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
)
func CreateOrderHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.CreateOrderReq
userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
if err != nil {
return
}
// 创建一个业务逻辑层实例
l := logic.NewCreateOrderLogic(r.Context(), svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.CreateOrder(&req, userinfo)
if !basic.AfterLogic(w, r, rl, resp) {
basic.NormalAfterLogic(w, r, resp)
}
}
}

View File

@ -1,52 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/shopping-cart-confirmation/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/cart/add",
Handler: CartAddHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/cart/del",
Handler: CartDeleteHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/cart/num",
Handler: CartNumberHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/cart/list",
Handler: CartListHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/api/cart/order-detail",
Handler: CartOrderDetailHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/cart/chang-order-method",
Handler: ChangeOrderMethodHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/api/cart/create-order",
Handler: CreateOrderHandler(serverCtx),
},
},
)
}

View File

@ -1,132 +0,0 @@
package logic
import (
"errors"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"strings"
"time"
"gorm.io/gorm"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CartAddLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCartAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartAddLogic {
return &CartAddLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 添加入购物车
func (l *CartAddLogic) CartAdd(req *types.CartAddReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
if req.BuyNum == 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param buy_num can`t be 0")
}
if req.IsCheck != 0 && req.IsCheck != 1 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param is_check should be 0 or 1")
}
req.DesignId = strings.Trim(req.DesignId, " ")
if req.DesignId == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param design_id can`t be empty")
}
//查询是否有此设计
productDesignModel := gmodel.NewFsProductDesignModel(l.svcCtx.MysqlConn)
productDesignInfo, err := productDesignModel.FindOneBySn(l.ctx, req.DesignId, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "design info is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product design info")
}
//查找是否有此材质、产品、大小id的阶梯价格
productPriceModel := gmodel.NewFsProductPriceModel(l.svcCtx.MysqlConn)
priceStatus := int64(1)
priceReq := gmodel.FindOneProductPriceByParamsReq{
ProductId: productDesignInfo.ProductId,
MaterialId: productDesignInfo.MaterialId,
SizeId: productDesignInfo.SizeId,
Status: &priceStatus,
}
productPriceInfo, err := productPriceModel.FindOneProductPriceByParams(l.ctx, priceReq)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product price info")
}
if productPriceInfo.Id == 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, " product price info is not exists")
}
if *productPriceInfo.EachBoxNum == 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, " product price info err: each box num can`t be zero")
}
//买的数量和每箱数量取余为0 且 份数大于等于最小购买数量才算满足条件
if req.BuyNum%*productPriceInfo.EachBoxNum != 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "invalid buy number,please check")
}
if int64(float64(req.BuyNum)/float64(*productPriceInfo.EachBoxNum)) < *productPriceInfo.MinBuyNum {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "invalid buy number,please check!")
}
//查询购物车
cartModel := gmodel.NewFsCartModel(l.svcCtx.MysqlConn)
cartStatus := int64(1)
cartReq := gmodel.FindOneCartByParamsReq{
UserId: &userinfo.UserId,
ProductId: productDesignInfo.ProductId,
TemplateId: productDesignInfo.TemplateId,
PriceId: &productPriceInfo.Id,
DesignId: &productDesignInfo.Id,
MaterialId: productDesignInfo.MaterialId,
Status: &cartStatus,
}
cartInfo, err := cartModel.FindOneCartByParams(l.ctx, cartReq)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get cart info")
}
now := time.Now().UTC().Unix()
nowTime := time.Now().UTC()
data := gmodel.FsCart{
UserId: &userinfo.UserId,
ProductId: productPriceInfo.ProductId,
TemplateId: productDesignInfo.TemplateId,
PriceId: &productPriceInfo.Id,
MaterialId: productDesignInfo.MaterialId,
SizeId: productDesignInfo.SizeId,
BuyNum: &req.BuyNum,
Cover: productDesignInfo.Cover,
DesignId: &productDesignInfo.Id,
Ctime: &now,
Status: &cartStatus,
OptionalId: productDesignInfo.OptionalId,
IsCheck: &req.IsCheck,
TsTime: &nowTime,
}
if cartInfo == nil {
err = cartModel.Create(l.ctx, data)
} else {
err = cartModel.Update(l.ctx, cartInfo.Id, data)
}
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to add to cart")
}
return resp.SetStatusWithMessage(basic.CodeOK, "add to cart success")
}

View File

@ -1,47 +0,0 @@
package logic
import (
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CartDeleteLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCartDeleteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartDeleteLogic {
return &CartDeleteLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CartDeleteLogic) CartDelete(req *types.CartDeleteReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
if req.Id <= 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "invalid param id")
}
cartModel := gmodel.NewFsCartModel(l.svcCtx.MysqlConn)
status := int64(0)
err := cartModel.UpdateByIdUserId(l.ctx, req.Id, userinfo.UserId, gmodel.FsCart{
Status: &status,
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to delete cart")
}
return resp.SetStatusWithMessage(basic.CodeOK, "delete success")
}

View File

@ -1,278 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/image"
"fusenapi/utils/step_price"
"strings"
"sync"
"time"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CartListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCartListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartListLogic {
return &CartListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 获取用户购物车列表
func (l *CartListLogic) CartList(req *types.CartListReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
//获取当前图片应该返回的尺寸大小
if req.Size > 0 {
req.Size = image.GetCurrentSize(req.Size)
}
//获取用户购物车数据
cartRelativeData, err := l.getUserCartRelativeList(l.ctx, userinfo.UserId)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get cart list data")
}
if len(cartRelativeData.CartList) == 0 {
return resp.SetStatusWithMessage(basic.CodeOK, "success")
}
//产品名map
mapProduct := make(map[int64]int)
for k, v := range cartRelativeData.ProductList {
mapProduct[v.Id] = k
}
//产品尺寸size map
mapProductSize := make(map[int64]int)
for k, v := range cartRelativeData.ProductSizeList {
mapProductSize[v.Id] = k
}
//设计map数据
mapProductDesign := make(map[int64]int)
for k, v := range cartRelativeData.ProductDesignList {
mapProductDesign[v.Id] = k
}
//产品模型map数据
mapProductModel3d := make(map[int64]int)
for k, v := range cartRelativeData.ProductModel3dList {
mapProductModel3d[v.Id] = k
}
//遍历组装数据
rspList := make([]types.CartListRsp, 0, len(cartRelativeData.CartList))
for _, v := range cartRelativeData.CartList {
name := ""
productSn := ""
if productIndex, ok := mapProduct[*v.ProductId]; ok {
name = *cartRelativeData.ProductList[productIndex].Title
productSn = strings.ToLower(*cartRelativeData.ProductList[productIndex].Sn)
}
designSn := ""
if designIndex, ok := mapProductDesign[*v.DesignId]; ok {
designSn = strings.ToLower(*cartRelativeData.ProductDesignList[designIndex].Sn)
}
pcList, err := l.getPcList(cartRelativeData.ProductPriceList, *v.ProductId, *v.MaterialId, *v.SizeId)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to calculate step price")
}
d := types.CartListRsp{
Id: v.Id,
Cover: *v.Cover,
Name: name,
Capacity: "",
ETA: time.Now().UTC().AddDate(0, 0, 60).Format("2006-01-02 15:04:05"),
Pcs: *v.BuyNum,
ProductSn: productSn,
DesignSn: designSn,
Option: nil,
IsCheck: *v.IsCheck,
TsTime: v.TsTime.Format("2006-01-02 15:04:05"),
PcsList: pcList,
Size: nil,
}
var sizeList types.CartSizeItem
if sizeIndex, ok := mapProductSize[*v.SizeId]; ok {
d.Capacity = *cartRelativeData.ProductSizeList[sizeIndex].Capacity
err = json.Unmarshal([]byte(*cartRelativeData.ProductSizeList[sizeIndex].Title), &sizeList)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse product size`s title")
}
d.Size = &sizeList
}
if model3dIndex, ok := mapProductModel3d[*v.OptionalId]; ok {
d.Option = &types.CartOption{
Id: cartRelativeData.ProductModel3dList[model3dIndex].Id,
Title: *cartRelativeData.ProductModel3dList[model3dIndex].Title,
Price: float64(*cartRelativeData.ProductModel3dList[model3dIndex].Price) / float64(100),
}
}
rspList = append(rspList, d)
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", rspList)
}
type GetUserCartRelativeListRsp struct {
CartList []gmodel.FsCart
ProductDesignList []gmodel.FsProductDesign
ProductSizeList []gmodel.FsProductSize
ProductList []gmodel.FsProduct
ProductModel3dList []gmodel.FsProductModel3d
ProductTemplateV2List []gmodel.FsProductTemplateV2
ProductPriceList []gmodel.FsProductPrice
}
// 获取阶梯对应的价格
func (l *CartListLogic) getPcList(productPriceList []gmodel.FsProductPrice, productId int64, materialId int64, sizeId int64) (list []*types.PcsItem, err error) {
for _, price := range productPriceList {
if *price.ProductId != productId || *price.MaterialId != materialId || *price.SizeId != sizeId {
continue
}
stepNumStrSlice := strings.Split(*price.StepNum, ",")
stepNumSlice, err := format.StrSlicToIntSlice(stepNumStrSlice)
if err != nil {
return nil, err
}
stepPriceStrSlice := strings.Split(*price.StepPrice, ",")
stepPriceSlice, err := format.StrSlicToIntSlice(stepPriceStrSlice)
if err != nil {
return nil, err
}
lenStepPriceSlice := len(stepPriceSlice)
lenStepNumSlice := len(stepNumSlice)
if lenStepPriceSlice == 0 || lenStepNumSlice == 0 {
return nil, errors.New("step num or step price item count can`t be 0 ")
}
for int(*price.MinBuyNum) < stepNumSlice[lenStepNumSlice-1]+5 {
list = append(list, &types.PcsItem{
Num: *price.MinBuyNum,
TotalNum: *price.MinBuyNum * *price.EachBoxNum,
Title: *price.Title,
Price: step_price.GetStepPrice(int(*price.MinBuyNum), stepNumSlice, stepPriceSlice),
})
*price.MinBuyNum++
}
}
return list, nil
}
// 获取用户购物车数据
func (l *CartListLogic) getUserCartRelativeList(ctx context.Context, userId int64) (resp GetUserCartRelativeListRsp, err error) {
//购物车列表
cartModel := gmodel.NewFsCartModel(l.svcCtx.MysqlConn)
cartList, err := cartModel.GetAllByUserId(ctx, userId, "ctime-desc")
if err != nil {
return GetUserCartRelativeListRsp{}, err
}
if len(cartList) == 0 {
return
}
resp.CartList = cartList
productIds := make([]int64, 0, len(cartList))
sizeIds := make([]int64, 0, len(cartList))
designIds := make([]int64, 0, len(cartList))
optionIds := make([]int64, 0, len(cartList))
templateIds := make([]int64, 0, len(cartList))
for _, v := range cartList {
productIds = append(productIds, *v.ProductId)
sizeIds = append(sizeIds, *v.SizeId)
designIds = append(designIds, *v.DesignId)
optionIds = append(optionIds, *v.OptionalId)
templateIds = append(templateIds, *v.TemplateId)
}
//******************************协程并发开始***********************************
wait := sync.WaitGroup{}
errChan := make(chan error)
wait.Add(6) //注意要加协程这里要记得加
//获取产品数据1
go func() {
defer wait.Done()
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
productList, err := productModel.GetProductListByIds(ctx, productIds, "")
if err != nil {
errChan <- err
return
}
resp.ProductList = productList
}()
//获取尺寸数据2
go func() {
defer wait.Done()
productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn)
productSizeList, err := productSizeModel.GetAllByIds(ctx, sizeIds, "")
if err != nil {
errChan <- err
}
resp.ProductSizeList = productSizeList
}()
//获取设计列表3
go func() {
defer wait.Done()
productDesignModel := gmodel.NewFsProductDesignModel(l.svcCtx.MysqlConn)
productDesignList, err := productDesignModel.GetAllByIds(ctx, designIds)
if err != nil {
errChan <- err
}
resp.ProductDesignList = productDesignList
}()
//获取配件列表4
go func() {
defer wait.Done()
productModel3dModel := gmodel.NewFsProductModel3dModel(l.svcCtx.MysqlConn)
productModel3dList, err := productModel3dModel.GetAllByIdsTag(ctx, optionIds, constants.TAG_PARTS)
if err != nil {
errChan <- err
}
resp.ProductModel3dList = productModel3dList
}()
//获取模板信息5
go func() {
defer wait.Done()
productTemplateModel := gmodel.NewFsProductTemplateV2Model(l.svcCtx.MysqlConn)
templateV2List, err := productTemplateModel.FindAllByIds(ctx, templateIds)
if err != nil {
errChan <- err
}
resp.ProductTemplateV2List = templateV2List
}()
//获取产品价格列表6
go func() {
defer wait.Done()
productPriceModel := gmodel.NewFsProductPriceModel(l.svcCtx.MysqlConn)
productPriceList, err := productPriceModel.GetPriceListByProductIds(ctx, productIds)
if err != nil {
errChan <- err
}
resp.ProductPriceList = productPriceList
}()
//******************************协程并发结束***********************************
go func() {
wait.Wait()
close(errChan)
}()
//获取错误信息
for err = range errChan {
if err != nil {
return GetUserCartRelativeListRsp{}, err
}
}
return resp, nil
}

View File

@ -1,43 +0,0 @@
package logic
import (
"fusenapi/model/gmodel"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type CartNumberLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCartNumberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartNumberLogic {
return &CartNumberLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CartNumberLogic) CartNumber(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
cartModel := gmodel.NewFsCartModel(l.svcCtx.MysqlConn)
total, err := cartModel.CountUserCart(l.ctx, userinfo.UserId)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeApiErr, "failed to get count of your cart")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CartNumberRsp{
Num: total,
})
}

View File

@ -1,180 +0,0 @@
package logic
import (
"errors"
"fmt"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"gorm.io/gorm"
"strings"
"time"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CartOrderDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCartOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CartOrderDetailLogic {
return &CartOrderDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CartOrderDetailLogic) CartOrderDetail(req *types.CartOrderDetailReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
req.Sn = strings.Trim(req.Sn, " ")
if req.Sn == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param sn is required")
}
//获取订单数据
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the order is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info")
}
//获取订单详细数据
orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
orderDetailList, err := orderDetailModel.GetOrderDetailsByOrderId(l.ctx, orderInfo.Id)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details")
}
if len(orderDetailList) == 0 {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "order details is empty")
}
orderDetailTemplateIds := make([]int64, 0, len(orderDetailList))
productIds := make([]int64, 0, len(orderDetailList))
for _, v := range orderDetailList {
orderDetailTemplateIds = append(orderDetailTemplateIds, *v.OrderDetailTemplateId)
productIds = append(productIds, *v.ProductId)
}
//获取订单详情对应模板信息
orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(l.svcCtx.MysqlConn)
orderDetailTemplateList, err := orderDetailTemplateModel.GetListByIds(l.ctx, orderDetailTemplateIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details templates")
}
sizeIds := make([]int64, 0, len(orderDetailTemplateList))
mapDetailTemplate := make(map[int64]int)
for k, v := range orderDetailTemplateList {
sizeIds = append(sizeIds, *v.SizeId)
mapDetailTemplate[v.Id] = k
}
//获取尺寸信息
productSizeModel := gmodel.NewFsProductSizeModel(l.svcCtx.MysqlConn)
productSizeList, err := productSizeModel.GetAllByIds(l.ctx, sizeIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product size list")
}
mapProductSize := make(map[int64]int)
for k, v := range productSizeList {
mapProductSize[v.Id] = k
}
//获取产品信息
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
productList, err := productModel.GetProductListByIds(l.ctx, productIds, "")
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order products")
}
mapProduct := make(map[int64]int)
for k, v := range productList {
mapProduct[v.Id] = k
}
//获取用户地址信息
addressModel := gmodel.NewFsAddressModel(l.svcCtx.MysqlConn)
addressList, err := addressModel.GetUserAllAddress(l.ctx, userinfo.UserId)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get address")
}
//处理订单数据
addressItems := make([]*types.CartAddr, 0, len(addressList))
for _, v := range addressList {
addressItems = append(addressItems, &types.CartAddr{
Id: v.Id,
Name: *v.Name,
FirstName: *v.FirstName,
LastName: *v.LastName,
Mobile: *v.Mobile,
Street: *v.Street,
Suite: *v.Suite,
City: *v.City,
State: *v.State,
ZipCode: *v.ZipCode,
IsDefault: *v.IsDefault,
})
}
items := make([]*types.CartDetailItem, 0, len(orderDetailList))
totalAmount := int64(0) //订单总金额
for _, v := range orderDetailList {
thisTotal := (*v.BuyNum) * (*v.Amount)
size := ""
if detailTemplateIndex, ok := mapDetailTemplate[*v.OrderDetailTemplateId]; ok {
detailTemplate := orderDetailTemplateList[detailTemplateIndex]
if sizeIndex, ok := mapProductSize[*detailTemplate.SizeId]; ok {
size = *productSizeList[sizeIndex].Capacity
}
}
name := ""
if productIndex, ok := mapProduct[*v.ProductId]; ok {
name = *productList[productIndex].Title
}
items = append(items, &types.CartDetailItem{
Cover: *v.Cover,
Pcs: *v.BuyNum,
Amount: fmt.Sprintf("$ %.2f", float64(thisTotal)/100),
Option: *v.OptionalTitle,
Size: size,
Name: name,
})
totalAmount += thisTotal
}
//首付50%
total := totalAmount / 2
//尾款
remaining := totalAmount - total
payStep := int64(0) //未支付
if *orderInfo.PayedAmount == *orderInfo.TotalAmount/2 {
payStep = 1 //已支付首款
}
if *orderInfo.PayedAmount == *orderInfo.TotalAmount {
payStep = 2 //已支付尾款
}
payTime := ""
if *orderInfo.Ptime != 0 {
payTime = time.Unix(*orderInfo.Ptime, 0).Format("2006-01-02 15:04:05")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CartOrderDetailRsp{
DeliveryMethod: 1,
AddressId: 0,
PayTime: payTime,
PayMethod: 1,
PayStep: payStep,
Subtotal: fmt.Sprintf("$%.2f", float64(totalAmount)/100),
Total: fmt.Sprintf("$%.2f", float64(total)/100),
Remaining: fmt.Sprintf("$%.2f", float64(remaining)/100),
AddrList: addressItems,
Items: items,
})
}

View File

@ -1,79 +0,0 @@
package logic
import (
"encoding/json"
"errors"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"gorm.io/gorm"
"strings"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type ChangeOrderMethodLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewChangeOrderMethodLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ChangeOrderMethodLogic {
return &ChangeOrderMethodLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *ChangeOrderMethodLogic) ChangeOrderMethod(req *types.ChangeOrderMethodReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
req.Sn = strings.Trim(req.Sn, " ")
if req.Sn == "" {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param sn is required")
}
//查询订单信息
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the order is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info")
}
if *orderInfo.PayedAmount > 0 {
return resp.SetStatusWithMessage(basic.CodeApiErr, "the order`s address cannot be changed for it is paid")
}
updData := &gmodel.FsOrder{Id: orderInfo.Id}
//地址
if req.AddressId > 0 {
addressModel := gmodel.NewFsAddressModel(l.svcCtx.MysqlConn)
addr, err := addressModel.GetOne(l.ctx, req.AddressId, userinfo.UserId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return resp.SetStatusWithMessage(basic.CodeServiceErr, "address is not exists")
}
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get address info")
}
infoJsonByte, _ := json.Marshal(addr)
strInfoJson := string(infoJsonByte)
updData.AddressInfo = &strInfoJson
}
updData.DeliveryMethod = &req.DeliveryMethod
updData.AddressId = &req.AddressId
updData.PayMethod = &req.PayMethod
if err = orderModel.Update(l.ctx, updData); err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to save data")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success")
}

View File

@ -1,190 +0,0 @@
package logic
import (
"fmt"
"fusenapi/model/gmodel"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/utils/format"
"fusenapi/utils/id_generator"
"fusenapi/utils/step_price"
"math"
"strings"
"time"
"gorm.io/gorm"
"context"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/server/shopping-cart-confirmation/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type CreateOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic {
return &CreateOrderLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq, userinfo *auth.UserInfo) (resp *basic.Response) {
if userinfo.GetIdType() != auth.IDTYPE_User {
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
}
if len(req.Form) == 0 {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param form:can`t be empty")
}
cartIds := make([]int64, 0, len(req.Form))
mapForm := make(map[int64]int)
for k, v := range req.Form {
cartIds = append(cartIds, v.Id)
mapForm[v.Id] = k
}
//获取购物车列表
cartList, err := l.svcCtx.AllModels.FsCart.GetUserCartsByIds(l.ctx, userinfo.UserId, cartIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get cart list")
}
if len(cartList) != len(req.Form) {
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "sorry,may be some one not belong to you")
}
priceIds := make([]int64, 0, len(cartList))
optionalIds := make([]int64, 0, len(cartList))
for _, v := range cartList {
priceIds = append(priceIds, *v.PriceId)
optionalIds = append(optionalIds, *v.OptionalId)
}
//获取价格
priceList, err := l.svcCtx.AllModels.FsProductPrice.GetAllByIdsWithoutStatus(l.ctx, priceIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product price list")
}
mapPrice := make(map[int64]int)
for k, v := range priceList {
mapPrice[v.Id] = k
}
//获取附加项
model3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsWithoutStatus(l.ctx, optionalIds)
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get 3d model list")
}
mapModel3d := make(map[int64]int)
for k, v := range model3dList {
mapModel3d[v.Id] = k
}
var (
now = time.Now().UTC().Unix()
total int64 //总价
)
orderSn := id_generator.GenSnNum()
//开启事务
err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error {
orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(tx)
orderDetailModel := gmodel.NewFsOrderDetailModel(tx)
orderModel := gmodel.NewFsOrderModel(tx)
//订单数据
deliveryMethod := int64(1)
orderCreateData := gmodel.FsOrder{
Sn: &orderSn,
UserId: &userinfo.UserId,
Ctime: &now,
Utime: &now,
DeliveryMethod: &deliveryMethod,
}
if err = orderModel.Create(l.ctx, &orderCreateData); err != nil {
return err
}
for _, cart := range cartList {
priceIndex, ok := mapPrice[*cart.PriceId]
if !ok {
return fmt.Errorf("price info is not exists,id = %d", *cart.PriceId)
}
//订单详情模板数据
orderDetailTemplateSn, err := id_generator.GenSnowFlakeId()
if err != nil {
return err
}
orderDetailTemplateCreateData := gmodel.FsOrderDetailTemplate{
Sn: &orderDetailTemplateSn,
ProductId: cart.ProductId,
ModelId: cart.OptionalId,
TemplateId: cart.TemplateId,
MaterialId: cart.MaterialId,
SizeId: cart.SizeId,
EachBoxNum: priceList[priceIndex].EachBoxNum,
EachBoxWeight: priceList[priceIndex].EachBoxWeight,
DesignId: cart.DesignId,
Ctime: &now,
}
if err = orderDetailTemplateModel.Create(l.ctx, &orderDetailTemplateCreateData); err != nil {
return err
}
//获取阶梯价格和数量
stepNumSlice, err := format.StrSlicToIntSlice(strings.Split(*priceList[priceIndex].StepNum, ","))
if err != nil {
return err
}
stepPriceSlice, err := format.StrSlicToIntSlice(strings.Split(*priceList[priceIndex].StepPrice, ","))
if err != nil {
return err
}
formIndex, _ := mapForm[cart.Id] //一定会有不用判断
//订单详情数据
orderDetailSn, err := id_generator.GenSnowFlakeId()
if err != nil {
return err
}
optionalPrice := int64(0)
optionalTitle := ""
if model3dIndex, ok := mapModel3d[*cart.OptionalId]; ok {
optionalPrice = *model3dList[model3dIndex].Price
optionalTitle = *model3dList[model3dIndex].Title
}
fn := int(math.Ceil(float64(req.Form[formIndex].Num) / float64(*priceList[priceIndex].EachBoxNum)))
amount := step_price.GetCentStepPrice(fn, stepNumSlice, stepPriceSlice)
orderDetailCreateData := gmodel.FsOrderDetail{
OrderId: &orderCreateData.Id,
Sn: &orderDetailSn,
UserId: &userinfo.UserId,
OrderDetailTemplateId: &orderDetailTemplateCreateData.Id,
ProductId: cart.ProductId,
BuyNum: &req.Form[formIndex].Num, //以提交数量为准
Amount: &amount,
Cover: cart.Cover,
Ctime: &now,
OptionalId: cart.OptionalId,
OptionalTitle: &optionalTitle,
OptionPrice: &optionalPrice,
CartId: &cart.Id,
}
if err = orderDetailModel.Create(l.ctx, &orderDetailCreateData); err != nil {
return err
}
total += amount * (*orderDetailCreateData.BuyNum)
}
//更新订单总价
return orderModel.Update(l.ctx, &gmodel.FsOrder{
Id: orderCreateData.Id,
TotalAmount: &total,
})
})
if err != nil {
logx.Error(err)
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to create order")
}
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CreateOrderRsp{
Sn: orderSn,
})
}

View File

@ -1,66 +0,0 @@
package svc
import (
"errors"
"fmt"
"fusenapi/server/shopping-cart-confirmation/internal/config"
"fusenapi/shared"
"net/http"
"fusenapi/initalize"
"fusenapi/model/gmodel"
"github.com/golang-jwt/jwt"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
SharedState *shared.SharedState
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
// StateServer := shared.StartNode(c.ReplicaId, autoconfig.AutoGetAllServerConfig(), conn)
return &ServiceContext{
Config: c,
MysqlConn: conn,
SharedState: nil,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
}
}
func (svcCtx *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if AuthKey == "" {
return nil, nil
}
AuthKey = AuthKey[7:]
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
// 返回用于验证签名的密钥
return []byte(svcCtx.Config.Auth.AccessSecret), nil
})
if err != nil {
return nil, errors.New(fmt.Sprint("Error parsing token:", err))
}
// 验证成功返回
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New(fmt.Sprint("Invalid token", err))
}

View File

@ -1,187 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
type CartAddReq struct {
DesignId string `json:"design_id"` //设计sn
BuyNum int64 `json:"buy_num"` //购买数量
IsCheck int64 `json:"is_check,optional"`
}
type CartDeleteReq struct {
Id int64 `json:"id"`
}
type CartNumberRsp struct {
Num int64 `json:"num"`
}
type CartListReq struct {
Size uint32 `form:"size"`
}
type CartListRsp struct {
Id int64 `json:"id"`
Cover string `json:"cover"`
Name string `json:"name"`
Capacity string `json:"capacity"`
ETA string `json:"ETA"`
Pcs int64 `json:"pcs"`
ProductSn string `json:"product_sn"`
DesignSn string `json:"designSn"`
Option *CartOption `json:"option"`
IsCheck int64 `json:"is_check"`
TsTime string `json:"ts_time"`
PcsList []*PcsItem `json:"pcs_list"`
Size *CartSizeItem `json:"size"`
}
type CartOption struct {
Id int64 `json:"id"`
Title string `json:"title"`
Price float64 `json:"price"`
}
type PcsItem struct {
Num int64 `json:"num"`
TotalNum int64 `json:"total_num"`
Title string `json:"title"`
Price float64 `json:"price"`
}
type CartSizeItem struct {
Cm string `json:"cm"`
Inch string `json:"inch"`
}
type CartOrderDetailReq struct {
Sn string `form:"sn"`
}
type CartOrderDetailRsp struct {
DeliveryMethod int64 `json:"delivery_method"`
AddressId int64 `json:"address_id"`
PayTime string `json:"pay_time"`
PayMethod int64 `json:"pay_method"`
PayStep int64 `json:"pay_step"`
Subtotal string `json:"subtotal"`
Total string `json:"total"`
Remaining string `json:"remaining"`
AddrList []*CartAddr `json:"addr_list"`
Items []*CartDetailItem `json:"items"`
}
type CartDetailItem struct {
Cover string `json:"cover"`
Pcs int64 `json:"pcs"`
Amount string `json:"amount"`
Option string `json:"option"`
Size string `json:"size"`
Name string `json:"name"`
}
type CartAddr struct {
Id int64 `json:"id"`
Name string `json:"name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Mobile string `json:"mobile"`
Street string `json:"street"`
Suite string `json:"suite"`
City string `json:"city"`
State string `json:"state"`
ZipCode string `json:"zip_code"`
IsDefault int64 `json:"is_default"`
}
type ChangeOrderMethodReq struct {
Sn string `json:"sn"`
DeliveryMethod int64 `json:"delivery_method , options=1|2"`
AddressId int64 `json:"address_id"`
PayMethod int64 `json:"pay_method"`
}
type CreateOrderReq struct {
Form []OrderFormItem `json:"form"`
}
type OrderFormItem struct {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
type CreateOrderRsp struct {
Sn string `json:"sn"`
}
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:"totalCount"`
PageCount int64 `json:"pageCount"`
CurrentPage int `json:"currentPage"`
PerPage int `json:"perPage"`
}
// 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
}

View File

@ -1,53 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"fusenapi/server/shopping-cart-confirmation/internal/config"
"fusenapi/server/shopping-cart-confirmation/internal/handler"
"fusenapi/server/shopping-cart-confirmation/internal/svc"
"fusenapi/utils/auth"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/shopping-cart-confirmation.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
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()
}
// var testConfigFile = flag.String("f", "../etc/shopping-cart-confirmation.yaml", "the config file")
// var cnf config.Config
// func GetTestServer() *rest.Server {
// flag.Parse()
// conf.MustLoad(*testConfigFile, &cnf)
// server := rest.MustNewServer(cnf.RestConf)
// defer server.Stop()
// ctx := svc.NewServiceContext(cnf)
// handler.RegisterHandlers(server, ctx)
// fmt.Printf("Starting server at %s:%d...\n", cnf.Host, cnf.Port)
// return server
// }

View File

@ -1,123 +0,0 @@
syntax = "v1"
info (
title: "云仓服务"// TODO: add title
desc: // TODO: add description
author: "daming"
email: ""
)
import "basic.api"
service inventory {
//提取云仓货物
@handler TakeHandler
post /api/inventory/take(TakeReq) returns (response);
//获取云仓库存列表
@handler GetCloudListHandler
post /api/inventory/list(GetCloudListReq) returns (response);
//云仓补货
@handler SupplementHandler
post /api/inventory/supplement(SupplementReq) returns (response);
//提货列表
@handler GetPickupListHandler
get /api/inventory/pick-up-list(GetPickupListReq) returns (response);
}
//提取云仓货物
type TakeReq {
Form []TakeForm `json:"form"`
AddressId int64 `json:"address_id"`
}
type TakeForm {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
//获取云仓库存列表
type GetCloudListReq {
Page int `json:"page"`
PageSize int `json:"page_size"`
Size int64 `json:"size"`
}
type GetCloudListRsp {
WarehouseBoxes int64 `json:"warehouse_boxes"`
TransitBoxes int64 `json:"transit_boxes"`
MinTakeNum int64 `json:"minTakeNum"`
ListData []ListDataItem `json:"listData"`
Meta Meta `json:"_meta"`
}
type ListDataItem {
Id int64 `json:"id"`
Sn string `json:"sn"`
Cover string `json:"cover"`
Name string `json:"name"`
DesignSn string `json:"design_sn"`
Fitting string `json:"fitting"`
Production int64 `json:"production"`
ProductionBox int64 `json:"production_box"`
EachBoxNum int64 `json:"each_box_num"`
Stick int64 `json:"stick"`
StickBox int64 `json:"stick_box"`
Type int64 `json:"type"`
TakeNum int64 `json:"takeNum"`
Size string `json:"size"`
IsStop int64 `json:"is_stop"`
PriceList []PriceItem `json:"price"`
}
type PriceItem {
Num int64 `json:"num"`
TotalNum int64 `json:"total_num"`
Price int64 `json:"price"`
}
//云仓补货
type SupplementReq {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
type SupplementRsp {
Sn string `json:"sn"`
}
//提货列表
type GetPickupListReq {
Status int64 `form:"status,options=-1|1|2|3|4"`
Page int `form:"page"`
PageSize int `form:"page_size"`
Size int `form:"size"`
}
type GetPickupListRsp {
PickupList []PickupItem `json:"items"`
Meta Meta `json:"_meta"`
}
type PickupItem {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
TrackNum string `json:"track_num"`
Ctime string `json:"ctime"`
Status int64 `json:"status"`
UpsSn string `json:"ups_sn"`
Address string `json:"address"`
ProductList []Product `json:"productList"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
LogisticsStatus int64 `json:"logistics_status"`
StatusTimes []StatusTimesItem `json:"status_times"`
}
type Product {
Id int64 `json:"id"`
PickId int64 `json:"pick_id"`
StockId int64 `json:"stock_id"`
Num int64 `json:"num"`
Boxes int64 `json:"boxes"`
Ctime int64 `json:"ctime"`
ProductName string `json:"product_name"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
Cover string `json:"cover"`
Size string `json:"size"`
Fitting string `json:"fitting"`
}
type StatusTimesItem {
Key int64 `json:"key"`
Time string `json:"time"`
}

View File

@ -1,85 +0,0 @@
syntax = "v1"
info (
title: "订单服务"// TODO: add title
desc: // TODO: add description
author: ""
email: ""
)
import "basic.api"
service orders {
//获取订单发票
@handler GetOrderInvoiceHandler
get /api/order/invoice (GetOrderInvoiceReq) returns (response);
//获取订单详情
@handler GetOrderDetailHandler
get /api/order/detail (GetOrderDetailReq) returns (response);
}
//获取订单发票
type GetOrderInvoiceReq {
Sn string `form:"sn"`
TimeZone int64 `form:"timeZone"`
}
type GetOrderInvoiceRsp {
FileName string `json:"file_name"`
Pdf string `json:"pdf"`
}
//获取订单详情
type GetOrderDetailReq {
Sn string `form:"sn"`
Size int64 `form:"size, optional"`
}
type GetOrderDetailRsp {
Id int64 `json:"id"`
TotalAmount int64 `json:"total_amount"`
Deposit int64 `json:"deposit"`
Remaining int64 `json:"remaining"`
IsPayCompleted int64 `json:"is_pay_completed"`
DeliveryMethod int64 `json:"delivery_method"`
Sn string `json:"sn"`
Status int64 `json:"status"`
Ctime string `json:"ctime"`
PayInfo *PayInfo `json:"pay_info"`
Address *Address `json:"address"`
ProductList []*Product `json:"productList"`
}
type Product {
Cover string `json:"cover"`
Fitting string `json:"fitting"`
OptionPrice int64 `json:"option_price"`
OrderDetailTemplateId int64 `json:"order_detail_template_id"`
OrderId int64 `json:"order_id"`
Pcs int64 `json:"pcs"`
PcsBox int64 `json:"pcs_box"`
Price int64 `json:"price"`
ProductId int64 `json:"product_id"`
Size string `json:"size"`
Title string `json:"title"`
}
type Address {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
Name string `json:"name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Mobile string `json:"mobile"`
Street string `json:"street"`
Suite string `json:"suite"`
City string `json:"city"`
State string `json:"state"`
Country string `json:"country"`
ZipCode string `json:"zip_code"`
Status int64 `json:"status"`
IsDefault int64 `json:"is_default"`
}
type PayInfo {
Deposit Deposit `json:"Deposit"`
Final Deposit `json:"Final"`
}
type Deposit {
Method string `json:"method"`
TransNo string `json:"trans_no"`
}

View File

@ -1,15 +0,0 @@
syntax = "v1"
info (
title: "渲染"// TODO: add title
desc: // TODO: add description
author: ""
email: ""
)
import "basic.api"
service render {
//获取面片信息
@handler GetFaceSliceHandler
post /api/render/get_face_slice(request) returns (response);
}

View File

@ -1,139 +0,0 @@
syntax = "v1"
info (
title: "购物车服务"
desc: // TODO: add description
author: "ldm"
email: ""
)
import "basic.api"
service shopping-cart-confirmation {
//添加入购物车
@handler CartAddHandler
post /api/cart/add (CartAddReq) returns (response);
//删除购物车
@handler CartDeleteHandler
post /api/cart/del (CartDeleteReq) returns (response);
//获取用户购物车数量
@handler CartNumberHandler
get /api/cart/num (request) returns (response);
//获取用户购物车列表
@handler CartListHandler
get /api/cart/list (CartListReq) returns (response);
//获取用户购物车订单详情
@handler CartOrderDetailHandler
get /api/cart/order-detail (CartOrderDetailReq) returns (response);
//变更发货方式和地址
@handler ChangeOrderMethodHandler
post /api/cart/chang-order-method (ChangeOrderMethodReq) returns (response);
//创建购物车订单
@handler CreateOrderHandler
post /api/cart/create-order (CreateOrderReq) returns (response);
}
//添加入购物车
type CartAddReq {
DesignId string `json:"design_id"` //设计sn
BuyNum int64 `json:"buy_num"` //购买数量
IsCheck int64 `json:"is_check,optional"`
}
//删除购物车
type CartDeleteReq {
Id int64 `json:"id"`
}
//获取用户购物车数量
type CartNumberRsp {
Num int64 `json:"num"`
}
//获取用户购物车列表
type CartListReq {
Size uint32 `form:"size"`
}
type CartListRsp {
Id int64 `json:"id"`
Cover string `json:"cover"`
Name string `json:"name"`
Capacity string `json:"capacity"`
ETA string `json:"ETA"`
Pcs int64 `json:"pcs"`
ProductSn string `json:"product_sn"`
DesignSn string `json:"designSn"`
Option *CartOption `json:"option"`
IsCheck int64 `json:"is_check"`
TsTime string `json:"ts_time"`
PcsList []*PcsItem `json:"pcs_list"`
Size *CartSizeItem `json:"size"`
}
type CartOption {
Id int64 `json:"id"`
Title string `json:"title"`
Price float64 `json:"price"`
}
type PcsItem {
Num int64 `json:"num"`
TotalNum int64 `json:"total_num"`
Title string `json:"title"`
Price float64 `json:"price"`
}
type CartSizeItem {
Cm string `json:"cm"`
Inch string `json:"inch"`
}
//获取用户购物车订单详情
type CartOrderDetailReq {
Sn string `form:"sn"`
}
type CartOrderDetailRsp {
DeliveryMethod int64 `json:"delivery_method"`
AddressId int64 `json:"address_id"`
PayTime string `json:"pay_time"`
PayMethod int64 `json:"pay_method"`
PayStep int64 `json:"pay_step"`
Subtotal string `json:"subtotal"`
Total string `json:"total"`
Remaining string `json:"remaining"`
AddrList []*CartAddr `json:"addr_list"`
Items []*CartDetailItem `json:"items"`
}
type CartDetailItem {
Cover string `json:"cover"`
Pcs int64 `json:"pcs"`
Amount string `json:"amount"`
Option string `json:"option"`
Size string `json:"size"`
Name string `json:"name"`
}
type CartAddr {
Id int64 `json:"id"`
Name string `json:"name"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Mobile string `json:"mobile"`
Street string `json:"street"`
Suite string `json:"suite"`
City string `json:"city"`
State string `json:"state"`
ZipCode string `json:"zip_code"`
IsDefault int64 `json:"is_default"`
}
//变更发货方式和地址
type ChangeOrderMethodReq {
Sn string `json:"sn"`
DeliveryMethod int64 `json:"delivery_method , options=1|2"`
AddressId int64 `json:"address_id"`
PayMethod int64 `json:"pay_method"`
}
//创建购物车订单
type CreateOrderReq {
Form []OrderFormItem `json:"form"`
}
type OrderFormItem {
Id int64 `json:"id"`
Num int64 `json:"num"`
}
type CreateOrderRsp {
Sn string `json:"sn"`
}