+source currency pick fix +fx side propagation
This commit is contained in:
@@ -12,20 +12,13 @@ type PaymentQuoteRecord struct {
|
||||
storable.Base `bson:",inline" json:",inline"`
|
||||
model.OrganizationBoundBase `bson:",inline" json:",inline"`
|
||||
|
||||
QuoteRef string `bson:"quoteRef" json:"quoteRef"`
|
||||
IdempotencyKey string `bson:"idempotencyKey" json:"idempotencyKey"`
|
||||
Intent PaymentIntent `bson:"intent,omitempty" json:"intent,omitempty"`
|
||||
Intents []PaymentIntent `bson:"intents,omitempty" json:"intents,omitempty"`
|
||||
Quote *PaymentQuoteSnapshot `bson:"quote,omitempty" json:"quote,omitempty"`
|
||||
Quotes []*PaymentQuoteSnapshot `bson:"quotes,omitempty" json:"quotes,omitempty"`
|
||||
StatusV2 *QuoteStatusV2 `bson:"statusV2,omitempty" json:"statusV2,omitempty"`
|
||||
StatusesV2 []*QuoteStatusV2 `bson:"statusesV2,omitempty" json:"statusesV2,omitempty"`
|
||||
Plan *PaymentPlan `bson:"plan,omitempty" json:"plan,omitempty"`
|
||||
Plans []*PaymentPlan `bson:"plans,omitempty" json:"plans,omitempty"`
|
||||
ExecutionNote string `bson:"executionNote,omitempty" json:"executionNote,omitempty"`
|
||||
ExpiresAt time.Time `bson:"expiresAt" json:"expiresAt"`
|
||||
PurgeAt time.Time `bson:"purgeAt,omitempty" json:"purgeAt,omitempty"`
|
||||
Hash string `bson:"hash" json:"hash"`
|
||||
QuoteRef string `bson:"quoteRef" json:"quoteRef"`
|
||||
IdempotencyKey string `bson:"idempotencyKey" json:"idempotencyKey"`
|
||||
RequestShape QuoteRequestShape `bson:"requestShape,omitempty" json:"requestShape,omitempty"`
|
||||
Items []*PaymentQuoteItemV2 `bson:"items,omitempty" json:"items,omitempty"`
|
||||
ExpiresAt time.Time `bson:"expiresAt" json:"expiresAt"`
|
||||
PurgeAt time.Time `bson:"purgeAt,omitempty" json:"purgeAt,omitempty"`
|
||||
Hash string `bson:"hash" json:"hash"`
|
||||
}
|
||||
|
||||
// Collection implements storable.Storable.
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
package model
|
||||
|
||||
// QuoteRequestShape identifies the API surface that created the quote record.
|
||||
type QuoteRequestShape string
|
||||
|
||||
const (
|
||||
QuoteRequestShapeUnspecified QuoteRequestShape = "unspecified"
|
||||
QuoteRequestShapeSingle QuoteRequestShape = "single"
|
||||
QuoteRequestShapeBatch QuoteRequestShape = "batch"
|
||||
)
|
||||
|
||||
// QuoteState captures v2 quote state metadata for persistence.
|
||||
type QuoteState string
|
||||
|
||||
@@ -30,3 +39,10 @@ type QuoteStatusV2 struct {
|
||||
State QuoteState `bson:"state,omitempty" json:"state,omitempty"`
|
||||
BlockReason QuoteBlockReason `bson:"blockReason,omitempty" json:"blockReason,omitempty"`
|
||||
}
|
||||
|
||||
// PaymentQuoteItemV2 keeps one intent/quote/status tuple in a stable shape.
|
||||
type PaymentQuoteItemV2 struct {
|
||||
Intent *PaymentIntent `bson:"intent,omitempty" json:"intent,omitempty"`
|
||||
Quote *PaymentQuoteSnapshot `bson:"quote,omitempty" json:"quote,omitempty"`
|
||||
Status *QuoteStatusV2 `bson:"status,omitempty" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package store
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -90,25 +91,39 @@ func (q *Quotes) Create(ctx context.Context, quote *model.PaymentQuoteRecord) er
|
||||
if quote.IdempotencyKey == "" {
|
||||
return merrors.InvalidArgument("quotesStore: idempotency key is required")
|
||||
}
|
||||
quote.ExecutionNote = strings.TrimSpace(quote.ExecutionNote)
|
||||
quote.RequestShape = model.QuoteRequestShape(strings.TrimSpace(string(quote.RequestShape)))
|
||||
if quote.RequestShape == "" || quote.RequestShape == model.QuoteRequestShapeUnspecified {
|
||||
return merrors.InvalidArgument("quotesStore: request shape is required")
|
||||
}
|
||||
if len(quote.Items) == 0 {
|
||||
return merrors.InvalidArgument("quotesStore: items are required")
|
||||
}
|
||||
if quote.RequestShape == model.QuoteRequestShapeSingle && len(quote.Items) != 1 {
|
||||
return merrors.InvalidArgument("quotesStore: single shape requires exactly one item")
|
||||
}
|
||||
if quote.ExpiresAt.IsZero() {
|
||||
return merrors.InvalidArgument("quotesStore: expires_at is required")
|
||||
}
|
||||
if quote.PurgeAt.IsZero() || quote.PurgeAt.Before(quote.ExpiresAt) {
|
||||
quote.PurgeAt = quote.ExpiresAt.Add(q.retention)
|
||||
}
|
||||
if quote.Intent.Attributes != nil {
|
||||
for k, v := range quote.Intent.Attributes {
|
||||
quote.Intent.Attributes[k] = strings.TrimSpace(v)
|
||||
for i := range quote.Items {
|
||||
item := quote.Items[i]
|
||||
if item == nil {
|
||||
return merrors.InvalidArgument("quotesStore: items[" + strconv.Itoa(i) + "] is required")
|
||||
}
|
||||
}
|
||||
if len(quote.Intents) > 0 {
|
||||
for i := range quote.Intents {
|
||||
if quote.Intents[i].Attributes == nil {
|
||||
continue
|
||||
}
|
||||
for k, v := range quote.Intents[i].Attributes {
|
||||
quote.Intents[i].Attributes[k] = strings.TrimSpace(v)
|
||||
if item.Intent == nil {
|
||||
return merrors.InvalidArgument("quotesStore: items[" + strconv.Itoa(i) + "].intent is required")
|
||||
}
|
||||
if item.Quote == nil {
|
||||
return merrors.InvalidArgument("quotesStore: items[" + strconv.Itoa(i) + "].quote is required")
|
||||
}
|
||||
if item.Status == nil {
|
||||
return merrors.InvalidArgument("quotesStore: items[" + strconv.Itoa(i) + "].status is required")
|
||||
}
|
||||
if item.Intent.Attributes != nil {
|
||||
for k, v := range item.Intent.Attributes {
|
||||
item.Intent.Attributes[k] = strings.TrimSpace(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user