refactor: reorganize modules and add Linux build tooling

This commit is contained in:
2026-08-09 12:41:08 +08:00
parent 86024fa81d
commit 5cc5fd92ed
1461 changed files with 4054 additions and 4724 deletions

View File

@@ -0,0 +1,60 @@
package summary
import (
"context"
"time"
"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"
)
// 取消订单
func Cancel(ctx context.Context, in *pb.CancelRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
var (
summary = new(models.OrderSummary)
)
err = models.DBService.Where("order_no = ?", in.OrderNo).First(&summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
if summary.Status == 1 {
values := &models.OrderSummary{
CouponIdentity: "",
CouponAmount: 0.00,
}
values.Status = -1
err := models.DBService.Where("order_no = ?", in.OrderNo).Updates(values).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
err = models.DBService.Model(&models.OrderCoupon{}).Where("identity=?", summary.CouponIdentity).Update("status", 2).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
}
return &pb.StatusReply{
Code: 0,
Identity: summary.Identity,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,37 @@
package summary
import (
"context"
"time"
"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"
)
// 检测是否有未确认及付款的订单
func Check(ctx context.Context, in *pb.Empty) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
var (
summary = new(models.OrderSummary)
)
err = models.DBService.Where("passport_id = ?", auth.ID).First(&summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Identity: summary.OrderNo,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,84 @@
package summary
import (
"context"
"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"
)
// 确认订单,物流,优惠卷等其它信息
func Confirm(ctx context.Context, in *pb.ConfirmRequest) (reply *pb.ConfirmReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
var (
logisFee int64 = 0
couponAmount int64 = 0
summary = new(models.OrderSummary)
coupon = new(models.OrderCoupon)
)
err = models.DBService.Where("order_no = ?", in.OrderNo).First(&summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
if in.AddressIdentity != "" {
/*
err = models.DBService.Where("id=?", in.AddressId).First(&address).Error
if err == nil {
summary.Address = address.Detail
summary.County = address.Country
summary.Province = address.Province
summary.City = address.City
summary.Area = address.Area
summary.Contact = address.Contact
summary.Phone = address.Phone
logisFee = GetLogisticsFee(summary.TotalPrice, address.Province)
}
*/
}
if logisFee > 0 {
summary.TotalPrice = summary.TotalPrice + logisFee
}
if in.CouponIdentity != "" {
err = models.DBService.Where("identity=?", in.CouponIdentity).First(&coupon).Error
if err == nil {
if coupon.Status == 2 {
models.DBService.Model(&models.OrderCoupon{}).Where("identity=?", in.CouponIdentity).Update("status", 3)
couponAmount = coupon.Amount
} else {
printer.Error(err.Error())
return nil, errcode.ErrUnavailable
}
} else {
printer.Error(err.Error())
return nil, errcode.ErrRecordNotFound
}
}
if couponAmount > 0 {
summary.TotalPrice = summary.TotalPrice + couponAmount
}
summary.Status = 1
err = models.DBService.Where("order_no = ?", in.OrderNo).Updates(summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.ConfirmReply{
TotalPrice: summary.TotalPrice,
}, nil
}

View File

@@ -0,0 +1,35 @@
package summary
import (
"context"
"bsm/full/module/ec/order/internal/logic/common"
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"
)
// 获取一个订单的详情数据
func Get(ctx context.Context, in *pb.IdentRequest) (reply *pb.SummaryGetReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
summary, err := common.GetOrderSummaryByIdentity(in.Identity)
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.SummaryGetReply{
Summary: summary,
}, nil
}

View File

@@ -0,0 +1,70 @@
package summary
import (
"context"
"errors"
"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"
"gorm.io/gorm"
)
// 根据不同的类型获取我的订单列表
func List(ctx context.Context, in *pb.SummaryListRequest) (reply *pb.SummaryListReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
var (
page = 1
size = 50
payType int32 = 0 // 支付方式
orderStatus int32 = 0 // 订单状态
cnt int64 = 0
)
if in.PayType != 0 {
payType = in.PayType
}
if in.OrderStatus != 0 {
orderStatus = in.OrderStatus
}
if in.GetPageNo() > 0 {
page = int(in.PageNo)
}
if in.GetPageSize() > 0 {
size = int(in.PageSize)
}
orderList := make([]*models.OrderSummary, 0)
tx := models.DBService.Model(&models.OrderSummary{}).Preload("OrderDetails").Where("passport_identity = ?", auth.Identity)
if payType != 0 {
tx = tx.Where("pay_type = ?", payType)
}
if orderStatus != 0 {
tx = tx.Where("status = ?", orderStatus)
}
err = tx.Order("created_at desc").Count(&cnt).Limit(size).Offset((page - 1) * size).Find(&orderList).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errcode.ErrRecordNotFound
}
printer.Error(err.Error())
return nil, errcode.ErrDB
}
data := common.ListModelToReply(orderList)
return &pb.SummaryListReply{
Count: int32(cnt),
Data: data,
}, nil
}

View File

@@ -0,0 +1,165 @@
package summary
import (
"context"
"errors"
"strings"
"time"
"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/utils"
)
// 快速创建一个店铺订单
func QuickCreateByProduct(ctx context.Context, in *pb.QuickCreateByProductRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, &service.ParseOptions{RoleValue: "Mall_Admin"})
if err != nil {
return nil, err
}
// 验证输入参数是否有效。
if in.GetProductIdentity() == "" || in.GetNumber() == 0 || in.GetStoreIdentity() == "" || in.GetAddressIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
// 查询商店信息以确保其存在且状态为启用。
store := map[string]any{}
err = models.DBService.Table("mall_store").Take(&store, "identity=?", in.StoreIdentity).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
if store["status"].(int16) != 1 {
return nil, errcode.ErrUnknown
}
// 查询产品信息以确保其存在且状态为启用。
product := map[string]any{}
var pi string = strings.ToLower(in.ProductIdentity)
if pi == "gas_by_kg" || pi == "gas_by_bottle" {
err = models.DBService.Table("mall_product").Take(&product, "store_identity=? and serial_id=?", in.StoreIdentity, pi).Error
} else {
err = models.DBService.Table("mall_product").Take(&product, "identity=?", in.ProductIdentity).Error
}
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
if product["status"].(int32) != 1 {
return nil, errcode.ErrUnknown
}
// 查询产品规格信息
spec := map[string]any{}
err = models.DBService.Table("mall_product_spec").Take(&spec, "product_identity=?", in.ProductIdentity).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
// 查询地址信息以确保其存在。
address := map[string]any{}
err = models.DBService.Table("address_library").Take(&address, "identity=?", in.AddressIdentity).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
// // 查询配送员信息
// member := map[string]any{}
// err = models.DBService.Table("delivery_member").Take(&member, "identity=?", in.MemberIdentity).Error
// if err != nil {
// printer.Error(err.Error())
// if errors.Is(err, models.ErrNotFound) {
// return nil, errcode.ErrRecordNotFound
// }
// return nil, errcode.ErrDB
// }
// 生成订单号。
orderNo := common.CreateOrderNo()
// 计算交易价格并构建订单摘要对象。
TransPrice := (int64(in.Number) * spec["price"].(int64))
summary := &models.OrderSummary{
StoreID: uint(store["id"].(int64)),
StoreIdentity: in.StoreIdentity,
OrderNo: orderNo,
PartnerID: in.PartnerId,
TransPrice: TransPrice,
TotalPrice: TransPrice,
Args: in.Args,
AddressIdentity: in.AddressIdentity,
Province: address["province"].(string),
City: address["city"].(string),
Area: address["area"].(string),
Address: address["detail"].(string),
Contact: address["contact"].(string),
Phone: address["phone"].(string),
DeliveryTime: in.GetDeliveryTime(),
// DeliveryIdentity: member["identity"].(string),
DeliveryAddress: in.DeliveryAddress,
}
summary.Identity = utils.UUID()
summary.PassportID = auth.ID
summary.PassportIdentity = auth.Identity
summary.Status = 1
// 从产品信息中提取单价、ID等详情并构建订单详情对象。
unit_price := product["sales_price"].(int64)
productID := product["id"].(int64)
details := &models.OrderDetails{
Type: 1,
ProductID: productID,
ProductIdentity: product["identity"].(string),
SpecID: spec["id"].(int64),
OrderNo: orderNo,
Title: product["title"].(string),
CoverImage: product["cover_image"].(string),
UnitPrice: unit_price,
Number: in.Number,
ProductArgs: product["args"].(string),
SummaryIdentity: summary.Identity,
SpecTitle: spec["title"].(string),
SpecNo: spec["serial_number"].(string),
GasType: product["gas_types"].(int32),
SupplyId: product["supply_id"].(int64),
}
// 将订单摘要和订单详情记录到数据库。
err = models.DBService.Create(summary).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
err = models.DBService.Create(details).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,38 @@
package summary
import (
"context"
"errors"
"time"
"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"
)
// 模拟支付
func SimulatePay(ctx context.Context, in *pb.SimulatePayRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
err = models.DBService.Model(&models.OrderSummary{}).Where("identity in ?", in.Identity).Updates(models.OrderSummary{Status: 2, PayTime: time.Now(), PayType: 4, PayRemark: "支付备注", PayTradeNo: "Pay12371937812897", PayAmount: 10000000}).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,42 @@
package summary
import (
"context"
"errors"
"time"
"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"
)
// 模拟收货
func SimulateReceiving(ctx context.Context, in *pb.IdentRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
err = models.DBService.Model(&models.OrderSummary{}).Where("identity = ?", in.Identity).Update("status", 4).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,41 @@
package summary
import (
"context"
"errors"
"time"
"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"
)
// 模拟发货
func SimulateShipments(ctx context.Context, in *pb.SimulateShipmentsRequest) (reply *pb.StatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
if in.GetMemberIdentity() == "" {
return nil, errcode.ErrInvalidArgument
}
err = models.DBService.Where("identity = ?", in.Identity).Updates(&models.OrderSummary{Status: 3, DeliveryIdentity: in.MemberIdentity}).Error
if err != nil {
printer.Error(err.Error())
if errors.Is(err, models.ErrNotFound) {
return nil, errcode.ErrRecordNotFound
}
return nil, errcode.ErrDB
}
return &pb.StatusReply{
Code: 0,
Message: "OK",
Timeseq: time.Now().UnixNano(),
}, nil
}

View File

@@ -0,0 +1,245 @@
package summary
import (
"context"
"errors"
"log"
"strings"
"time"
"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.StatusReply, 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 = models.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 = models.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 = models.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 = models.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 := models.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 = models.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.StatusReply{
Code: 0,
Identity: firstOrderNo,
Message: strings.Join(keys, ","),
Timeseq: time.Now().UnixNano(),
}, nil
}