修改订单创建

This commit is contained in:
JNG 2026-06-09 10:48:46 +08:00
parent d18a5243f2
commit 26ebd81bcf
6 changed files with 138 additions and 16 deletions

View File

@ -0,0 +1,18 @@
-- 为 bundle_order_records 表添加 order_type 字段
-- 订单类型: 1=套餐订单, 2=增值服务订单
ALTER TABLE bundle_order_records
ADD COLUMN order_type INT DEFAULT 1 COMMENT '订单类型 1:套餐订单 2:增值服务订单';
-- 为现有订单设置默认值(兼容性:现有订单都是套餐订单)
UPDATE bundle_order_records
SET order_type = 1
WHERE order_type IS NULL;
-- 添加索引以提高查询性能
CREATE INDEX idx_order_type ON bundle_order_records(order_type);
-- 说明:
-- 1. 默认值 1 确保向后兼容(现有订单都被视为套餐订单)
-- 2. 新的增值服务订单将使用 order_type = 2
-- 3. 索引加速按订单类型筛选的查询

View File

@ -455,7 +455,11 @@ func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonRespons
tx.Rollback()
}
}()
// 生成订单号和UUID
orderNo := utils.GetOrderNo()
mainOrderUUID := app.ModuleClients.SfNode.Generate().Base64()
// 增值订单默认先用后付(规则 2增值服务订单只有先用后付类型
addOrderMode := req.OrderMode
if addOrderMode == 0 {
@ -469,11 +473,47 @@ func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonRespons
if addOrderMode == model.OrderModePayLater && addContractTplType == 0 {
addContractTplType = model.ContractTplValueAddPayLater
}
// 计算总金额
var totalAmount float32
for _, i := range req.AddPriceOptionsList {
totalAmount += i.Amount
}
// 创建增值服务主订单记录
mainOrder := &model.BundleOrderRecords{
UUID: mainOrderUUID,
OrderNo: orderNo,
BundleUUID: req.BundleUuid, // 保留原套餐UUID用于追溯
CustomerID: req.CustomerID,
CustomerNum: req.CustomerNum,
CustomerName: req.CustomerName,
TotalAmount: totalAmount,
Amount: 0, // 增值服务订单不涉及套餐金额
SignContract: req.SignContract,
Signature: req.Signature,
SignedTime: req.SignedTime,
Status: model.BundleStatusSignedUnpaid, // 已签未支付
OrderMode: addOrderMode,
DueTime: req.DueTime,
PayLaterStatus: addPayLaterStatus,
ContractTplType: addContractTplType,
OrderType: model.OrderTypeValueAdd, // 标记为增值服务订单
ExpirationTime: req.ExpirationDate,
}
// 创建主订单
if err = tx.Create(mainOrder).Error; err != nil {
tx.Rollback()
return nil, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "创建增值服务主订单失败")
}
// 创建子订单记录
var childOrders []*model.BundleOrderValueAdd
for _, i := range req.AddPriceOptionsList {
childOrder := &model.BundleOrderValueAdd{
UUID: app.ModuleClients.SfNode.Generate().Base64(),
OrderUUID: req.OrderUUID, // 修正: 这里应使用主订单UUID
OrderUUID: mainOrderUUID, // 关联到新创建的增值服务主订单
CustomerID: req.CustomerID,
CustomerNum: req.CustomerNum,
CustomerName: req.CustomerName,
@ -497,16 +537,17 @@ func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonRespons
}
childOrders = append(childOrders, childOrder)
// 如果是类型5服务,更新主订单的过期时间
if i.ServiceType == 5 && req.ExpirationDate != "" {
// 如果是类型5服务(可用时长),更新原套餐订单的过期时间
if i.ServiceType == 5 && req.ExpirationDate != "" && req.OrderUUID != "" {
if err := tx.Model(&model.BundleOrderRecords{}).
Where("uuid = ?", req.BundleUuid).
Where("uuid = ?", req.OrderUUID).
Update("expiration_time", req.ExpirationDate).Error; err != nil {
tx.Rollback()
return nil, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "更新订单过期时间失败: ")
return nil, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "更新原套餐订单过期时间失败: ")
}
}
}
// 批量创建子订单(提高性能)
if err = tx.Model(&model.BundleOrderValueAdd{}).Create(childOrders).Error; err != nil {
tx.Rollback()
@ -520,7 +561,7 @@ func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonRespons
}
return &bundle.CommonResponse{
Uuid: req.BundleUuid,
Uuid: mainOrderUUID, // 返回新创建的增值服务主订单UUID
OrderNo: orderNo,
Msg: msg.SuccessCreateOrderInfo,
}, nil
@ -569,6 +610,9 @@ func OrderRecordsListV2(req *bundle.OrderRecordsRequestV2) (res *bundle.OrderRec
if req.PayLaterStatus != 0 {
modelObj = modelObj.Where("bundle_order_records.pay_later_status = ?", req.PayLaterStatus)
}
if req.OrderType != 0 {
modelObj = modelObj.Where("bundle_order_records.order_type = ?", req.OrderType)
}
err = modelObj.Count(&count).Error
if req.PageSize != 0 && req.Page != 0 {
modelObj = modelObj.Limit(int(req.PageSize)).Offset(int(req.Page-1) * int(req.PageSize))
@ -602,6 +646,7 @@ func OrderRecordsListV2(req *bundle.OrderRecordsRequestV2) (res *bundle.OrderRec
DueTime: record.DueTime,
PayLaterStatus: record.PayLaterStatus,
ContractTplType: record.ContractTplType,
OrderType: record.OrderType,
}
// 聚合子订单

View File

@ -117,6 +117,7 @@ func CreateOrderRecord(req *bundle.OrderCreateRecord) (res *bundle.CommonRespons
DueTime: req.DueTime,
PayLaterStatus: payLaterStatus,
ContractTplType: req.ContractTplType,
OrderType: model.OrderTypeBundle, // 套餐订单
}
res, err = dao.CreateOrderRecord(orderRecord)
return
@ -190,6 +191,17 @@ func PackagePriceAndTime(req *bundle.OrderRecord) (res *bundle.PackagePriceAndTi
}
func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonResponse, err error) {
res = new(bundle.CommonResponse)
// 增值订单下单前置校验规则5增值订单不受套餐过期限制可无限续杯
if eligibility, e := CheckOrderEligibility(&bundle.CheckOrderEligibilityRequest{
CustomerID: req.CustomerID,
OrderKind: model.OrderKindValueAdd,
OrderMode: req.OrderMode,
}); e != nil {
return nil, e
} else if !eligibility.Allow {
res.Msg = eligibility.Msg
return res, errors.New(eligibility.Reason)
}
res, err = dao.CreateOrderAddRecord(req)
return
}

View File

@ -52,6 +52,7 @@ type BundleOrderRecords struct {
DueTime string `gorm:"column:due_time;type:varchar(64);comment:先用后付到期应付时间" json:"dueTime"`
PayLaterStatus int32 `gorm:"column:pay_later_status;type:int;default:0;comment:先用后付状态 0:无 1:待付款 2:已付款 3:逾期未付;index:idx_paylater_status" json:"payLaterStatus"`
ContractTplType int32 `gorm:"column:contract_tpl_type;type:int;default:0;comment:合同模板类型 1:套餐普通 2:套餐先用后付 3:增值先用后付" json:"contractTplType"`
OrderType int32 `gorm:"column:order_type;type:int;default:1;comment:订单类型 1:套餐订单 2:增值服务订单" json:"orderType"`
}
type BundleOrderValueAdd struct {
gorm.Model
@ -159,3 +160,9 @@ const (
OrderGateReasonBundleActiveExists = "BUNDLE_ACTIVE_EXISTS"
OrderGateReasonValueAddLocked = "VALUE_ADD_OVERDUE_LOCKED"
)
// 订单类型
const (
OrderTypeBundle int32 = 1 // 套餐订单
OrderTypeValueAdd int32 = 2 // 增值服务订单
)

View File

@ -272,6 +272,7 @@ message OrderCreateRecord{
string dueTime = 27 [json_name = "dueTime"]; // ()
int32 payLaterStatus = 28 [json_name = "payLaterStatus"]; // 0: 1: 2: 3:
int32 contractTplType = 29 [json_name = "contractTplType"]; // 1: 2: 3:
int32 orderType = 30 [json_name = "orderType"]; // 1: 2:
}
message OrderCreateAddRecord{
int32 serviceType = 1 [json_name = "serviceType"];
@ -312,6 +313,7 @@ message OrderRecordsRequestV2{
uint64 purchaseType = 17;
int32 orderMode = 18 [json_name = "orderMode"]; // 1: 2:
int32 payLaterStatus = 19 [json_name = "payLaterStatus"]; // 0: 1: 2: 3:
int32 orderType = 20 [json_name = "orderType"]; // 1: 2:
}
message OrderRecordsResponseV2{
repeated OrderBundleRecordInfo bundleInfo = 1;
@ -340,6 +342,7 @@ message OrderBundleRecordInfo{
string dueTime = 18 [json_name = "dueTime"]; //
int32 payLaterStatus = 19 [json_name = "payLaterStatus"]; // 0: 1: 2: 3:
int32 contractTplType = 20 [json_name = "contractTplType"]; // 1: 2:
int32 orderType = 21 [json_name = "orderType"]; // 1: 2:
}
message OrderAddBundleRecordInfo{
string orderAddNo = 1;
@ -536,6 +539,7 @@ message OrderRecord {
string dueTime = 44 [json_name = "dueTime"]; //
int32 payLaterStatus = 45 [json_name = "payLaterStatus"]; // 0: 1: 2: 3:
int32 contractTplType = 46 [json_name = "contractTplType"]; //
int32 orderType = 47 [json_name = "orderType"]; // 1: 2:
}
//

View File

@ -946,6 +946,7 @@ type OrderCreateRecord struct {
DueTime string `protobuf:"bytes,27,opt,name=dueTime,proto3" json:"dueTime"` // 先用后付到期应付时间(北京时间)
PayLaterStatus int32 `protobuf:"varint,28,opt,name=payLaterStatus,proto3" json:"payLaterStatus"` // 先用后付状态 0:无 1:待付款 2:已付款 3:逾期未付
ContractTplType int32 `protobuf:"varint,29,opt,name=contractTplType,proto3" json:"contractTplType"` // 合同模板类型 1:套餐普通 2:套餐先用后付 3:增值先用后付
OrderType int32 `protobuf:"varint,30,opt,name=orderType,proto3" json:"orderType"` // 订单类型 1:套餐订单 2:增值服务订单
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -1183,6 +1184,13 @@ func (x *OrderCreateRecord) GetContractTplType() int32 {
return 0
}
func (x *OrderCreateRecord) GetOrderType() int32 {
if x != nil {
return x.OrderType
}
return 0
}
type OrderCreateAddRecord struct {
state protoimpl.MessageState `protogen:"open.v1"`
ServiceType int32 `protobuf:"varint,1,opt,name=serviceType,proto3" json:"serviceType"`
@ -1376,6 +1384,7 @@ type OrderRecordsRequestV2 struct {
PurchaseType uint64 `protobuf:"varint,17,opt,name=purchaseType,proto3" json:"purchaseType"`
OrderMode int32 `protobuf:"varint,18,opt,name=orderMode,proto3" json:"orderMode"` // 订单模式筛选 1:普通 2:先用后付
PayLaterStatus int32 `protobuf:"varint,19,opt,name=payLaterStatus,proto3" json:"payLaterStatus"` // 先用后付状态筛选 0:无 1:待付款 2:已付款 3:逾期未付
OrderType int32 `protobuf:"varint,20,opt,name=orderType,proto3" json:"orderType"` // 订单类型筛选 1:套餐订单 2:增值服务订单
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -1543,6 +1552,13 @@ func (x *OrderRecordsRequestV2) GetPayLaterStatus() int32 {
return 0
}
func (x *OrderRecordsRequestV2) GetOrderType() int32 {
if x != nil {
return x.OrderType
}
return 0
}
type OrderRecordsResponseV2 struct {
state protoimpl.MessageState `protogen:"open.v1"`
BundleInfo []*OrderBundleRecordInfo `protobuf:"bytes,1,rep,name=bundleInfo,proto3" json:"bundleInfo"`
@ -1633,6 +1649,7 @@ type OrderBundleRecordInfo struct {
DueTime string `protobuf:"bytes,18,opt,name=dueTime,proto3" json:"dueTime"` // 先用后付到期应付时间
PayLaterStatus int32 `protobuf:"varint,19,opt,name=payLaterStatus,proto3" json:"payLaterStatus"` // 先用后付状态 0:无 1:待付款 2:已付款 3:逾期未付
ContractTplType int32 `protobuf:"varint,20,opt,name=contractTplType,proto3" json:"contractTplType"` // 合同模板类型 1:套餐普通 2:套餐先用后付
OrderType int32 `protobuf:"varint,21,opt,name=orderType,proto3" json:"orderType"` // 订单类型 1:套餐订单 2:增值服务订单
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -1807,6 +1824,13 @@ func (x *OrderBundleRecordInfo) GetContractTplType() int32 {
return 0
}
func (x *OrderBundleRecordInfo) GetOrderType() int32 {
if x != nil {
return x.OrderType
}
return 0
}
type OrderAddBundleRecordInfo struct {
state protoimpl.MessageState `protogen:"open.v1"`
OrderAddNo string `protobuf:"bytes,1,opt,name=orderAddNo,proto3" json:"orderAddNo"`
@ -3257,6 +3281,7 @@ type OrderRecord struct {
DueTime string `protobuf:"bytes,44,opt,name=dueTime,proto3" json:"dueTime"` // 先用后付到期时间
PayLaterStatus int32 `protobuf:"varint,45,opt,name=payLaterStatus,proto3" json:"payLaterStatus"` // 先用后付状态 0:无 1:待付款 2:已付款 3:逾期未付
ContractTplType int32 `protobuf:"varint,46,opt,name=contractTplType,proto3" json:"contractTplType"` // 合同模板类型
OrderType int32 `protobuf:"varint,47,opt,name=orderType,proto3" json:"orderType"` // 订单类型 1:套餐订单 2:增值服务订单
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -3613,6 +3638,13 @@ func (x *OrderRecord) GetContractTplType() int32 {
return 0
}
func (x *OrderRecord) GetOrderType() int32 {
if x != nil {
return x.OrderType
}
return 0
}
// 下单前置校验
type CheckOrderEligibilityRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
@ -21081,7 +21113,7 @@ const file_pb_bundle_proto_rawDesc = "" +
"\buserName\x18\n" +
" \x01(\tR\buserName\x124\n" +
"\x15competitiveAdditional\x18\v \x01(\x05R\x15competitiveAdditional\x12\"\n" +
"\fpurchaseType\x18\f \x01(\x05R\fpurchaseType\"\xdd\a\n" +
"\fpurchaseType\x18\f \x01(\x05R\fpurchaseType\"\xfb\a\n" +
"\x11OrderCreateRecord\x12\x1e\n" +
"\n" +
"bundleUuid\x18\x01 \x01(\tR\n" +
@ -21126,7 +21158,8 @@ const file_pb_bundle_proto_rawDesc = "" +
"\torderMode\x18\x1a \x01(\x05R\torderMode\x12\x18\n" +
"\adueTime\x18\x1b \x01(\tR\adueTime\x12&\n" +
"\x0epayLaterStatus\x18\x1c \x01(\x05R\x0epayLaterStatus\x12(\n" +
"\x0fcontractTplType\x18\x1d \x01(\x05R\x0fcontractTplType\"\x9c\x04\n" +
"\x0fcontractTplType\x18\x1d \x01(\x05R\x0fcontractTplType\x12\x1c\n" +
"\torderType\x18\x1e \x01(\x05R\torderType\"\x9c\x04\n" +
"\x14OrderCreateAddRecord\x12 \n" +
"\vserviceType\x18\x01 \x01(\x05R\vserviceType\x12\x1a\n" +
"\bvalueUid\x18\x02 \x01(\tR\bvalueUid\x12\"\n" +
@ -21149,7 +21182,7 @@ const file_pb_bundle_proto_rawDesc = "" +
"\torderMode\x18\x0e \x01(\x05R\torderMode\x12\x18\n" +
"\adueTime\x18\x0f \x01(\tR\adueTime\x12&\n" +
"\x0epayLaterStatus\x18\x10 \x01(\x05R\x0epayLaterStatus\x12(\n" +
"\x0fcontractTplType\x18\x11 \x01(\x05R\x0fcontractTplType\"\xb7\x05\n" +
"\x0fcontractTplType\x18\x11 \x01(\x05R\x0fcontractTplType\"\xd5\x05\n" +
"\x15OrderRecordsRequestV2\x12\"\n" +
"\fcustomerName\x18\x01 \x01(\tR\fcustomerName\x12\x16\n" +
"\x06telNum\x18\x02 \x01(\tR\x06telNum\x12\x1e\n" +
@ -21174,14 +21207,15 @@ const file_pb_bundle_proto_rawDesc = "" +
"\fbundlePayEnd\x18\x10 \x01(\tR\fbundlePayEnd\x12\"\n" +
"\fpurchaseType\x18\x11 \x01(\x04R\fpurchaseType\x12\x1c\n" +
"\torderMode\x18\x12 \x01(\x05R\torderMode\x12&\n" +
"\x0epayLaterStatus\x18\x13 \x01(\x05R\x0epayLaterStatus\"\x9d\x01\n" +
"\x0epayLaterStatus\x18\x13 \x01(\x05R\x0epayLaterStatus\x12\x1c\n" +
"\torderType\x18\x14 \x01(\x05R\torderType\"\x9d\x01\n" +
"\x16OrderRecordsResponseV2\x12=\n" +
"\n" +
"bundleInfo\x18\x01 \x03(\v2\x1d.bundle.OrderBundleRecordInfoR\n" +
"bundleInfo\x12\x12\n" +
"\x04page\x18\x02 \x01(\x05R\x04page\x12\x1a\n" +
"\bpageSize\x18\x03 \x01(\x05R\bpageSize\x12\x14\n" +
"\x05total\x18\x04 \x01(\x05R\x05total\"\xc1\x05\n" +
"\x05total\x18\x04 \x01(\x05R\x05total\"\xdf\x05\n" +
"\x15OrderBundleRecordInfo\x12\x18\n" +
"\aorderNo\x18\x01 \x01(\tR\aorderNo\x12\x1e\n" +
"\n" +
@ -21207,7 +21241,8 @@ const file_pb_bundle_proto_rawDesc = "" +
"\torderMode\x18\x11 \x01(\x05R\torderMode\x12\x18\n" +
"\adueTime\x18\x12 \x01(\tR\adueTime\x12&\n" +
"\x0epayLaterStatus\x18\x13 \x01(\x05R\x0epayLaterStatus\x12(\n" +
"\x0fcontractTplType\x18\x14 \x01(\x05R\x0fcontractTplType\"\xe4\x04\n" +
"\x0fcontractTplType\x18\x14 \x01(\x05R\x0fcontractTplType\x12\x1c\n" +
"\torderType\x18\x15 \x01(\x05R\torderType\"\xe4\x04\n" +
"\x18OrderAddBundleRecordInfo\x12\x1e\n" +
"\n" +
"orderAddNo\x18\x01 \x01(\tR\n" +
@ -21343,7 +21378,7 @@ const file_pb_bundle_proto_rawDesc = "" +
"\x03msg\x18\x02 \x01(\tR\x03msg\"Y\n" +
"\x16BundleDetailResponseV2\x12-\n" +
"\x06bundle\x18\x01 \x01(\v2\x15.bundle.BundleProfileR\x06bundle\x12\x10\n" +
"\x03msg\x18\x02 \x01(\tR\x03msg\"\xa2\r\n" +
"\x03msg\x18\x02 \x01(\tR\x03msg\"\xc0\r\n" +
"\vOrderRecord\x12\x12\n" +
"\x04uuid\x18\x01 \x01(\tR\x04uuid\x12\x1e\n" +
"\n" +
@ -21405,7 +21440,8 @@ const file_pb_bundle_proto_rawDesc = "" +
"\torderMode\x18+ \x01(\x05R\torderMode\x12\x18\n" +
"\adueTime\x18, \x01(\tR\adueTime\x12&\n" +
"\x0epayLaterStatus\x18- \x01(\x05R\x0epayLaterStatus\x12(\n" +
"\x0fcontractTplType\x18. \x01(\x05R\x0fcontractTplType\"z\n" +
"\x0fcontractTplType\x18. \x01(\x05R\x0fcontractTplType\x12\x1c\n" +
"\torderType\x18/ \x01(\x05R\torderType\"z\n" +
"\x1cCheckOrderEligibilityRequest\x12\x1e\n" +
"\n" +
"customerID\x18\x01 \x01(\tR\n" +