mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
- go.mod module path + all self-imports: github.com/formancehq/payments -> github.com/hanzo-fi/payments (1590 .go files / 3152 refs; 20 modules: root, pkg/client, pkg/domain, 18 ce/plugins). External dep kept: formancehq/go-libs. - plugins: each ce/plugins/* consumed a *published* pkg/domain; added local 'replace .../pkg/domain => ../../../pkg/domain' (consistent with root) so every standalone plugin module builds in-monorepo. compile-plugin.sh MOD var rebranded too. - branding: README, LICENSE (dual MIT+EE; upstream copyright retained + Hanzo added), goreleaser (release images -> registry.hanzo.ai/hanzo-fi, OCI labels, homepage), proto go_package, renovate, speakeasy gen.yaml, connector-template *.gotpl. - CI: removed Numary/Formance workflows + composite action; added canonical hanzo.yml + cicd.yml (hanzoai/ci, gated HANZO_CI_ENABLED) + secretless ci.yml (go build/vet). - kept as data/compat keys: wire capability enums ALLOW_FORMANCE_*, generated SDK type client.Formance, domain field FormanceRedirectURL, OTEL_SERVICE_NAME, upstream base image. - verified: go build ./... (default + -tags ee) + all 20 nested modules green.
118 lines
3.5 KiB
Go
118 lines
3.5 KiB
Go
package mappers
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hanzo-fi/payments/ee/plugins/routable/client"
|
|
)
|
|
|
|
// TestPayableMetadata_AliasKeys locks in the correlation contract
|
|
// documented in MAPPINGS.md §5.5: every synced Payment must carry the
|
|
// Routable payable UUID under MetadataKeyRoutablePayableID, and the
|
|
// originating PI reference under MetadataKeyPaymentInitiationReference
|
|
// (when external_id is present).
|
|
func TestPayableMetadata_AliasKeys(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
payable client.Payable
|
|
wantPIRef string // expected value for payment_initiation_reference (empty = absent)
|
|
wantPayable string // expected value for payable_id
|
|
}{
|
|
{
|
|
name: "with external_id (Formance-initiated)",
|
|
payable: client.Payable{
|
|
ID: "pa_abc123",
|
|
ExternalID: "pi_xyz",
|
|
Type: "ach",
|
|
},
|
|
wantPIRef: "pi_xyz",
|
|
wantPayable: "pa_abc123",
|
|
},
|
|
{
|
|
name: "without external_id (Routable UI-initiated)",
|
|
payable: client.Payable{
|
|
ID: "pa_def456",
|
|
Type: "ach",
|
|
},
|
|
wantPIRef: "", // absent — stripEmpty drops empty values
|
|
wantPayable: "pa_def456",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
m := PayableMetadata(tc.payable)
|
|
assertAliasMetadata(t, m, tc.wantPIRef, tc.wantPayable)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestReceivableMetadata_AliasKeys mirrors the payable contract for the
|
|
// inbound path so the correlation works regardless of payment direction.
|
|
func TestReceivableMetadata_AliasKeys(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
receivable client.Receivable
|
|
wantPIRef string
|
|
wantPayable string
|
|
}{
|
|
{
|
|
name: "with external_id",
|
|
receivable: client.Receivable{
|
|
ID: "re_abc",
|
|
ExternalID: "pi_inbound",
|
|
Type: "ach",
|
|
},
|
|
wantPIRef: "pi_inbound",
|
|
wantPayable: "re_abc",
|
|
},
|
|
{
|
|
name: "without external_id",
|
|
receivable: client.Receivable{
|
|
ID: "re_def",
|
|
Type: "ach",
|
|
},
|
|
wantPIRef: "",
|
|
wantPayable: "re_def",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
m := ReceivableMetadata(tc.receivable)
|
|
assertAliasMetadata(t, m, tc.wantPIRef, tc.wantPayable)
|
|
})
|
|
}
|
|
}
|
|
|
|
// assertAliasMetadata pins the correlation contract precisely:
|
|
// - payable_id MUST be present and equal to wantPayable.
|
|
// - When wantPIRef != "", payment_initiation_reference and external_id
|
|
// MUST both be present and equal to wantPIRef.
|
|
// - When wantPIRef == "" (Routable-UI-initiated row), both alias and
|
|
// legacy keys MUST be ABSENT (not present-with-empty-string), since
|
|
// stripEmpty drops empty values. CodeRabbit flagged that comparing
|
|
// value-only would let a missing key and an empty-string value both
|
|
// pass — this helper closes the gap.
|
|
func assertAliasMetadata(t *testing.T, m map[string]string, wantPIRef, wantPayable string) {
|
|
t.Helper()
|
|
|
|
got, ok := m[MetadataKeyRoutablePayableID]
|
|
if !ok {
|
|
t.Fatalf("payable_id alias missing entirely from metadata: %v", m)
|
|
}
|
|
if got != wantPayable {
|
|
t.Errorf("payable_id = %q, want %q", got, wantPayable)
|
|
}
|
|
|
|
for _, key := range []string{MetadataKeyPaymentInitiationReference, MetadataKeyExternalID} {
|
|
got, present := m[key]
|
|
switch {
|
|
case wantPIRef == "" && present:
|
|
t.Errorf("%s should be ABSENT when external_id is empty (stripEmpty contract); got %q", key, got)
|
|
case wantPIRef != "" && !present:
|
|
t.Errorf("%s should be present when external_id is set (want %q); not found in %v", key, wantPIRef, m)
|
|
case wantPIRef != "" && got != wantPIRef:
|
|
t.Errorf("%s = %q, want %q", key, got, wantPIRef)
|
|
}
|
|
}
|
|
}
|