package dao import ( "encoding/json" "gorm.io/gorm" "micro-bundle/internal/model" "micro-bundle/pb/bundle" "micro-bundle/pkg/app" commonErr "micro-bundle/pkg/err" "micro-bundle/pkg/msg" "micro-bundle/pkg/utils" "time" ) func CreateOrderRecord(orderRecord *model.BundleOrderRecords, req *bundle.OrderRecord) (res *bundle.CommonResponse, err error) { res = new(bundle.CommonResponse) bundleInfo := new(model.BundleProfile) // 生成UUID和订单号 orderRecord.UUID = app.ModuleClients.SfNode.Generate().Base64() orderRecord.OrderNo = utils.GetOrderNo() // 开启事务 tx := app.ModuleClients.BundleDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 查询套餐主表并预加载 err = tx.Model(&model.BundleProfile{}). Where("uuid = ?", orderRecord.BundleUUID). Preload("BundleToValueAddService"). Preload("BundleProfileLang", "language = ?", req.Language). First(&bundleInfo).Error if err != nil { tx.Rollback() res.Msg = msg.ErrorBundleNotFound return res, commonErr.ReturnError(err, msg.ErrorBundleNotFound, "查询Bundle信息失败: ") } // 填充BundleCommonJson字段 if bundleJson, e := json.Marshal(bundleInfo); e == nil { orderRecord.BundleCommonJson = bundleJson } else { tx.Rollback() res.Msg = msg.ErrorDataConvert return res, commonErr.ReturnError(e, msg.ErrorDataConvert, "Bundle信息转换失败: ") } // 创建主订单 if err = tx.Model(&model.BundleOrderRecords{}).Create(orderRecord).Error; err != nil { tx.Rollback() res.Msg = msg.ErrorCreateOrderInfo return res, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "创建订单信息失败: ") } var ( childOrders []*model.BundleOrderValueAdd valueAddAmount float64 expirationTime = "9999-12-31" ) for _, service := range bundleInfo.BundleToValueAddService { amount, info, num, day, e := calculateAmount(service.ValueUid, req) if e != nil { tx.Rollback() res.Msg = msg.ErrorDataConvert return res, commonErr.ReturnError(e, msg.ErrorDataConvert, "子订单金额计算失败: ") } if day != "" { expirationTime = day } valueAddAmount = valueAddAmount + amount childOrder := &model.BundleOrderValueAdd{ UUID: app.ModuleClients.SfNode.Generate().Base64(), OrderUUID: orderRecord.UUID, // 修正: 这里应使用主订单UUID CustomerID: orderRecord.CustomerID, CustomerNum: orderRecord.CustomerNum, CustomerName: orderRecord.CustomerName, ServiceType: info.ServiceType, CurrencyType: info.PriceType, Amount: amount, OrderNo: orderRecord.OrderNo, Num: num, Unit: info.Unit, ValueAddUUID: service.ValueUid, Source: 1, PaymentStatus: 1, SignContract: orderRecord.SignContract, Signature: orderRecord.Signature, SignedTime: orderRecord.SignedTime, } childOrders = append(childOrders, childOrder) } // 批量创建子订单(提高性能) if err = tx.Model(&model.BundleOrderValueAdd{}).Create(childOrders).Error; err != nil { tx.Rollback() return res, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "批量创建子订单失败") } // 更新总金额 updateData := map[string]interface{}{ "total_amount": gorm.Expr("total_amount + ?", valueAddAmount), "updated_at": time.Now(), "expiration_time": expirationTime, } if err = tx.Model(&model.BundleOrderRecords{}). Where("uuid = ?", orderRecord.UUID). Updates(updateData).Error; err != nil { tx.Rollback() return res, commonErr.ReturnError(err, msg.ErrorUpdateOrderInfo, "更新订单总金额失败") } // 提交事务 if err = tx.Commit().Error; err != nil { res.Msg = msg.ErrorCommitTransaction return res, commonErr.ReturnError(err, msg.ErrorCommitTransaction, "提交事务失败: ") } res.Uuid = orderRecord.UUID res.OrderNo = orderRecord.OrderNo res.Msg = msg.SuccessCreateOrderInfo return } // calculateAmount 计算子订单金额 func calculateAmount(valueUid string, req *bundle.OrderRecord) (amount float64, valueAddServiceLang *model.ValueAddServiceLang, num int32, expirationDay string, err error) { err = app.ModuleClients.BundleDB. Where("uuid = ? AND language = ?", valueUid, req.Language). First(&valueAddServiceLang).Error if err != nil { return } for _, opt := range valueAddServiceLang.Options { for _, p := range req.PriceOptionsInfo { if p.ValueUid == valueUid && opt.Id == p.Id { num = opt.Num if valueAddServiceLang.PriceMode == 1 { amount = float64(float32(opt.Num) * opt.Price) } else if valueAddServiceLang.PriceMode == 2 { amount = float64(opt.Price) } } } // 计算过期时间 if valueAddServiceLang.ServiceType == 5 { expirationDay = calculateExpirationDay(opt.Num, valueAddServiceLang.Unit) } } return } // calculateExpirationDay 计算到期日 func calculateExpirationDay(num int32, unit string) string { now := time.Now() switch unit { case "天": return now.AddDate(0, 0, int(num)).Format("2006-01-02") case "月": return now.AddDate(0, int(num), 0).Format("2006-01-02") case "年": return now.AddDate(int(num), 0, 0).Format("2006-01-02") default: return "" } } func UpdateOrderRecord(orderRecord *model.BundleOrderRecords) (res *bundle.CommonResponse, err error) { res = new(bundle.CommonResponse) err = app.ModuleClients.BundleDB.Model(&model.BundleOrderRecords{}).Where("uuid = ?", orderRecord.UUID).Updates(orderRecord).Error if err != nil { res.Msg = msg.ErrorUpdateOrderInfo return res, commonErr.ReturnError(err, msg.ErrorUpdateOrderInfo, "更新订单信息失败: ") } res.Uuid = orderRecord.UUID res.Msg = msg.SuccessUpdateOrderInfo return } func UpdateOrderRecordByOrderNO(orderRecord *model.BundleOrderRecords) (res *bundle.CommonResponse, err error) { res = new(bundle.CommonResponse) // Step 1: 先更新子订单(增值服务)的支付状态 valueAdd := &model.BundleOrderValueAdd{ PaymentStatus: int(orderRecord.Status), PaymentTime: orderRecord.PayTime, } err = app.ModuleClients.BundleDB.Model(&model.BundleOrderValueAdd{}). Where("order_no = ?", orderRecord.OrderNo). Updates(valueAdd).Error if err != nil { res.Msg = msg.ErrorUpdateOrderInfo return res, commonErr.ReturnError(err, msg.ErrorUpdateOrderInfo, "更新增值服务支付状态失败: ") } // Step 2: 再更新主订单信息(如果存在) err = app.ModuleClients.BundleDB.Model(&model.BundleOrderRecords{}). Where("order_no = ?", orderRecord.OrderNo). Updates(orderRecord).Error // Step 3: 返回结果(即使主订单更新失败,也视为成功) res.Uuid = orderRecord.UUID res.Msg = msg.SuccessUpdateOrderInfo return res, nil } func OrderRecordsList(req *bundle.OrderRecordsRequest) (res *bundle.OrderRecordsResponse, err error) { res = new(bundle.OrderRecordsResponse) res.OrderRecords = make([]*bundle.OrderRecord, 0) records := make([]*model.BundleOrderRecords, 0) query := app.ModuleClients.BundleDB.Model(&model.BundleOrderRecords{}) query.Joins("left join `micro-account`.`user` on `micro-account`.`user`.`id` = `bundle_order_records`.`customer_id`") if req.CustomerID != "" { query = query.Where("customer_id = ?", req.CustomerID) } if req.CustomerNum != "" { query = query.Where("customer_num like ?", "%"+req.CustomerNum+"%") } if req.CustomerName != "" { query = query.Where("customer_name like ?", "%"+req.CustomerName+"%") } if req.BundleName != "" { query = query.Where("bundle_name like ?", "%"+req.BundleName+"%") } if req.BundleUUID != "" { query = query.Where("bundle_uuid = ?", req.BundleUUID) } if req.OrderNo != "" { query = query.Where("order_no like ?", "%"+req.OrderNo+"%") } if req.Status != 0 { query = query.Where("`bundle_order_records`.status = ?", req.Status) } if req.StartSignedTime != "" { query = query.Where("signed_time >= ?", req.StartSignedTime) } if req.EndSignedTime != "" { query = query.Where("signed_time <= ?", req.EndSignedTime) } if req.StartPayTime != "" { query = query.Where("pay_time >= ?", req.StartPayTime) } if req.EndPayTime != "" { query = query.Where("pay_time <= ?", req.EndPayTime) } if req.IsHaveValueAdd == 1 { // 有 query = query.Where("value_add_bundle_uuid != ?", "") } else if req.IsHaveValueAdd == 2 { // 无 query = query.Where("IFNULL(value_add_bundle_uuid,'') = ''") } if req.FinancialConfirmation != 0 { query = query.Where("financial_confirmation = ?", req.FinancialConfirmation) } if req.TelNum != "" { query = query.Where("`micro-account`.`user`.`tel_num` like ?", "%"+req.TelNum+"%") } count := *query if req.PageSize != 0 && req.Page != 0 { query = query.Limit(int(req.PageSize)).Offset(int(req.Page-1) * int(req.PageSize)) } err = query.Find(&records).Error if err != nil { return res, commonErr.ReturnError(err, msg.ErrorGetOrderList, "获取订单信息失败: ") } //_ = copier.CopyWithOption(&res.OrderRecords, records, copier.Option{DeepCopy: true}) for _, record := range records { res.OrderRecords = append(res.OrderRecords, &bundle.OrderRecord{ Uuid: record.UUID, OrderNo: record.OrderNo, BundleUuid: record.BundleUUID, BundleName: record.BundleName, CustomerID: record.CustomerID, CustomerNum: record.CustomerNum, CustomerName: record.CustomerName, Amount: record.Amount, AmountType: record.AmountType, SignContract: record.SignContract, Signature: record.Signature, SignedTime: record.SignedTime, PayType: record.PayType, PayTime: record.PayTime, CheckoutSessionId: record.CheckoutSessionId, CheckoutSessionUrl: record.CheckoutSessionUrl, Status: record.Status, ContractNo: record.ContractNo, ValueAddBundleUuid: record.ValueAddBundleUUID, ValueAddBundleAmount: record.ValueAddBundleAmount, ValueAddOriginalPrice: record.ValueAddOriginalPrice, ValueAddDiscountPrice: record.ValueAddDiscountPrice, ValueAddSavedAmount: record.ValueAddSavedAmount, TotalAmount: record.TotalAmount, Num: record.Num, BundleCommonUid: record.BundleCommonUid, AddBundleCommonUid: record.AddBundleCommonUid, FinancialConfirmation: record.FinancialConfirmation, ExpirationTime: record.ExpirationTime, }) } var total int64 count.Count(&total) res.Total = int32(total) return } func OrderRecordDetail(req *bundle.OrderRecordsDetailRequest) (res *bundle.OrderRecord, err error) { res = new(bundle.OrderRecord) orderRecord := new(model.BundleOrderRecords) query := app.ModuleClients.BundleDB.Model(&model.BundleOrderRecords{}) if req.Uuid != "" { query = query.Where("uuid = ?", req.Uuid) } if req.OrderNo != "" { query = query.Where("order_no = ?", req.OrderNo) } if req.CustomerID != "" { query = query.Where("customer_id = ?", req.CustomerID) } err = query.First(&orderRecord).Error if err != nil { return res, commonErr.ReturnError(err, msg.ErrorGetOrderInfo, "获取订单信息失败: ") } //_ = copier.CopyWithOption(&res, orderRecord, copier.Option{DeepCopy: true}) res = &bundle.OrderRecord{ Uuid: orderRecord.UUID, OrderNo: orderRecord.OrderNo, BundleUuid: orderRecord.BundleUUID, BundleName: orderRecord.BundleName, CustomerID: orderRecord.CustomerID, CustomerNum: orderRecord.CustomerNum, CustomerName: orderRecord.CustomerName, Amount: orderRecord.Amount, AmountType: orderRecord.AmountType, SignContract: orderRecord.SignContract, Signature: orderRecord.Signature, SignedTime: orderRecord.SignedTime, PayType: orderRecord.PayType, PayTime: orderRecord.PayTime, CheckoutSessionId: orderRecord.CheckoutSessionId, CheckoutSessionUrl: orderRecord.CheckoutSessionUrl, Status: orderRecord.Status, ContractNo: orderRecord.ContractNo, ValueAddBundleUuid: orderRecord.ValueAddBundleUUID, ValueAddBundleAmount: orderRecord.ValueAddBundleAmount, TotalAmount: orderRecord.TotalAmount, } return } func PackagePriceAndTime(orderRecord *bundle.OrderRecord) (res *bundle.PackagePriceAndTimeResponse, err error) { res = new(bundle.PackagePriceAndTimeResponse) bundleInfo := new(model.BundleProfile) // 查询套餐主表并预加载 err = app.ModuleClients.BundleDB.Model(&model.BundleProfile{}). Where("uuid = ?", orderRecord.BundleUuid). Preload("BundleToValueAddService"). Preload("BundleProfileLang", "language = ?", orderRecord.Language). First(&bundleInfo).Error if err != nil { return res, commonErr.ReturnError(err, msg.ErrorBundleNotFound, "查询Bundle信息失败: ") } var ( valueAddAmount float64 expirationTime = "9999-12-31" ) for _, service := range bundleInfo.BundleToValueAddService { amount, _, _, day, e := calculateAmount(service.ValueUid, orderRecord) if e != nil { return res, commonErr.ReturnError(e, msg.ErrorDataConvert, "子订单金额计算失败: ") } if day != "" { expirationTime = day } valueAddAmount = valueAddAmount + amount } res = &bundle.PackagePriceAndTimeResponse{ Price: float32(valueAddAmount), Time: expirationTime, } return } func CreateOrderAddRecord(req *bundle.OrderAddRecord) (res *bundle.CommonResponse, err error) { tx := app.ModuleClients.BundleDB.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() orderNo := utils.GetOrderNo() var childOrders []*model.BundleOrderValueAdd for _, i := range req.AddPriceOptionsList { childOrder := &model.BundleOrderValueAdd{ UUID: app.ModuleClients.SfNode.Generate().Base64(), OrderUUID: req.BundleUuid, // 修正: 这里应使用主订单UUID CustomerID: req.CustomerID, CustomerNum: req.CustomerNum, CustomerName: req.CustomerName, ServiceType: i.ServiceType, CurrencyType: i.CurrencyType, Amount: float64(i.Amount), OrderNo: orderNo, Num: i.Num, Unit: i.Unit, ValueAddUUID: i.ValueUid, Source: 1, PaymentStatus: 1, SignContract: req.SignContract, Signature: req.Signature, SignedTime: req.SignedTime, } childOrders = append(childOrders, childOrder) // 如果是类型5服务,更新主订单的过期时间 if i.ServiceType == 5 && req.ExpirationDate != "" { if err := tx.Model(&model.BundleOrderRecords{}). Where("uuid = ?", req.BundleUuid). Update("expiration_time", req.ExpirationDate).Error; err != nil { tx.Rollback() return nil, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "更新主订单过期时间失败: ") } } } // 批量创建子订单(提高性能) if err = tx.Model(&model.BundleOrderValueAdd{}).Create(childOrders).Error; err != nil { tx.Rollback() return res, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "批量创建子订单失败") } // 提交事务 if err := tx.Commit().Error; err != nil { tx.Rollback() return nil, commonErr.ReturnError(err, msg.ErrorCreateOrderInfo, "提交事务失败: ") } return &bundle.CommonResponse{ Uuid: req.BundleUuid, OrderNo: orderNo, Msg: msg.SuccessCreateOrderInfo, }, nil }