propagated payment commentto bff
This commit is contained in:
@@ -51,6 +51,7 @@ type StepShell struct {
|
||||
InstanceID string `bson:"instanceId,omitempty" json:"instanceId,omitempty"`
|
||||
ReportVisibility model.ReportVisibility `bson:"reportVisibility,omitempty" json:"reportVisibility,omitempty"`
|
||||
UserLabel string `bson:"userLabel,omitempty" json:"userLabel,omitempty"`
|
||||
Comment string `bson:"comment,omitempty" json:"comment,omitempty"`
|
||||
PlannedMoney *paymenttypes.Money `bson:"plannedMoney,omitempty" json:"plannedMoney,omitempty"`
|
||||
PlannedConvertedMoney *paymenttypes.Money `bson:"plannedConvertedMoney,omitempty" json:"plannedConvertedMoney,omitempty"`
|
||||
}
|
||||
@@ -64,6 +65,7 @@ type StepExecution struct {
|
||||
InstanceID string `bson:"instanceId,omitempty" json:"instanceId,omitempty"`
|
||||
ReportVisibility model.ReportVisibility `bson:"reportVisibility,omitempty" json:"reportVisibility,omitempty"`
|
||||
UserLabel string `bson:"userLabel,omitempty" json:"userLabel,omitempty"`
|
||||
Comment string `bson:"comment,omitempty" json:"comment,omitempty"`
|
||||
State StepState `bson:"state" json:"state"`
|
||||
Attempt uint32 `bson:"attempt" json:"attempt"`
|
||||
StartedAt *time.Time `bson:"startedAt,omitempty" json:"startedAt,omitempty"`
|
||||
|
||||
@@ -156,6 +156,7 @@ func buildInitialStepTelemetry(shell []StepShell) ([]StepExecution, error) {
|
||||
InstanceID: instanceID,
|
||||
ReportVisibility: visibility,
|
||||
UserLabel: userLabel,
|
||||
Comment: strings.TrimSpace(shell[i].Comment),
|
||||
State: StepStatePending,
|
||||
Attempt: 1,
|
||||
PlannedMoney: svcshared.CloneMoneyTrimNonEmpty(shell[i].PlannedMoney),
|
||||
|
||||
@@ -42,6 +42,7 @@ const (
|
||||
type PayoutTarget struct {
|
||||
TargetRef string `json:"target_ref,omitempty"`
|
||||
IntentRef []string `json:"intent_refs,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Amount *paymenttypes.Money `json:"amount,omitempty"`
|
||||
Card *model.CardEndpoint `json:"card,omitempty"`
|
||||
Customer *model.Customer `json:"customer,omitempty"`
|
||||
@@ -208,6 +209,7 @@ func normalizeTarget(target PayoutTarget, index int) PayoutTarget {
|
||||
target.TargetRef = "target-" + strconv.Itoa(index+1)
|
||||
}
|
||||
target.IntentRef = normalizeStringSlice(target.IntentRef)
|
||||
target.Comment = strings.TrimSpace(target.Comment)
|
||||
if target.Amount != nil {
|
||||
amount := strings.TrimSpace(target.Amount.Amount)
|
||||
currency := strings.ToUpper(strings.TrimSpace(target.Amount.Currency))
|
||||
|
||||
@@ -103,6 +103,7 @@ func cloneStepExecutions(src []agg.StepExecution) []agg.StepExecution {
|
||||
step.ReportVisibility = model.ReportVisibilityUnspecified
|
||||
}
|
||||
step.UserLabel = strings.TrimSpace(step.UserLabel)
|
||||
step.Comment = strings.TrimSpace(step.Comment)
|
||||
step.FailureCode = strings.TrimSpace(step.FailureCode)
|
||||
step.FailureMsg = strings.TrimSpace(step.FailureMsg)
|
||||
if step.Attempt == 0 {
|
||||
|
||||
@@ -529,6 +529,7 @@ func normalizePayment(payment *agg.Payment, requirePaymentRef bool) (*paymentDoc
|
||||
step := &doc.StepExecutions[i]
|
||||
step.StepRef = strings.TrimSpace(step.StepRef)
|
||||
step.StepCode = strings.TrimSpace(step.StepCode)
|
||||
step.Comment = strings.TrimSpace(step.Comment)
|
||||
step.FailureCode = strings.TrimSpace(step.FailureCode)
|
||||
step.FailureMsg = strings.TrimSpace(step.FailureMsg)
|
||||
if step.StepRef == "" {
|
||||
|
||||
@@ -36,7 +36,7 @@ func mapIntentSnapshot(src model.PaymentIntent) (*quotationv2.QuoteIntent, error
|
||||
SettlementMode: settlementMode,
|
||||
FeeTreatment: feeTreatment,
|
||||
SettlementCurrency: strings.ToUpper(strings.TrimSpace(src.SettlementCurrency)),
|
||||
Comment: strings.TrimSpace(src.Attributes["comment"]),
|
||||
Comment: strings.TrimSpace(src.Comment),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -271,9 +271,7 @@ func newPaymentFixture() *agg.Payment {
|
||||
SettlementMode: model.SettlementModeFixSource,
|
||||
FeeTreatment: model.FeeTreatmentDeductFromDestination,
|
||||
SettlementCurrency: "USD",
|
||||
Attributes: map[string]string{
|
||||
"comment": "invoice-7",
|
||||
},
|
||||
Comment: "invoice-7",
|
||||
},
|
||||
QuoteSnapshot: &model.PaymentQuoteSnapshot{
|
||||
DebitAmount: &paymenttypes.Money{
|
||||
|
||||
@@ -228,6 +228,7 @@ func toStepShells(graph *xplan.Graph, intent model.PaymentIntent, quote *model.P
|
||||
InstanceID: graph.Steps[i].InstanceID,
|
||||
ReportVisibility: graph.Steps[i].Visibility,
|
||||
UserLabel: graph.Steps[i].UserLabel,
|
||||
Comment: graph.Steps[i].Comment,
|
||||
PlannedMoney: plannedMoney,
|
||||
PlannedConvertedMoney: plannedConverted,
|
||||
})
|
||||
|
||||
@@ -320,6 +320,7 @@ func buildBatchPayoutTargets(group opagg.Group) []batchmeta.PayoutTarget {
|
||||
target := batchmeta.PayoutTarget{
|
||||
TargetRef: firstNonEmpty(strings.TrimSpace(member.IntentRef), "recipient-"+strconv.Itoa(i+1)),
|
||||
IntentRef: normalizeIntentRefs([]string{member.IntentRef}),
|
||||
Comment: strings.TrimSpace(member.IntentSnapshot.Comment),
|
||||
Amount: batchPayoutAmountFromMember(member),
|
||||
}
|
||||
if member.IntentSnapshot.Destination.Type == model.EndpointTypeCard && member.IntentSnapshot.Destination.Card != nil {
|
||||
@@ -344,6 +345,7 @@ func buildBatchPayoutTargets(group opagg.Group) []batchmeta.PayoutTarget {
|
||||
target := batchmeta.PayoutTarget{
|
||||
TargetRef: firstNonEmpty(strings.TrimSpace(group.RecipientKey), "recipient-1"),
|
||||
IntentRef: normalizeIntentRefs(group.IntentRefs),
|
||||
Comment: strings.TrimSpace(group.IntentSnapshot.Comment),
|
||||
Amount: batchPayoutAmount(group),
|
||||
}
|
||||
if group.IntentSnapshot.Destination.Type == model.EndpointTypeCard && group.IntentSnapshot.Destination.Card != nil {
|
||||
|
||||
@@ -80,11 +80,13 @@ func TestExecuteBatchPayment_CardBatchCreatesPerTargetPayoutStepsWithoutMerging(
|
||||
var (
|
||||
targetRefs []string
|
||||
amounts []string
|
||||
comments []string
|
||||
)
|
||||
env := newTestEnv(t, func(kind string, req sexec.StepRequest) (*sexec.ExecuteOutput, error) {
|
||||
if kind == "card_payout" {
|
||||
targetRefs = append(targetRefs, req.Step.Metadata[batchmeta.MetaPayoutTargetRef])
|
||||
amounts = append(amounts, req.Step.Metadata[batchmeta.MetaAmount])
|
||||
comments = append(comments, req.Step.Comment)
|
||||
}
|
||||
step := req.StepExecution
|
||||
step.State = agg.StepStateCompleted
|
||||
@@ -116,15 +118,22 @@ func TestExecuteBatchPayment_CardBatchCreatesPerTargetPayoutStepsWithoutMerging(
|
||||
if got, want := len(amounts), 2; got != want {
|
||||
t.Fatalf("expected %d card payout amounts, got=%d", want, got)
|
||||
}
|
||||
if got, want := len(comments), 2; got != want {
|
||||
t.Fatalf("expected %d card payout comments, got=%d", want, got)
|
||||
}
|
||||
|
||||
sort.Strings(targetRefs)
|
||||
sort.Strings(amounts)
|
||||
sort.Strings(comments)
|
||||
if targetRefs[0] == targetRefs[1] {
|
||||
t.Fatalf("expected distinct target refs, got=%v", targetRefs)
|
||||
}
|
||||
if got, want := amounts, []string{"100", "150"}; got[0] != want[0] || got[1] != want[1] {
|
||||
t.Fatalf("amount overrides mismatch: got=%v want=%v", got, want)
|
||||
}
|
||||
if got, want := comments, []string{"batch-comment-a", "batch-comment-b"}; got[0] != want[0] || got[1] != want[1] {
|
||||
t.Fatalf("comment overrides mismatch: got=%v want=%v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteBatchPayment_CryptoPolicyMergesByDestination(t *testing.T) {
|
||||
@@ -343,9 +352,10 @@ func newExecutableBatchCardQuoteDiffDest(orgRef bson.ObjectID, quoteRef string)
|
||||
Items: []*model.PaymentQuoteItemV2{
|
||||
{
|
||||
Intent: &model.PaymentIntent{
|
||||
Ref: "intent-a",
|
||||
Kind: model.PaymentKindPayout,
|
||||
Source: testLedgerEndpoint("ledger-src"),
|
||||
Ref: "intent-a",
|
||||
Kind: model.PaymentKindPayout,
|
||||
Comment: "batch-comment-a",
|
||||
Source: testLedgerEndpoint("ledger-src"),
|
||||
Destination: model.PaymentEndpoint{
|
||||
Type: model.EndpointTypeCard,
|
||||
Card: &model.CardEndpoint{
|
||||
@@ -372,9 +382,10 @@ func newExecutableBatchCardQuoteDiffDest(orgRef bson.ObjectID, quoteRef string)
|
||||
},
|
||||
{
|
||||
Intent: &model.PaymentIntent{
|
||||
Ref: "intent-b",
|
||||
Kind: model.PaymentKindPayout,
|
||||
Source: testLedgerEndpoint("ledger-src"),
|
||||
Ref: "intent-b",
|
||||
Kind: model.PaymentKindPayout,
|
||||
Comment: "batch-comment-b",
|
||||
Source: testLedgerEndpoint("ledger-src"),
|
||||
Destination: model.PaymentEndpoint{
|
||||
Type: model.EndpointTypeCard,
|
||||
Card: &model.CardEndpoint{
|
||||
|
||||
@@ -325,6 +325,7 @@ func normalizeExecutorOutput(current agg.StepExecution, out *sexec.ExecuteOutput
|
||||
if out.StepExecution.Attempt != 0 {
|
||||
next.Attempt = out.StepExecution.Attempt
|
||||
}
|
||||
next.Comment = strings.TrimSpace(out.StepExecution.Comment)
|
||||
next.ExternalRefs = out.StepExecution.ExternalRefs
|
||||
next.ExecutedMoney = svcshared.CloneMoneyTrimNonEmpty(out.StepExecution.ExecutedMoney)
|
||||
next.ConvertedMoney = svcshared.CloneMoneyTrimNonEmpty(out.StepExecution.ConvertedMoney)
|
||||
@@ -431,6 +432,9 @@ func stepExecutionEqual(left, right agg.StepExecution) bool {
|
||||
if strings.TrimSpace(left.FailureMsg) != strings.TrimSpace(right.FailureMsg) {
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(left.Comment) != strings.TrimSpace(right.Comment) {
|
||||
return false
|
||||
}
|
||||
if !timePtrEqual(left.StartedAt, right.StartedAt) || !timePtrEqual(left.CompletedAt, right.CompletedAt) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ func validateInput(in ExecuteInput) (StepRequest, error) {
|
||||
func normalizeStep(step xplan.Step) (xplan.Step, error) {
|
||||
step.StepRef = strings.TrimSpace(step.StepRef)
|
||||
step.StepCode = strings.TrimSpace(step.StepCode)
|
||||
step.Comment = strings.TrimSpace(step.Comment)
|
||||
if step.StepRef == "" {
|
||||
return xplan.Step{}, merrors.InvalidArgument("step.step_ref is required")
|
||||
}
|
||||
@@ -126,6 +127,7 @@ func normalizeStep(step xplan.Step) (xplan.Step, error) {
|
||||
func normalizeStepExecution(exec agg.StepExecution, step xplan.Step) (agg.StepExecution, error) {
|
||||
exec.StepRef = strings.TrimSpace(exec.StepRef)
|
||||
exec.StepCode = strings.TrimSpace(exec.StepCode)
|
||||
exec.Comment = strings.TrimSpace(exec.Comment)
|
||||
if exec.StepRef == "" {
|
||||
exec.StepRef = step.StepRef
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ func (s *svc) prepareInput(in Input) (*preparedInput, error) {
|
||||
func normalizeGraphStep(step xplan.Step, index int) (xplan.Step, error) {
|
||||
step.StepRef = strings.TrimSpace(step.StepRef)
|
||||
step.StepCode = strings.TrimSpace(step.StepCode)
|
||||
step.Comment = strings.TrimSpace(step.Comment)
|
||||
if step.StepRef == "" {
|
||||
return xplan.Step{}, merrors.InvalidArgument("steps[" + itoa(index) + "].step_ref is required")
|
||||
}
|
||||
@@ -157,6 +158,9 @@ func (s *svc) normalizeStepExecutions(
|
||||
if strings.TrimSpace(exec.InstanceID) == "" {
|
||||
exec.InstanceID = strings.TrimSpace(step.InstanceID)
|
||||
}
|
||||
if strings.TrimSpace(exec.Comment) == "" {
|
||||
exec.Comment = strings.TrimSpace(step.Comment)
|
||||
}
|
||||
exec.ReportVisibility = effectiveStepVisibility(exec.ReportVisibility, stepsByRef[stepRef].Visibility)
|
||||
exec.UserLabel = firstNonEmpty(exec.UserLabel, stepsByRef[stepRef].UserLabel)
|
||||
cloned := cloneStepExecution(exec)
|
||||
@@ -168,6 +172,7 @@ func (s *svc) normalizeStepExecutions(
|
||||
func (s *svc) normalizeStepExecution(exec agg.StepExecution, index int) (agg.StepExecution, error) {
|
||||
exec.StepRef = strings.TrimSpace(exec.StepRef)
|
||||
exec.StepCode = strings.TrimSpace(exec.StepCode)
|
||||
exec.Comment = strings.TrimSpace(exec.Comment)
|
||||
exec.FailureCode = strings.TrimSpace(exec.FailureCode)
|
||||
exec.FailureMsg = strings.TrimSpace(exec.FailureMsg)
|
||||
exec.UserLabel = strings.TrimSpace(exec.UserLabel)
|
||||
@@ -220,6 +225,7 @@ func seedMissingExecutions(
|
||||
Rail: step.Rail,
|
||||
Gateway: strings.TrimSpace(step.Gateway),
|
||||
InstanceID: strings.TrimSpace(step.InstanceID),
|
||||
Comment: strings.TrimSpace(step.Comment),
|
||||
ReportVisibility: effectiveStepVisibility(model.ReportVisibilityUnspecified, step.Visibility),
|
||||
UserLabel: strings.TrimSpace(step.UserLabel),
|
||||
State: agg.StepStatePending,
|
||||
|
||||
@@ -14,11 +14,13 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche
|
||||
targetsRaw, err := batchmeta.EncodePayoutTargets([]batchmeta.PayoutTarget{
|
||||
{
|
||||
TargetRef: "recipient-1",
|
||||
Comment: "batch-comment-1",
|
||||
Amount: &paymenttypes.Money{Amount: "100", Currency: "RUB"},
|
||||
Card: &model.CardEndpoint{Pan: "2200700142860161", ExpMonth: 3, ExpYear: 2030},
|
||||
},
|
||||
{
|
||||
TargetRef: "recipient-2",
|
||||
Comment: "batch-comment-2",
|
||||
Amount: &paymenttypes.Money{Amount: "150", Currency: "RUB"},
|
||||
Card: &model.CardEndpoint{Pan: "2200700142860162", ExpMonth: 4, ExpYear: 2030},
|
||||
},
|
||||
@@ -69,6 +71,7 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche
|
||||
}
|
||||
|
||||
seenTargets := map[string]string{}
|
||||
seenComments := map[string]string{}
|
||||
for i := range sendSteps {
|
||||
step := sendSteps[i]
|
||||
if got, want := step.DependsOn, []string{graph.Steps[0].StepRef}; !equalStringSlice(got, want) {
|
||||
@@ -76,10 +79,12 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche
|
||||
}
|
||||
targetRef := step.Metadata[batchmeta.MetaPayoutTargetRef]
|
||||
amount := step.Metadata[batchmeta.MetaAmount]
|
||||
if targetRef == "" || amount == "" {
|
||||
t.Fatalf("expected target metadata on send step, got=%v", step.Metadata)
|
||||
comment := step.Comment
|
||||
if targetRef == "" || amount == "" || comment == "" {
|
||||
t.Fatalf("expected target fields on send step, metadata=%v comment=%q", step.Metadata, step.Comment)
|
||||
}
|
||||
seenTargets[targetRef] = amount
|
||||
seenComments[targetRef] = comment
|
||||
}
|
||||
if got, want := seenTargets["recipient-1"], "100"; got != want {
|
||||
t.Fatalf("recipient-1 amount mismatch: got=%q want=%q", got, want)
|
||||
@@ -87,4 +92,10 @@ func TestCompile_InternalToCard_WithBatchTargetsExpandsPerRecipientPayoutBranche
|
||||
if got, want := seenTargets["recipient-2"], "150"; got != want {
|
||||
t.Fatalf("recipient-2 amount mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if got, want := seenComments["recipient-1"], "batch-comment-1"; got != want {
|
||||
t.Fatalf("recipient-1 comment mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
if got, want := seenComments["recipient-2"], "batch-comment-2"; got != want {
|
||||
t.Fatalf("recipient-2 comment mismatch: got=%q want=%q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ func normalizeStep(step Step) Step {
|
||||
step.Gateway = strings.TrimSpace(step.Gateway)
|
||||
step.InstanceID = strings.TrimSpace(step.InstanceID)
|
||||
step.UserLabel = strings.TrimSpace(step.UserLabel)
|
||||
step.Comment = strings.TrimSpace(step.Comment)
|
||||
step.Visibility = model.NormalizeReportVisibility(step.Visibility)
|
||||
step.CommitPolicy = normalizeCommitPolicy(step.CommitPolicy)
|
||||
step.DependsOn = normalizeStringList(step.DependsOn)
|
||||
|
||||
@@ -21,12 +21,12 @@ func planFeeHops(
|
||||
return nil, err
|
||||
}
|
||||
if !hasFee {
|
||||
return nil, nil
|
||||
return map[string]struct{}{}, nil
|
||||
}
|
||||
|
||||
sourceHop, ok := sourceFeeHop(hops)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
return map[string]struct{}{}, nil
|
||||
}
|
||||
return map[string]struct{}{
|
||||
observedKey(sourceHop): {},
|
||||
|
||||
@@ -56,6 +56,7 @@ type Step struct {
|
||||
HopRole paymenttypes.QuoteRouteHopRole
|
||||
Visibility model.ReportVisibility
|
||||
UserLabel string
|
||||
Comment string
|
||||
CommitPolicy model.CommitPolicy
|
||||
CommitAfter []string
|
||||
Metadata map[string]string
|
||||
|
||||
@@ -123,14 +123,17 @@ func (s *svc) applyBatchCardPayoutBoundary(
|
||||
return merrors.InvalidArgument("intent_snapshot.attributes[" + batchmeta.AttrPayoutTargets + "]: card is required for each target")
|
||||
}
|
||||
targetMeta := batchmeta.StepMetadataForTarget(target, i)
|
||||
targetComment := strings.TrimSpace(target.Comment)
|
||||
|
||||
sendStep := makeRailSendStep(to, intent)
|
||||
sendStep.DependsOn = []string{blockRef}
|
||||
sendStep.Comment = targetComment
|
||||
sendStep.Metadata = cloneMetadata(targetMeta)
|
||||
sendRef := ex.appendBranch(sendStep)
|
||||
|
||||
observeStep := makeRailObserveStep(to, intent)
|
||||
observeStep.DependsOn = []string{sendRef}
|
||||
observeStep.Comment = targetComment
|
||||
observeStep.Metadata = cloneMetadata(targetMeta)
|
||||
observeRef := ex.appendBranch(observeStep)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user