package usecase import ( "app-cloudep-trade-service/internal/domain" "app-cloudep-trade-service/internal/domain/usecase" model "app-cloudep-trade-service/internal/model/mongo" "context" "errors" "time" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/mon" ) type OrderUseCaseParam struct { OrderModel model.OrderModel } type OrderUseCase struct { OrderModel model.OrderModel } func NewOrderUseCase(param OrderUseCaseParam) usecase.OrderUseCase { return &OrderUseCase{ OrderModel: param.OrderModel, } } func (o *OrderUseCase) CreateOrder(ctx context.Context, param usecase.CreateOrderReq) error { now := time.Now().UTC().UnixNano() // 插入資料庫 order := &model.Order{ UpdateTime: now, CreateTime: now, BusinessID: param.BusinessID, OrderType: param.OrderType, OrderStatus: param.OrderStatus, Brand: param.Brand, OrderUID: param.OrderUID, ReferenceID: param.ReferenceID, Count: param.Count, OrderFee: param.OrderFee, Amount: param.Amount, ReferenceBrand: param.ReferenceBrand, ReferenceUID: param.ReferenceUID, WalletStatus: param.WalletStatus, ThreePartyStatus: param.ThreePartyStatus, DirectionType: param.DirectionType, CryptoType: param.CryptoType, ThirdPartyFee: param.ThirdPartyFee, CryptoToUSDTRate: param.CryptoToUSDTRate, FiatToUSDRate: param.FiatToUSDRate, FeeCryptoToUSDTRate: param.FeeCryptoToUSDTRate, USDTToCryptoTypeRate: param.USDTToCryptoTypeRate, PaymentFiat: param.PaymentFiat, PaymentUnitPrice: param.PaymentUnitPrice, PaymentTemplateID: param.PaymentTemplateID, OrderArrivalTime: param.OrderArrivalTime, OrderPaymentTime: param.OrderPaymentTime, UnpaidTimeoutSecond: param.UnpaidTimeoutSecond, ChainType: param.ChainType, TxHash: param.TxHash, FromAddress: param.FromAddress, ToAddress: param.ToAddress, ChainFee: param.ChainFee, ChainFeeCrypto: param.ChainFeeCrypto, Memo: param.Memo, OrderNote: param.OrderNote, } err := o.OrderModel.Insert(ctx, order) if err != nil { // 錯誤代碼 06-021-01 e := domain.CommentErrorL( domain.CreateOrderErrorCode, logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: param}, {Key: "func", Value: "OrderModel.Insert"}, {Key: "err", Value: err}, }, "failed to insert order into mongo:").Wrap(err) return e } return nil } func (o *OrderUseCase) CancelOrder(ctx context.Context, param usecase.CancelOrderQuery) error { _, err := o.OrderModel.UpdateStatus(ctx, model.UpdateStatusReq{ BusinessID: param.BusinessID, Status: param.Status.ToInt64(), }) if err != nil { // 錯誤代碼 06-021-02 e := domain.CommentErrorL( domain.CancelOrderErrorCode, logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: param}, {Key: "func", Value: "OrderModel.UpdateStatus"}, {Key: "err", Value: err}, }, "failed to update order status:").Wrap(err) return e } return nil } func (o *OrderUseCase) DeleteOrder(ctx context.Context, param usecase.DeleteOrderQuery) error { _, err := o.OrderModel.DeleteByBusinessID(ctx, param.BusinessID) if err != nil { return err } return nil } func (o *OrderUseCase) GetOrder(ctx context.Context, param usecase.GetOrderQuery) (*usecase.GetOrderResp, error) { order, err := o.OrderModel.FindOneBusinessID(ctx, param.BusinessID) if err != nil { if errors.Is(mon.ErrNotFound, err) { return nil, domain.NotFoundError(domain.DataNotFoundErrorCode, "failed to get this order id:", param.BusinessID) } return nil, err } resp := &usecase.GetOrderResp{ UpdateTime: order.UpdateTime, CreateTime: order.CreateTime, BusinessId: order.BusinessID, OrderType: order.OrderType, OrderStatus: order.OrderStatus, Brand: order.Brand, OrderUid: order.OrderUID, ReferenceId: order.ReferenceID, Count: order.Count.String(), OrderFee: order.OrderFee.String(), Amount: order.Amount.String(), ReferenceBrand: order.ReferenceBrand, ReferenceUid: order.ReferenceUID, WalletStatus: Int64Ptr(order.WalletStatus), ThreePartyStatus: order.ThreePartyStatus, DirectionType: Int64Ptr(order.DirectionType), CryptoType: order.CryptoType, ThirdPartyFee: DecimalToStringPtr(order.ThirdPartyFee), CryptoToUsdtRate: DecimalToStringPtr(order.CryptoToUSDTRate), FiatToUsdRate: DecimalToStringPtr(order.FiatToUSDRate), FeeCryptoToUsdtRate: DecimalToStringPtr(order.FeeCryptoToUSDTRate), UsdtToCryptoTypeRate: DecimalToStringPtr(order.USDTToCryptoTypeRate), PaymentFiat: order.PaymentFiat, PaymentUnitPrice: DecimalToStringPtr(order.PaymentUnitPrice), PaymentTemplateId: order.PaymentTemplateID, OrderArrivalTime: order.OrderArrivalTime, OrderPaymentTime: order.OrderPaymentTime, UnpaidTimeoutSecond: order.UnpaidTimeoutSecond, ChainType: order.ChainType, TxHash: order.TxHash, FromAddress: order.FromAddress, ToAddress: order.ToAddress, ChainFee: DecimalToStringPtr(order.ChainFee), ChainFeeCrypto: order.ChainFeeCrypto, Memo: order.Memo, OrderNote: order.OrderNote, } return resp, nil } func (o *OrderUseCase) ListOrder(ctx context.Context, param usecase.GetOrderListReq) (*usecase.ListOrderResp, error) { // 構建查詢條件 req := model.GetOrderListReq{ PageIndex: param.PageIndex, PageSize: param.PageSize, ReferenceID: param.ReferenceID, ReferenceUID: param.ReferenceUID, BusinessID: param.BusinessID, UID: param.UID, OrderType: param.OrderType.ToInt(), DirectionType: param.DirectionType, OrderStatus: param.OrderStatus, StartCreateTime: param.StartCreateTime, EndCreateTime: param.EndCreateTime, StartUpdateTime: param.StartUpdateTime, EndUpdateTime: param.EndUpdateTime, StartOrderArrivalTime: param.StartOrderArrivalTime, EndOrderArrivalTime: param.EndOrderArrivalTime, StartOrderPaymentTime: param.StartOrderPaymentTime, EndOrderPaymentTime: param.EndOrderPaymentTime, CryptoType: param.CryptoType, TxHash: param.TxHash, } // 查詢訂單 orders, total, err := o.OrderModel.ListOrder(ctx, req) if err != nil { return nil, err } return &usecase.ListOrderResp{ Data: o.convertOrdersToResponses(orders), Page: &usecase.Pager{ Total: total, Index: param.PageIndex, Size: param.PageSize, }, }, nil } func (o *OrderUseCase) ModifyOrderStatus(ctx context.Context, param *usecase.ModifyOrderQuery) error { _, err := o.OrderModel.UpdateStatus(ctx, model.UpdateStatusReq{ BusinessID: param.BusinessID, Status: param.Status, }) if err != nil { // 錯誤代碼 06-021-02 e := domain.CommentErrorL( domain.ModifyOrderErrorCode, logx.WithContext(ctx), []logx.LogField{ {Key: "req", Value: param}, {Key: "func", Value: "OrderModel.UpdateStatus"}, {Key: "err", Value: err}, }, "failed to update order status:").Wrap(err) return e } return nil } func (o *OrderUseCase) OrderStatusTimeout(ctx context.Context) error { now := time.Now().UTC().UnixNano() _, err := o.OrderModel.UpdateTimeoutOrder(ctx, model.UpdateTimeoutReq{ CreateTimeBefore: now, }) if err != nil { // 錯誤代碼 06-021-02 e := domain.CommentErrorL( domain.TimeoutOrderErrorCode, logx.WithContext(ctx), []logx.LogField{ {Key: "now", Value: now}, {Key: "func", Value: "OrderModel.UpdateTimeoutOrder"}, {Key: "err", Value: err}, }, "failed to update timeout order").Wrap(err) return e } return nil } // ================= 工具類區 ================= func (o *OrderUseCase) convertOrdersToResponses(orders []model.Order) []*usecase.GetOrderResp { res := make([]*usecase.GetOrderResp, 0, len(orders)) for _, order := range orders { resp := &usecase.GetOrderResp{ UpdateTime: order.UpdateTime, CreateTime: order.CreateTime, BusinessId: order.BusinessID, OrderType: order.OrderType, OrderStatus: order.OrderStatus, Brand: order.Brand, OrderUid: order.OrderUID, ReferenceId: order.ReferenceID, Count: order.Count.String(), OrderFee: order.OrderFee.String(), Amount: order.Amount.String(), ReferenceBrand: order.ReferenceBrand, ReferenceUid: order.ReferenceUID, WalletStatus: Int64Ptr(order.WalletStatus), ThreePartyStatus: order.ThreePartyStatus, DirectionType: Int64Ptr(order.DirectionType), CryptoType: order.CryptoType, ThirdPartyFee: DecimalToStringPtr(order.ThirdPartyFee), CryptoToUsdtRate: DecimalToStringPtr(order.CryptoToUSDTRate), FiatToUsdRate: DecimalToStringPtr(order.FiatToUSDRate), FeeCryptoToUsdtRate: DecimalToStringPtr(order.FeeCryptoToUSDTRate), UsdtToCryptoTypeRate: DecimalToStringPtr(order.USDTToCryptoTypeRate), PaymentFiat: order.PaymentFiat, PaymentUnitPrice: DecimalToStringPtr(order.PaymentUnitPrice), PaymentTemplateId: order.PaymentTemplateID, OrderArrivalTime: order.OrderArrivalTime, OrderPaymentTime: order.OrderPaymentTime, UnpaidTimeoutSecond: order.UnpaidTimeoutSecond, ChainType: order.ChainType, TxHash: order.TxHash, FromAddress: order.FromAddress, ToAddress: order.ToAddress, ChainFee: DecimalToStringPtr(order.ChainFee), ChainFeeCrypto: order.ChainFeeCrypto, Memo: order.Memo, OrderNote: order.OrderNote, } res = append(res, resp) } return res }