Files
full/module/ec/order/internal/logic/summary/submit.go

248 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package summary
import (
"context"
"errors"
"log"
"strings"
"time"
"bsm/full/module/ec/order/internal/impl"
"bsm/full/module/ec/order/internal/logic/common"
"bsm/full/module/ec/order/internal/models"
pb "bsm/full/module/ec/order/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils"
"gorm.io/gorm"
)
// 将购物车的数据提交生成订单
func Submit(ctx context.Context, in *pb.SubmitRequest) (reply *pb.OrderStatusReply, err error) {
// parse authorization meta.
RoleValve := &service.ParseOptions{RoleValue: "Mall_Admin"}
if in.GetAddress() != nil {
RoleValve = nil
}
auth, err := service.ParseMetaCtx(ctx, RoleValve)
if err != nil {
return nil, err
}
var (
cart = make([]*models.OrderCart, 0)
details = make([]*models.OrderDetails, 0)
summary = make([]*models.OrderSummary, 0)
keys = make([]string, 0)
address = models.OrderAddress{}
StoreId uint = 0
)
// 获取购物车内数据信息
err = impl.DBService.Where("passport_identity = ?", auth.Identity).Find(&cart).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
// 获取地址信息
if in.GetAddress() != nil {
address = models.OrderAddress{
Country: in.Address.Country,
Province: in.Address.Province,
City: in.Address.City,
Detail: in.Address.Detail,
Contact: in.Address.Contact,
Phone: in.Address.Phone,
Area: in.Address.Area,
Email: in.Address.Email,
ZipCode: in.Address.ZipCode,
}
} else {
err = impl.DBService.Table("address_library").Where("identity = ?", in.AddressIdentity).Find(&address).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
}
// 按店铺分组购物车商品
storeGroups := make(map[string][]*models.OrderCart)
for k, item := range cart {
product := models.Product{}
err = impl.DBService.Select("store_identity").Table("mall_product").Where("id = ?", item.ProductID).First(&product).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
if k == 0 {
StoreId = product.StoreId
}
storeGroups[product.StoreIdentity] = append(storeGroups[product.StoreIdentity], item)
}
// 处理每个店铺
for StoreIdentity, items := range storeGroups {
var storeTotal int64 = 0
var storeDetails []*models.OrderDetails
//订单号2位年份6位随机数共18位
summaryIdentity := utils.UUID()
orderNo := common.CreateOrderNo()
// 处理店铺内所有商品
for _, item := range items {
product := models.Product{}
spec := models.Spec{}
// 获取产品信息
err = impl.DBService.Select("title,cover_image,cost_price,supply_id,args,gas_types").Table("mall_product").
Where("id = ?", item.ProductID).First(&product).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
// 获取规格信息
err := impl.DBService.Select("title,serial_number,price").Table("mall_product_spec").
Where("id = ?", item.SpecID).First(&spec).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
// 计算商品总价
itemTotal := int64(item.Number) * spec.Price
storeTotal += itemTotal
// 添加到订单详情
storeDetails = append(storeDetails, &models.OrderDetails{
Type: 1,
ProductID: item.ProductID,
ProductIdentity: item.ProductIdentity,
SpecID: item.SpecID,
OrderNo: orderNo,
Title: product.Title,
CoverImage: product.CoverImage,
UnitPrice: spec.Price,
SalesPrice: spec.Price,
Number: item.Number,
ProductArgs: item.ProductArgs,
SummaryIdentity: summaryIdentity,
SpecTitle: spec.Title,
SpecNo: spec.SerialNumber,
GasType: int32(product.GasTypes),
SupplyId: product.SupplyId,
TotalPrice: int64(item.Number) * spec.Price,
})
}
// 创建店铺订单摘要
summary = append(summary, &models.OrderSummary{
OrderNo: orderNo,
Std_Identity: types.Std_Identity{Identity: summaryIdentity},
PartnerID: in.PartnerId,
TransPrice: storeTotal,
TotalPrice: storeTotal,
StoreID: StoreId,
StoreIdentity: StoreIdentity,
LogisticsFee: 0,
Remark: "",
AddressIdentity: in.AddressIdentity,
County: address.Country,
Province: address.Province,
City: address.City,
Area: address.Area,
Address: address.Detail,
Contact: address.Contact,
Phone: address.Phone,
Std_Passport: types.Std_Passport{PassportID: auth.ID, PassportIdentity: auth.Identity},
Status: 1,
})
// 添加到总详情列表
details = append(details, storeDetails...)
keys = append(keys, StoreIdentity)
}
err = impl.DBService.Transaction(func(tx *gorm.DB) error {
// 1. 创建订单摘要
if err := tx.Create(summary).Error; err != nil {
printer.Error(err.Error())
return err
}
// 2. 创建订单详情
if err := tx.Model(&models.OrderDetails{}).CreateInBatches(details, len(details)).Error; err != nil {
printer.Error(err.Error())
return err
}
// 3. 扣减库存
for _, detail := range details {
if detail.Number > 0 {
var stock int32
result := tx.Table("mall_product_spec").Select("stock").Where("id = ?", detail.SpecID).Scan(&stock)
if result.Error != nil || stock < detail.Number {
log.Printf("Insufficient stock or spec does not exist: %v", result.Error)
return errors.New("库存不足或规格不存在")
}
updateErr := tx.Table("mall_product_spec").
Where("id = ? AND stock >= ?", detail.SpecID, detail.Number).
UpdateColumn("stock", gorm.Expr("stock - ?", detail.Number)).
Error
if updateErr != nil {
printer.Error(updateErr.Error())
return updateErr
}
}
}
// 4. 清空购物车
if err := tx.Where("passport_identity = ?", auth.Identity).
Delete(&models.OrderCart{}).Error; err != nil {
printer.Error(err.Error())
return err
}
return nil
})
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
// 返回第一个订单号作为标识
firstOrderNo := ""
if len(summary) > 0 {
firstOrderNo = summary[0].OrderNo
}
return &pb.OrderStatusReply{
Code: 0,
Identity: firstOrderNo,
Message: strings.Join(keys, ","),
Timeseq: time.Now().UnixNano(),
}, nil
}