package orderservicelogic import ( "app-cloudep-order-server/gen_result/pb/order" "app-cloudep-order-server/internal/domain" model "app-cloudep-order-server/internal/model/mongo" "context" "fmt" "time" ers "code.30cm.net/digimon/library-go/errs" "github.com/shopspring/decimal" "app-cloudep-order-server/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) type CreateOrderLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic { return &CreateOrderLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } type createOrderReq struct { // 訂單ID BusinessID string `json:"business_id" validate:"required"` // 訂單業務流水號 OrderType int8 `json:"order_type" validate:"required"` // 訂單類型 OrderStatus int8 `json:"order_status" validate:"oneof=0 1 2 3 4 5 6 7 8 9 10 11"` // 訂單狀態 Brand string `json:"brand" validate:"required"` // 下單平台 OrderUID string `json:"order_uid" validate:"required"` // 下單用戶 UID ReferenceID string `json:"reference_id" validate:"required"` // 訂單來源 Count decimal.Decimal `json:"count" validate:"required,decimalGt=0"` // 訂單數量 OrderFee decimal.Decimal `json:"order_fee" validate:"required,decimalGte=0"` // 訂單手續費 Amount decimal.Decimal `json:"amount" validate:"required,decimalGte=0"` // 單價 ReferenceBrand *string `json:"reference_brand,omitempty" validate:"omitempty"` // 訂單來源平台 ReferenceUID *string `json:"reference_uid,omitempty" validate:"omitempty"` // 訂單來源用戶 UID WalletStatus *int64 `json:"wallet_status,omitempty" validate:"omitempty,oneof=1 2 3 4 5 6 7"` // 交易金額狀態 ThreePartyStatus *int64 `json:"three_party_status,omitempty" validate:"omitempty,oneof=1 2 3"` // 三方請求狀態 DirectionType *int64 `json:"direction_type,omitempty" validate:"omitempty,oneof=1 2"` // 交易方向 CryptoType *string `json:"crypto_type,omitempty" validate:"omitempty"` // 交易幣種 ThirdPartyFee *decimal.Decimal `json:"third_party_fee,omitempty" validate:"omitempty,decimalGte=0"` // 第三方手續費 CryptoToUSDTRate *decimal.Decimal `json:"crypto_to_usdt_rate,omitempty" validate:"omitempty,decimalGte=0"` // 交易幣種對 USDT 匯率 FiatToUSDRate *decimal.Decimal `json:"fiat_to_usd_rate,omitempty" validate:"omitempty,decimalGte=0"` // 法幣對 USD 匯率 FeeCryptoToUSDTRate *decimal.Decimal `json:"fee_crypto_to_usdt_rate,omitempty" validate:"omitempty,decimalGte=0"` // 手續費幣種對 USDT 匯率 USDTToCryptoTypeRate *decimal.Decimal `json:"usdt_to_crypto_type_rate,omitempty" validate:"omitempty,decimalGte=0"` // USDT 對交易幣種匯率 PaymentFiat *string `json:"payment_fiat,omitempty" validate:"omitempty"` // 支付法幣 PaymentUnitPrice *decimal.Decimal `json:"payment_unit_price,omitempty" validate:"omitempty,decimalGte=0"` // crypto 單價 PaymentTemplateID *string `json:"payment_template_id,omitempty" validate:"omitempty"` // 支付方式配置 ID OrderArrivalTime *int64 `json:"order_arrival_time,omitempty" validate:"omitempty"` // 訂單到帳時間 OrderPaymentTime *int64 `json:"order_payment_time,omitempty" validate:"omitempty"` // 訂單付款時間 UnpaidTimeoutSecond *int64 `json:"unpaid_timeout_second,omitempty" validate:"omitempty,decimalGte=0"` // 支付期限秒數 ChainType *string `json:"chain_type,omitempty" validate:"omitempty"` // 主網類型 TxHash *string `json:"tx_hash,omitempty" validate:"omitempty"` // 交易哈希 FromAddress *string `json:"from_address,omitempty" validate:"omitempty"` // 來源地址 ToAddress *string `json:"to_address,omitempty" validate:"omitempty"` // 目標地址 ChainFee *decimal.Decimal `json:"chain_fee,omitempty" validate:"omitempty,decimalGte=0"` // 鏈上交易手續費 ChainFeeCrypto *string `json:"chain_fee_crypto,omitempty" validate:"omitempty"` // 鏈上手續費使用幣別 Memo *string `json:"memo,omitempty" validate:"omitempty"` // 鏈上備註 OrderNote *string `json:"order_note,omitempty" validate:"omitempty"` } // CreateOrder 建立訂單 func (l *CreateOrderLogic) CreateOrder(in *order.CreateOrderReq) (*order.OKResp, error) { req, err := buildCreateOrderReq(in) if err != nil { // 錯誤代碼 06-011-00 fmt.Println("1", err) return nil, ers.InvalidFormat(err.Error()) } fmt.Println(req) // 驗證資料 if err := l.svcCtx.Validate.ValidateAll(req); err != nil { // 錯誤代碼 06-011-00 fmt.Println("2", err) return nil, ers.InvalidFormat(err.Error()) } fmt.Println(req) now := time.Now().UTC().UnixNano() // 插入資料庫 o := &model.Order{ UpdateTime: now, CreateTime: now, BusinessID: req.BusinessID, OrderType: req.OrderType, OrderStatus: req.OrderStatus, Brand: req.Brand, OrderUID: req.OrderUID, ReferenceID: req.ReferenceID, Count: req.Count, OrderFee: req.OrderFee, Amount: req.Amount, // 下面的是未來擴充用,加密貨幣用,或者幣別轉換用,普通訂單用不到 ReferenceBrand: req.ReferenceBrand, ReferenceUID: req.ReferenceUID, WalletStatus: req.WalletStatus, ThreePartyStatus: req.ThreePartyStatus, DirectionType: req.DirectionType, CryptoType: req.CryptoType, ThirdPartyFee: req.ThirdPartyFee, CryptoToUSDTRate: req.CryptoToUSDTRate, FiatToUSDRate: req.FiatToUSDRate, FeeCryptoToUSDTRate: req.FeeCryptoToUSDTRate, USDTToCryptoTypeRate: req.USDTToCryptoTypeRate, PaymentFiat: req.PaymentFiat, PaymentUnitPrice: req.PaymentUnitPrice, PaymentTemplateID: req.PaymentTemplateID, OrderArrivalTime: req.OrderArrivalTime, OrderPaymentTime: req.OrderPaymentTime, UnpaidTimeoutSecond: req.UnpaidTimeoutSecond, ChainType: req.ChainType, TxHash: req.TxHash, FromAddress: req.FromAddress, ToAddress: req.ToAddress, ChainFee: req.ChainFee, ChainFeeCrypto: req.ChainFeeCrypto, Memo: req.Memo, OrderNote: req.OrderNote, } err = l.svcCtx.OrderModel.Insert(l.ctx, o) if err != nil { // 錯誤代碼 06-021-01 e := domain.CommentErrorL( domain.CreateOrderErrorCode, logx.WithContext(l.ctx), []logx.LogField{ {Key: "req", Value: in}, {Key: "func", Value: "OrderModel.Insert"}, {Key: "err", Value: err}, }, "failed to insert order into mongo:").Wrap(err) return nil, e } return &order.OKResp{}, nil } //nolint:gocyclo,gocognit func buildCreateOrderReq(in *order.CreateOrderReq) (*createOrderReq, error) { createOrderReq := &createOrderReq{ BusinessID: in.BusinessId, OrderType: int8(in.OrderType), OrderStatus: int8(in.OrderStatus), Brand: in.Brand, OrderUID: in.OrderUid, ReferenceID: in.ReferenceId, } var err error // 只有當 Count, OrderFee, Amount 不為空時才進行轉換和設置 if in.Count != "" { createOrderReq.Count, err = decimal.NewFromString(in.Count) if err != nil { return nil, err } } if in.OrderFee != "" { createOrderReq.OrderFee, err = decimal.NewFromString(in.OrderFee) if err != nil { return nil, err } } if in.Amount != "" { createOrderReq.Amount, err = decimal.NewFromString(in.Amount) if err != nil { return nil, err } } // 判斷可選字段,只有不為 nil 才設置 if in.ReferenceBrand != nil { createOrderReq.ReferenceBrand = in.ReferenceBrand } if in.ReferenceUid != nil { createOrderReq.ReferenceUID = in.ReferenceUid } if in.WalletStatus != nil { createOrderReq.WalletStatus = in.WalletStatus } if in.ThreePartyStatus != nil { createOrderReq.ThreePartyStatus = in.ThreePartyStatus } if in.DirectionType != nil { createOrderReq.DirectionType = in.DirectionType } if in.CryptoType != nil { createOrderReq.CryptoType = in.CryptoType } if in.ThirdPartyFee != nil && *in.ThirdPartyFee != "" { createOrderReq.ThirdPartyFee = decimalPtrFromString(*in.ThirdPartyFee) } if in.CryptoToUsdtRate != nil && *in.CryptoToUsdtRate != "" { createOrderReq.CryptoToUSDTRate = decimalPtrFromString(*in.CryptoToUsdtRate) } if in.FiatToUsdRate != nil && *in.FiatToUsdRate != "" { createOrderReq.FiatToUSDRate = decimalPtrFromString(*in.FiatToUsdRate) } if in.FeeCryptoToUsdtRate != nil && *in.FeeCryptoToUsdtRate != "" { createOrderReq.FeeCryptoToUSDTRate = decimalPtrFromString(*in.FeeCryptoToUsdtRate) } if in.UsdtToCryptoTypeRate != nil && *in.UsdtToCryptoTypeRate != "" { createOrderReq.USDTToCryptoTypeRate = decimalPtrFromString(*in.UsdtToCryptoTypeRate) } if in.PaymentFiat != nil { createOrderReq.PaymentFiat = in.PaymentFiat } if in.PaymentUnitPrice != nil && *in.PaymentUnitPrice != "" { createOrderReq.PaymentUnitPrice = decimalPtrFromString(*in.PaymentUnitPrice) } if in.PaymentTemplateId != nil { createOrderReq.PaymentTemplateID = in.PaymentTemplateId } if in.OrderArrivalTime != nil { createOrderReq.OrderArrivalTime = in.OrderArrivalTime } if in.OrderPaymentTime != nil { createOrderReq.OrderPaymentTime = in.OrderPaymentTime } if in.UnpaidTimeoutSecond != nil { createOrderReq.UnpaidTimeoutSecond = in.UnpaidTimeoutSecond } if in.ChainType != nil { createOrderReq.ChainType = in.ChainType } if in.TxHash != nil { createOrderReq.TxHash = in.TxHash } if in.FromAddress != nil { createOrderReq.FromAddress = in.FromAddress } if in.ToAddress != nil { createOrderReq.ToAddress = in.ToAddress } if in.ChainFee != nil && *in.ChainFee != "" { createOrderReq.ChainFee = decimalPtrFromString(*in.ChainFee) } if in.ChainFeeCrypto != nil { createOrderReq.ChainFeeCrypto = in.ChainFeeCrypto } if in.Memo != nil { createOrderReq.Memo = in.Memo } if in.OrderNote != nil { createOrderReq.OrderNote = in.OrderNote } return createOrderReq, nil } // Helper function for decimal conversion with nil support func decimalPtrFromString(val string) *decimal.Decimal { if val == "" { return nil } dec, err := decimal.NewFromString(val) if err != nil { return nil } return &dec }