package order import ( "errors" logger "eta/eta_mini_ht_api/common/component/log" "eta/eta_mini_ht_api/common/exception" "eta/eta_mini_ht_api/common/utils/page" merchantService "eta/eta_mini_ht_api/domian/merchant" productService "eta/eta_mini_ht_api/domian/merchant" orderService "eta/eta_mini_ht_api/domian/order" userService "eta/eta_mini_ht_api/domian/user" merchantDao "eta/eta_mini_ht_api/models/merchant" orderDao "eta/eta_mini_ht_api/models/order" "eta/eta_mini_ht_api/service/user" "fmt" "gorm.io/gorm" "sync" "time" ) const ( permanentlyValid = "永久有效" OnSale = "on_sale" //上架 OffSale = "off_sale" //下架 ) var ( productOrderStatusMap = map[orderDao.OrderStatus]string{ orderDao.OrderStatusPending: "pending", orderDao.OrderStatusPaid: "paid", orderDao.OrderStatusClosed: "closed", orderDao.OrderStatusRefund: "refund", } accessStatusMap = map[merchantDao.SubscribeStatus]string{ merchantDao.SubscribeValid: "valid", merchantDao.SubscribeExpired: "expired", merchantDao.SubscribeClose: "closed", } ) type ProductOrderInfo struct { Buyer BuyerInfo `json:"buyer"` ProductInfo ProductInfo `json:"productInfo"` Order ProductOrder `json:"order"` } type ProductInfo struct { Name string Type string Price string ValidDuration string } type ProductOrder struct { OrderNo string CreatedTime string } type BuyerInfo struct { Name string Mobile string AreaCode string } func GenerateProductOrderNo() string { return orderService.GenerateProductOrderNo() } func CreateProductOrder(templateUser user.User, productId int, orderNo string) (orderInfo ProductOrderInfo, err error) { if productId <= 0 { err = exception.New(exception.IllegalProductId) } productInfo, err := productService.GetMerchantProductById(productId) if err != nil { err = exception.NewWithException(exception.ProductInfoError, err.Error()) return } if productInfo.Deleted { err = exception.New(exception.ProductInfoError) return } if productInfo.SaleStatus == OffSale { err = exception.New(exception.ProductOffSale) return } officialUser, err := userService.GetUserByTemplateUserId(templateUser.Id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { err = exception.New(exception.OfficialUserNotFound) } else { err = exception.NewWithException(exception.OfficialUserFoundError, err.Error()) } return } //校验是否有相同待支付的产品订单 var existOrder orderService.ProductOrderDTO existOrder, err = orderService.GetUserOrderByProduct(productId, templateUser.Id, productOrderStatusMap[orderDao.OrderStatusPending]) if (err != nil && !errors.Is(err, gorm.ErrRecordNotFound)) || existOrder.Status == productOrderStatusMap[orderDao.OrderStatusPending] { err = exception.NewWithException(exception.DuplicateSubscribe, "当前产品有正在进行中的订单,请勿重复下单") return } //是否在有效期的产品 var access merchantService.UserAccessDTO access, err = merchantService.GetUserSubscribe(templateUser.Id, productId) if (err != nil && !errors.Is(err, gorm.ErrRecordNotFound)) || access.Status == accessStatusMap[merchantDao.SubscribeValid] { err = exception.NewWithException(exception.DuplicateSubscribe, "当前产品已订阅,请勿重复下单") return } var orderCreated orderService.ProductOrderDTO orderCreated, err = orderService.CreateProductOrder(orderService.ProductOrderDTO{ OrderID: orderNo, UserID: officialUser.ID, TemplateUserID: templateUser.Id, RealName: templateUser.Username, AreaCode: templateUser.AreaCode, Mobile: templateUser.Mobile, ProductID: productId, ProductType: productInfo.Type, ProductName: productInfo.ProductTile, TotalAmount: productInfo.Price, }) if err != nil { logger.Error("创建订单失败:%v", err) if errors.Is(err, gorm.ErrDuplicatedKey) { err = exception.NewWithException(exception.SubscribeFailed, "请勿重复下单") return } err = exception.NewWithException(exception.SubscribeFailed, err.Error()) return } buyer := BuyerInfo{ Name: officialUser.RealName, Mobile: templateUser.Mobile, AreaCode: templateUser.AreaCode, } var duration string if !productInfo.IsPermanent { beginDate := time.Now().Format(time.DateOnly) endDate := time.Now().Add(time.Duration(productInfo.ValidDays*24) * time.Hour).Format(time.DateOnly) duration = fmt.Sprintf("%s~%s", beginDate, endDate) } else { duration = permanentlyValid } product := ProductInfo{ Name: productInfo.Title, Type: productInfo.Type, Price: productInfo.Price, ValidDuration: duration, } order := ProductOrder{ OrderNo: orderCreated.OrderID, CreatedTime: orderCreated.CreatedTime, } orderInfo = ProductOrderInfo{ Buyer: buyer, ProductInfo: product, Order: order, } return } func PreViewProductOrder(templateUser user.User, productId int) (orderInfo ProductOrderInfo, err error) { if productId <= 0 { err = exception.New(exception.IllegalProductId) } productInfo, err := productService.GetMerchantProductById(productId) if err != nil { err = exception.NewWithException(exception.ProductInfoError, err.Error()) return } if productInfo.SaleStatus == OffSale { err = exception.New(exception.ProductOffSale) return } officialUser, err := userService.GetUserByTemplateUserId(templateUser.Id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { err = exception.New(exception.OfficialUserNotFound) } else { err = exception.NewWithException(exception.OfficialUserFoundError, err.Error()) } return } buyer := BuyerInfo{ Name: officialUser.RealName, Mobile: templateUser.Mobile, AreaCode: templateUser.AreaCode, } var duration string if !productInfo.IsPermanent { beginDate := time.Now().Format(time.DateOnly) endDate := time.Now().Add(time.Duration(productInfo.ValidDays*24) * time.Hour).Format(time.DateOnly) duration = fmt.Sprintf("%s~%s", beginDate, endDate) } else { duration = permanentlyValid } product := ProductInfo{ Name: productInfo.Title, Type: productInfo.Type, Price: productInfo.Price, ValidDuration: duration, } orderInfo = ProductOrderInfo{ Buyer: buyer, ProductInfo: product, } return } func GetTotalPageCountByUserId(userId int, orderStatus string) (total int64, latestId int64) { return orderService.GetTotalPageCountByUserId(userId, orderStatus) } func GetOrderPage(pageInfo page.PageInfo, userId int, orderStatus string) (orderList []orderService.ProductOrderDTO, err error) { orderList, err = orderService.GetOrderPage(pageInfo, userId, orderStatus) if err != nil { err = exception.NewWithException(exception.GetOrderListFailed, err.Error()) } var wg sync.WaitGroup wg.Add(len(orderList)) logger.Info("获取产品信息") for i := 0; i < len(orderList); i++ { go func(order *orderService.ProductOrderDTO) { defer wg.Done() product, pdErr := productService.GetMerchantProductById(order.ProductID) if pdErr != nil { logger.Error("获取产品信息失败:%v", err) } order.ProductName = product.Title }(&orderList[i]) } wg.Wait() return } func GetOrderDetail(orderId string, userId int) (order orderService.ProductOrderDetailDTO, err error) { order, err = orderService.GetOrderDetail(orderId, userId) return } func GetProductOrderByUser(templateUserId int, orderNo string) (order orderService.ProductOrderDTO, err error) { return orderService.GetOrderByUser(templateUserId, orderNo) } func CloseProductOrder(templateUserId int, productOrderNo string) (err error) { return orderService.CloseProductOrder(templateUserId, productOrderNo) } func GetTradeOrderByNo(tradeOrderNo string) (dto orderService.TradeOrderDTO, err error) { return orderService.GetTradeOrderByNo(tradeOrderNo) } func CheckProductStatus(productOrder orderService.ProductOrderDTO) (err error) { product, err := productService.GetMerchantProductById(productOrder.ProductID) if err != nil { return exception.NewWithException(exception.ProductInfoError, err.Error()) } if product.SaleStatus == "off_sale" { err = orderService.CloseProductOrder(productOrder.TemplateUserID, productOrder.OrderID) if err != nil { logger.Error("关闭订单失败:%v,订单编号:%s", err, product) } return exception.New(exception.ProductOffSale) } if product.Deleted { err = orderService.CloseProductOrder(productOrder.TemplateUserID, productOrder.OrderID) if err != nil { logger.Error("关闭订单失败:%v,订单编号:%s", err, product) } return exception.New(exception.ProductNotFound) } return }