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, req.Language) 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, Num: num, Unit: info.Unit, ValueAddUUID: service.ValueUid, Source: 1, PaymentStatus: 1, } 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, language string) (amount float64, valueAddServiceLang *model.ValueAddServiceLang, num int32, expirationDay string, err error) { err = app.ModuleClients.BundleDB. Where("uuid = ? AND language = ?", valueUid, language). First(&valueAddServiceLang).Error if err != nil { return } for _, opt := range valueAddServiceLang.Options { if valueAddServiceLang.PriceMode == 1 { for _, p := range req.PriceOptionsInfo { if p.ValueUid == valueUid && opt.Id == p.Id { amount = float64(float32(opt.Num) * opt.Price) num = opt.Num } } } 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) err = app.ModuleClients.BundleDB.Model(&model.BundleOrderRecords{}).Where("order_no = ?", orderRecord.OrderNo).Updates(orderRecord).Error if err != nil { res.Msg = msg.ErrorUpdateOrderInfo return res, commonErr.ReturnError(err, msg.ErrorUpdateOrderInfo, "更新订单信息失败: ") } valueAdd := &model.BundleOrderValueAdd{ PaymentStatus: int(orderRecord.Status), PaymentTime: orderRecord.PayTime, } //更新子订单支付状态 err = app.ModuleClients.BundleDB.Model(&model.BundleOrderValueAdd{}).Where("order_uuid = ?", orderRecord.UUID).Updates(valueAdd).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 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, }) } 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 }