Files

248 lines
6.9 KiB
Go
Raw Permalink Normal View History

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
}