From 67ccb9433cbd9ecfa4f293dcbb3985f56ae58310 Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Sun, 27 Oct 2024 22:23:37 +0800 Subject: [PATCH] add order usecase --- internal/domain/order.go | 10 +- internal/domain/usecase/order.go | 165 +++++++++++++++ internal/domain/wallet.go | 19 ++ internal/model/mongo/order_model.go | 7 +- internal/model/mongo/order_types.go | 6 +- internal/usecase/order.go | 307 ++++++++++++++++++++++++++++ internal/usecase/order_test.go | 263 ++++++++++++++++++++++++ internal/usecase/utils.go | 31 +++ 8 files changed, 801 insertions(+), 7 deletions(-) create mode 100644 internal/domain/usecase/order.go create mode 100644 internal/domain/wallet.go create mode 100644 internal/usecase/order.go create mode 100644 internal/usecase/order_test.go create mode 100644 internal/usecase/utils.go diff --git a/internal/domain/order.go b/internal/domain/order.go index 18233cb..be56da4 100644 --- a/internal/domain/order.go +++ b/internal/domain/order.go @@ -2,8 +2,8 @@ package domain type OrderStatus int64 -func (o *OrderStatus) ToInt() int { - return int(*o) +func (o *OrderStatus) ToInt64() int64 { + return int64(*o) } const ( @@ -20,3 +20,9 @@ const ( OrderStatusAbnormal OrderStatus = 10 // 交易異常 OrderStatusTimeout OrderStatus = 11 // 交易超時 ) + +type OrderType int64 + +func (o *OrderType) ToInt() int { + return int(*o) +} diff --git a/internal/domain/usecase/order.go b/internal/domain/usecase/order.go new file mode 100644 index 0000000..6e6760b --- /dev/null +++ b/internal/domain/usecase/order.go @@ -0,0 +1,165 @@ +package usecase + +import ( + "app-cloudep-trade-service/internal/domain" + "context" + + "github.com/shopspring/decimal" +) + +type OrderUseCase interface { + // CreateOrder 建立訂單,不另外做 struct 直接用 model.Order + // 考量底層已經寫完,如有額外需求需要在這邊用轉的 + CreateOrder(ctx context.Context, param CreateOrderReq) error + // CancelOrder 取消訂單 + CancelOrder(ctx context.Context, param CancelOrderQuery) error + // DeleteOrder 刪除訂單(軟刪除) + DeleteOrder(ctx context.Context, param DeleteOrderQuery) error + // GetOrder 取得訂單資料 + GetOrder(ctx context.Context, param GetOrderQuery) (*GetOrderResp, error) + // ListOrder 取得資料列表 + ListOrder(ctx context.Context, param GetOrderListReq) (*ListOrderResp, error) + // ModifyOrderStatus 更新資料 + ModifyOrderStatus(ctx context.Context, param *ModifyOrderQuery) error + // OrderStatusTimeout 訂單超時任務/cron/order-status/timeout + OrderStatusTimeout(ctx context.Context) error +} + +// ModifyOrderQuery +// 0.建立訂單 1.建單失敗 2.審核中 3.付款中 4.已付款 +// 5.已付款待轉帳 6.申訴中 7.交易完成 +// 8.交易失敗 9.交易取消 10.交易異常 11.交易超時 + +type ModifyOrderQuery struct { + BusinessID string `json:"business_id" validate:"required"` + Status int64 `json:"status" validate:"required,oneof=2 3 4 5 6 7 8 11"` +} + +// CancelOrderQuery 1.建單失敗 9.交易取消 10.交易異常 +type CancelOrderQuery struct { + BusinessID string + Status domain.OrderStatus +} + +// DeleteOrderQuery 刪除訂單(軟刪除) +type DeleteOrderQuery struct { + BusinessID string +} + +// GetOrderQuery 取得訂單 +type GetOrderQuery struct { + BusinessID string +} + +type GetOrderResp struct { + BusinessId string // 訂單業務流水號 + OrderType domain.OrderType `json:"order_type"` // 訂單類型 + OrderStatus domain.OrderStatus `json:"order_status"` // 訂單狀態 + Brand string `json:"brand"` // 下單平台 + OrderUid string `json:"order_uid"` // 下單用戶 UID + ReferenceId string `json:"reference_id"` // 訂單來源 + Count string `json:"count"` // 訂單數量 (decimal to string) + OrderFee string `json:"order_fee"` // 訂單手續費 (decimal to string) + Amount string `json:"amount"` // 單價 (decimal to string) + ReferenceBrand *string `json:"reference_brand,omitempty"` // 訂單來源平台 + ReferenceUid *string `json:"reference_uid,omitempty"` // 訂單來源用戶 UID + WalletStatus *int64 `json:"wallet_status,omitempty"` // 交易金額狀態 + ThreePartyStatus *int64 `json:"three_party_status,omitempty"` // 三方請求狀態 + DirectionType *int64 `json:"direction_type,omitempty"` // 交易方向 + CryptoType *string `json:"crypto_type,omitempty"` // 交易幣種 + ThirdPartyFee *string `json:"third_party_fee,omitempty"` // 第三方手續費 (decimal to string) + CryptoToUsdtRate *string `json:"crypto_to_usdt_rate,omitempty"` // 交易幣種對 USDT 匯率 (decimal to string) + FiatToUsdRate *string `json:"fiat_to_usd_rate,omitempty"` // 法幣對 USD 匯率 (decimal to string) + FeeCryptoToUsdtRate *string `json:"fee_crypto_to_usdt_rate,omitempty"` // 手續費幣種對 USDT 匯率 (decimal to string) + UsdtToCryptoTypeRate *string `json:"usdt_to_crypto_type_rate,omitempty"` // USDT 對交易幣種匯率 (decimal to string) + PaymentFiat *string `json:"payment_fiat,omitempty"` // 支付法幣 + PaymentUnitPrice *string `json:"payment_unit_price,omitempty"` // crypto 單價 (decimal to string) + PaymentTemplateId *string `json:"payment_template_id,omitempty"` // 支付方式配置 ID + OrderArrivalTime *int64 `json:"order_arrival_time,omitempty"` // 訂單到帳時間 + OrderPaymentTime *int64 `json:"order_payment_time,omitempty"` // 訂單付款時間 + UnpaidTimeoutSecond *int64 `json:"unpaid_timeout_second,omitempty"` // 支付期限秒數 + ChainType *string `json:"chain_type,omitempty"` // 主網類型 + TxHash *string `json:"tx_hash,omitempty,omitempty"` // 交易哈希 + FromAddress *string `json:"from_address,omitempty,omitempty"` // 來源地址 + ToAddress *string `json:"to_address,omitempty,omitempty"` // 目標地址 + ChainFee *string `json:"chain_fee,omitempty"` // 鏈上交易手續費 (decimal to string) + ChainFeeCrypto *string `json:"chain_fee_crypto,omitempty"` // 鏈上手續費使用幣別 + Memo *string `json:"memo,omitempty"` // 鏈上備註 + OrderNote *string `json:"order_note,omitempty"` // 訂單交易備註 + CreateTime int64 `json:"create_time,omitempty"` // 建立時間 + UpdateTime int64 `json:"update_time,omitempty"` // 更新時間 +} + +type GetOrderListReq struct { + PageIndex int64 + PageSize int64 + + ReferenceID string + ReferenceUID string + BusinessID string + UID string + OrderType domain.OrderType + DirectionType []int64 + OrderStatus []int64 + + StartCreateTime int64 + EndCreateTime int64 + StartUpdateTime int64 + EndUpdateTime int64 + StartOrderArrivalTime int64 + EndOrderArrivalTime int64 + StartOrderPaymentTime int64 + EndOrderPaymentTime int64 + + CryptoType string + TxHash string +} + +type Pager struct { + Index int64 + Size int64 + Total int64 +} + +type ListOrderResp struct { + Data []*GetOrderResp `json:"data"` // 訂單列表 + Page *Pager `json:"page"` +} + +type CreateOrderReq struct { + BusinessID string + OrderType domain.OrderType // 訂單類型 + OrderStatus domain.OrderStatus // 訂單狀態 + Brand string // 下單平台 + OrderUID string // 下單用戶 UID + ReferenceID string // 訂單來源 + Count decimal.Decimal // 訂單數量 + OrderFee decimal.Decimal // 訂單手續費 + Amount decimal.Decimal // 單價 + WalletStatus int64 // 交易金額狀態 + DirectionType int64 // 交易方向 + // 以上為必要欄位,下面是區塊鏈時才需要 + ReferenceBrand *string // 訂單來源平台 + ReferenceUID *string // 訂單來源用戶 UID + ThreePartyStatus *int64 // 三方請求狀態 + CryptoType *string // 交易幣種 + ThirdPartyFee *decimal.Decimal // 第三方手續費 + CryptoToUSDTRate *decimal.Decimal // 加密貨幣對 USDT 匯率 + FiatToUSDRate *decimal.Decimal // 法幣對 USD 匯率 + FeeCryptoToUSDTRate *decimal.Decimal // 手續費加密貨幣對 USDT 匯率 + USDTToCryptoTypeRate *decimal.Decimal // USDT 對加密貨幣匯率 + PaymentFiat *string // 支付法幣 + PaymentUnitPrice *decimal.Decimal // 加密貨幣單價 + PaymentTemplateID *string // 支付方式配置 ID + OrderArrivalTime *int64 // 訂單到帳時間 + OrderPaymentTime *int64 // 訂單付款時間 + UnpaidTimeoutSecond *int64 // 支付期限秒數 + ChainType *string // 主網類型 + TxHash *string // 交易哈希 + FromAddress *string // 來源地址 + ToAddress *string // 目標地址 + ChainFee *decimal.Decimal // 鏈上交易手續費 + ChainFeeCrypto *string // 鏈上手續費使用幣別 + Memo *string // 鏈上備註 + OrderNote *string // 訂單交易備註 +} diff --git a/internal/domain/wallet.go b/internal/domain/wallet.go new file mode 100644 index 0000000..0bd0cbe --- /dev/null +++ b/internal/domain/wallet.go @@ -0,0 +1,19 @@ +package domain + +type WalletStatus int64 + +func (o *WalletStatus) ToInt() int { + return int(*o) +} + +type ThreePartyStatus int64 + +func (o *ThreePartyStatus) ToInt() int { + return int(*o) +} + +type DirectionType int64 + +func (o *DirectionType) ToInt() int { + return int(*o) +} diff --git a/internal/model/mongo/order_model.go b/internal/model/mongo/order_model.go index b1c95db..2da7c31 100644 --- a/internal/model/mongo/order_model.go +++ b/internal/model/mongo/order_model.go @@ -4,11 +4,12 @@ import ( "app-cloudep-trade-service/internal/domain" "context" "errors" + "time" + "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" ) var _ OrderModel = (*customOrderModel)(nil) @@ -46,8 +47,8 @@ type ( BusinessID string `json:"business_id"` UID string `json:"uid"` OrderType int `json:"order_type"` - DirectionType []int32 `json:"direction_type"` - OrderStatus []int32 `json:"order_status"` + DirectionType []int64 `json:"direction_type"` + OrderStatus []int64 `json:"order_status"` StartCreateTime int64 `json:"start_create_time"` EndCreateTime int64 `json:"end_create_time"` diff --git a/internal/model/mongo/order_types.go b/internal/model/mongo/order_types.go index d7f73c5..db23980 100644 --- a/internal/model/mongo/order_types.go +++ b/internal/model/mongo/order_types.go @@ -1,6 +1,8 @@ package model import ( + "app-cloudep-trade-service/internal/domain" + "github.com/shopspring/decimal" "go.mongodb.org/mongo-driver/bson/primitive" ) @@ -10,8 +12,8 @@ type Order struct { UpdateTime int64 `bson:"update_time"` CreateTime int64 `bson:"create_time"` BusinessID string `bson:"business_id"` // 訂單業務流水號 - OrderType int8 `bson:"order_type"` // 訂單類型 - OrderStatus int8 `bson:"order_status"` // 訂單狀態 + OrderType domain.OrderType `bson:"order_type"` // 訂單類型 + OrderStatus domain.OrderStatus `bson:"order_status"` // 訂單狀態 Brand string `bson:"brand"` // 下單平台 OrderUID string `bson:"order_uid"` // 下單用戶 UID ReferenceID string `bson:"reference_id"` // 訂單來源 diff --git a/internal/usecase/order.go b/internal/usecase/order.go new file mode 100644 index 0000000..be34a79 --- /dev/null +++ b/internal/usecase/order.go @@ -0,0 +1,307 @@ +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 +} diff --git a/internal/usecase/order_test.go b/internal/usecase/order_test.go new file mode 100644 index 0000000..56ef42d --- /dev/null +++ b/internal/usecase/order_test.go @@ -0,0 +1,263 @@ +package usecase + +import ( + "app-cloudep-trade-service/internal/domain/usecase" + model "app-cloudep-trade-service/internal/model/mongo" + "context" + "reflect" + "testing" +) + +func TestNewOrderUseCase(t *testing.T) { + type args struct { + param OrderUseCaseParam + } + tests := []struct { + name string + args args + want usecase.OrderUseCase + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewOrderUseCase(tt.args.param); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewOrderUseCase() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOrderUseCase_CancelOrder(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param usecase.CancelOrderQuery + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if err := o.CancelOrder(tt.args.ctx, tt.args.param); (err != nil) != tt.wantErr { + t.Errorf("CancelOrder() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOrderUseCase_CreateOrder(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param usecase.CreateOrderReq + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if err := o.CreateOrder(tt.args.ctx, tt.args.param); (err != nil) != tt.wantErr { + t.Errorf("CreateOrder() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOrderUseCase_DeleteOrder(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param usecase.DeleteOrderQuery + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if err := o.DeleteOrder(tt.args.ctx, tt.args.param); (err != nil) != tt.wantErr { + t.Errorf("DeleteOrder() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOrderUseCase_GetOrder(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param usecase.GetOrderQuery + } + tests := []struct { + name string + fields fields + args args + want *usecase.GetOrderResp + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + got, err := o.GetOrder(tt.args.ctx, tt.args.param) + if (err != nil) != tt.wantErr { + t.Errorf("GetOrder() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetOrder() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOrderUseCase_ListOrder(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param usecase.GetOrderListReq + } + tests := []struct { + name string + fields fields + args args + want *usecase.ListOrderResp + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + got, err := o.ListOrder(tt.args.ctx, tt.args.param) + if (err != nil) != tt.wantErr { + t.Errorf("ListOrder() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ListOrder() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestOrderUseCase_ModifyOrderStatus(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + param *usecase.ModifyOrderQuery + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if err := o.ModifyOrderStatus(tt.args.ctx, tt.args.param); (err != nil) != tt.wantErr { + t.Errorf("ModifyOrderStatus() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOrderUseCase_OrderStatusTimeout(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + ctx context.Context + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if err := o.OrderStatusTimeout(tt.args.ctx); (err != nil) != tt.wantErr { + t.Errorf("OrderStatusTimeout() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestOrderUseCase_convertOrdersToResponses(t *testing.T) { + type fields struct { + OrderModel model.OrderModel + } + type args struct { + orders []model.Order + } + tests := []struct { + name string + fields fields + args args + want []*usecase.GetOrderResp + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + o := &OrderUseCase{ + OrderModel: tt.fields.OrderModel, + } + if got := o.convertOrdersToResponses(tt.args.orders); !reflect.DeepEqual(got, tt.want) { + t.Errorf("convertOrdersToResponses() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/internal/usecase/utils.go b/internal/usecase/utils.go new file mode 100644 index 0000000..cd31945 --- /dev/null +++ b/internal/usecase/utils.go @@ -0,0 +1,31 @@ +package usecase + +import "github.com/shopspring/decimal" + +// Int64Ptr 將 int64 類型轉為 *int64,若值為 0 則返回 nil +func Int64Ptr(val int64) *int64 { + if val == 0 { + return nil + } + + return &val +} + +// DecimalToStringPtr 將 decimal.Decimal 指標轉換為 *string,若為 nil 則返回 nil +func DecimalToStringPtr(val *decimal.Decimal) *string { + if val == nil { + return nil + } + str := val.String() + + return &str +} + +// StringPtr 將 *string 或其他欄位直接返回(適合用於已是指標的欄位) +func StringPtr(val string) *string { + if val == "" { + return nil + } + + return &val +}