package sresponse import ( "net/http" "github.com/tech/sendico/pkg/api/http/response" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/model" feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1" paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1" oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1" orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1" ) type FeeLine struct { LedgerAccountRef string `json:"ledgerAccountRef,omitempty"` Amount *model.Money `json:"amount,omitempty"` LineType string `json:"lineType,omitempty"` Side string `json:"side,omitempty"` Meta map[string]string `json:"meta,omitempty"` } type FxQuote struct { QuoteRef string `json:"quoteRef,omitempty"` BaseCurrency string `json:"baseCurrency,omitempty"` QuoteCurrency string `json:"quoteCurrency,omitempty"` Side string `json:"side,omitempty"` Price string `json:"price,omitempty"` BaseAmount *model.Money `json:"baseAmount,omitempty"` QuoteAmount *model.Money `json:"quoteAmount,omitempty"` ExpiresAtUnixMs int64 `json:"expiresAtUnixMs,omitempty"` Provider string `json:"provider,omitempty"` RateRef string `json:"rateRef,omitempty"` Firm bool `json:"firm,omitempty"` } type PaymentQuote struct { QuoteRef string `json:"quoteRef,omitempty"` DebitAmount *model.Money `json:"debitAmount,omitempty"` ExpectedSettlementAmount *model.Money `json:"expectedSettlementAmount,omitempty"` ExpectedFeeTotal *model.Money `json:"expectedFeeTotal,omitempty"` FeeLines []FeeLine `json:"feeLines,omitempty"` FxQuote *FxQuote `json:"fxQuote,omitempty"` } type PaymentQuoteAggregate struct { DebitAmounts []*model.Money `json:"debitAmounts,omitempty"` ExpectedSettlementAmounts []*model.Money `json:"expectedSettlementAmounts,omitempty"` ExpectedFeeTotals []*model.Money `json:"expectedFeeTotals,omitempty"` } type PaymentQuotes struct { QuoteRef string `json:"quoteRef,omitempty"` Aggregate *PaymentQuoteAggregate `json:"aggregate,omitempty"` Quotes []PaymentQuote `json:"quotes,omitempty"` } type Payment struct { PaymentRef string `json:"paymentRef,omitempty"` IdempotencyKey string `json:"idempotencyKey,omitempty"` State string `json:"state,omitempty"` FailureCode string `json:"failureCode,omitempty"` FailureReason string `json:"failureReason,omitempty"` LastQuote *PaymentQuote `json:"lastQuote,omitempty"` } type paymentQuoteResponse struct { authResponse `json:",inline"` Quote *PaymentQuote `json:"quote"` } type paymentQuotesResponse struct { authResponse `json:",inline"` Quote *PaymentQuotes `json:"quote"` } type paymentsResponse struct { authResponse `json:",inline"` Payments []Payment `json:"payments"` Page *paginationv1.CursorPageResponse `json:"page,omitempty"` } type paymentResponse struct { authResponse `json:",inline"` Payment *Payment `json:"payment"` } // PaymentQuote wraps a payment quote with refreshed access token. func PaymentQuoteResponse(logger mlogger.Logger, quote *orchestratorv1.PaymentQuote, token *TokenData) http.HandlerFunc { return response.Ok(logger, paymentQuoteResponse{ Quote: toPaymentQuote(quote), authResponse: authResponse{AccessToken: *token}, }) } // PaymentQuotes wraps batch quotes with refreshed access token. func PaymentQuotesResponse(logger mlogger.Logger, resp *orchestratorv1.QuotePaymentsResponse, token *TokenData) http.HandlerFunc { return response.Ok(logger, paymentQuotesResponse{ Quote: toPaymentQuotes(resp), authResponse: authResponse{AccessToken: *token}, }) } // Payments wraps a list of payments with refreshed access token. func PaymentsResponse(logger mlogger.Logger, payments []*orchestratorv1.Payment, token *TokenData) http.HandlerFunc { return response.Ok(logger, paymentsResponse{ Payments: toPayments(payments), authResponse: authResponse{AccessToken: *token}, }) } // PaymentsList wraps a list of payments with refreshed access token and pagination data. func PaymentsListResponse(logger mlogger.Logger, resp *orchestratorv1.ListPaymentsResponse, token *TokenData) http.HandlerFunc { return response.Ok(logger, paymentsResponse{ Payments: toPayments(resp.GetPayments()), Page: resp.GetPage(), authResponse: authResponse{AccessToken: *token}, }) } // Payment wraps a payment with refreshed access token. func PaymentResponse(logger mlogger.Logger, payment *orchestratorv1.Payment, token *TokenData) http.HandlerFunc { return response.Ok(logger, paymentResponse{ Payment: toPayment(payment), authResponse: authResponse{AccessToken: *token}, }) } func toFeeLines(lines []*feesv1.DerivedPostingLine) []FeeLine { if len(lines) == 0 { return nil } result := make([]FeeLine, 0, len(lines)) for _, line := range lines { if line == nil { continue } result = append(result, FeeLine{ LedgerAccountRef: line.GetLedgerAccountRef(), Amount: toMoney(line.GetMoney()), LineType: line.GetLineType().String(), Side: line.GetSide().String(), Meta: line.GetMeta(), }) } if len(result) == 0 { return nil } return result } func toFxQuote(q *oraclev1.Quote) *FxQuote { if q == nil { return nil } pair := q.GetPair() base := "" quote := "" if pair != nil { base = pair.GetBase() quote = pair.GetQuote() } return &FxQuote{ QuoteRef: q.GetQuoteRef(), BaseCurrency: base, QuoteCurrency: quote, Side: q.GetSide().String(), Price: q.GetPrice().GetValue(), BaseAmount: toMoney(q.GetBaseAmount()), QuoteAmount: toMoney(q.GetQuoteAmount()), ExpiresAtUnixMs: q.GetExpiresAtUnixMs(), Provider: q.GetProvider(), RateRef: q.GetRateRef(), Firm: q.GetFirm(), } } func toPaymentQuote(q *orchestratorv1.PaymentQuote) *PaymentQuote { if q == nil { return nil } return &PaymentQuote{ QuoteRef: q.GetQuoteRef(), DebitAmount: toMoney(q.GetDebitAmount()), ExpectedSettlementAmount: toMoney(q.GetExpectedSettlementAmount()), ExpectedFeeTotal: toMoney(q.GetExpectedFeeTotal()), FeeLines: toFeeLines(q.GetFeeLines()), FxQuote: toFxQuote(q.GetFxQuote()), } } func toPaymentQuoteAggregate(q *orchestratorv1.PaymentQuoteAggregate) *PaymentQuoteAggregate { if q == nil { return nil } return &PaymentQuoteAggregate{ DebitAmounts: toMoneyList(q.GetDebitAmounts()), ExpectedSettlementAmounts: toMoneyList(q.GetExpectedSettlementAmounts()), ExpectedFeeTotals: toMoneyList(q.GetExpectedFeeTotals()), } } func toPaymentQuotes(resp *orchestratorv1.QuotePaymentsResponse) *PaymentQuotes { if resp == nil { return nil } quotes := make([]PaymentQuote, 0, len(resp.GetQuotes())) for _, quote := range resp.GetQuotes() { if dto := toPaymentQuote(quote); dto != nil { quotes = append(quotes, *dto) } } if len(quotes) == 0 { quotes = nil } return &PaymentQuotes{ QuoteRef: resp.GetQuoteRef(), Aggregate: toPaymentQuoteAggregate(resp.GetAggregate()), Quotes: quotes, } } func toPayments(items []*orchestratorv1.Payment) []Payment { if len(items) == 0 { return nil } result := make([]Payment, 0, len(items)) for _, item := range items { if p := toPayment(item); p != nil { result = append(result, *p) } } if len(result) == 0 { return nil } return result } func toPayment(p *orchestratorv1.Payment) *Payment { if p == nil { return nil } return &Payment{ PaymentRef: p.GetPaymentRef(), IdempotencyKey: p.GetIdempotencyKey(), State: p.GetState().String(), FailureCode: p.GetFailureCode().String(), FailureReason: p.GetFailureReason(), LastQuote: toPaymentQuote(p.GetLastQuote()), } }