diff --git a/payment.go b/payment.go index 8975d0b..41e8ce6 100644 --- a/payment.go +++ b/payment.go @@ -78,6 +78,7 @@ type PrepaidPayment struct { } const sepaSchemeID = "SEPA" +const cardNetworkNotApplicable = "NA" func (ui *Invoice) addPayment(inv *bill.Invoice, ctx Context) error { if inv == nil || inv.Payment == nil { @@ -175,8 +176,10 @@ func (ui *Invoice) addPaymentInstructions(inv *bill.Invoice, ctx Context) error } } if instr.Card != nil { + network := cardNetworkNotApplicable ui.PaymentMeans[0].CardAccount = &CardAccount{ PrimaryAccountNumberID: &instr.Card.Last4, + NetworkID: &network, } if instr.Card.Holder != "" { ui.PaymentMeans[0].CardAccount.HolderName = &instr.Card.Holder diff --git a/payment_test.go b/payment_test.go index a5c8884..93ac726 100644 --- a/payment_test.go +++ b/payment_test.go @@ -71,6 +71,33 @@ func TestNewPayment(t *testing.T) { assert.Equal(t, "MANDATE-123", doc.PaymentMeans[0].PaymentMandate.ID.Value) }) + t.Run("card payment includes the network ID required by the schema", func(t *testing.T) { + env := loadTestEnvelope(t, "invoice-minimal.json") + + inv, ok := env.Extract().(*bill.Invoice) + require.True(t, ok) + + inv.Payment.Instructions.CreditTransfer = nil + inv.Payment.Instructions.Card = &pay.Card{Last4: "0312"} + + doc, err := ubl.ConvertInvoice(env) + require.NoError(t, err) + require.NotEmpty(t, doc.PaymentMeans) + + card := doc.PaymentMeans[0].CardAccount + require.NotNil(t, card) + require.NotNil(t, card.PrimaryAccountNumberID) + assert.Equal(t, "0312", *card.PrimaryAccountNumberID) + // cbc:NetworkID is mandatory in UBL, but has no EN 16931 business term. + require.NotNil(t, card.NetworkID) + assert.Equal(t, "NA", *card.NetworkID) + assert.Nil(t, card.HolderName) + + data, err := ubl.Bytes(doc) + require.NoError(t, err) + assert.Contains(t, string(data), "\n 0312\n NA\n ") + }) + t.Run("document type extension", func(t *testing.T) { env := loadTestEnvelope(t, "invoice-minimal.json")