add order usecase
This commit is contained in:
parent
799fc0bf9d
commit
67ccb9433c
|
@ -2,8 +2,8 @@ package domain
|
||||||
|
|
||||||
type OrderStatus int64
|
type OrderStatus int64
|
||||||
|
|
||||||
func (o *OrderStatus) ToInt() int {
|
func (o *OrderStatus) ToInt64() int64 {
|
||||||
return int(*o)
|
return int64(*o)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -20,3 +20,9 @@ const (
|
||||||
OrderStatusAbnormal OrderStatus = 10 // 交易異常
|
OrderStatusAbnormal OrderStatus = 10 // 交易異常
|
||||||
OrderStatusTimeout OrderStatus = 11 // 交易超時
|
OrderStatusTimeout OrderStatus = 11 // 交易超時
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OrderType int64
|
||||||
|
|
||||||
|
func (o *OrderType) ToInt() int {
|
||||||
|
return int(*o)
|
||||||
|
}
|
||||||
|
|
|
@ -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 // 訂單交易備註
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -4,11 +4,12 @@ import (
|
||||||
"app-cloudep-trade-service/internal/domain"
|
"app-cloudep-trade-service/internal/domain"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/stores/mon"
|
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ OrderModel = (*customOrderModel)(nil)
|
var _ OrderModel = (*customOrderModel)(nil)
|
||||||
|
@ -46,8 +47,8 @@ type (
|
||||||
BusinessID string `json:"business_id"`
|
BusinessID string `json:"business_id"`
|
||||||
UID string `json:"uid"`
|
UID string `json:"uid"`
|
||||||
OrderType int `json:"order_type"`
|
OrderType int `json:"order_type"`
|
||||||
DirectionType []int32 `json:"direction_type"`
|
DirectionType []int64 `json:"direction_type"`
|
||||||
OrderStatus []int32 `json:"order_status"`
|
OrderStatus []int64 `json:"order_status"`
|
||||||
|
|
||||||
StartCreateTime int64 `json:"start_create_time"`
|
StartCreateTime int64 `json:"start_create_time"`
|
||||||
EndCreateTime int64 `json:"end_create_time"`
|
EndCreateTime int64 `json:"end_create_time"`
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"app-cloudep-trade-service/internal/domain"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
)
|
)
|
||||||
|
@ -10,8 +12,8 @@ type Order struct {
|
||||||
UpdateTime int64 `bson:"update_time"`
|
UpdateTime int64 `bson:"update_time"`
|
||||||
CreateTime int64 `bson:"create_time"`
|
CreateTime int64 `bson:"create_time"`
|
||||||
BusinessID string `bson:"business_id"` // 訂單業務流水號
|
BusinessID string `bson:"business_id"` // 訂單業務流水號
|
||||||
OrderType int8 `bson:"order_type"` // 訂單類型
|
OrderType domain.OrderType `bson:"order_type"` // 訂單類型
|
||||||
OrderStatus int8 `bson:"order_status"` // 訂單狀態
|
OrderStatus domain.OrderStatus `bson:"order_status"` // 訂單狀態
|
||||||
Brand string `bson:"brand"` // 下單平台
|
Brand string `bson:"brand"` // 下單平台
|
||||||
OrderUID string `bson:"order_uid"` // 下單用戶 UID
|
OrderUID string `bson:"order_uid"` // 下單用戶 UID
|
||||||
ReferenceID string `bson:"reference_id"` // 訂單來源
|
ReferenceID string `bson:"reference_id"` // 訂單來源
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue