EnableBanking: use remittance for CARD-* names and merchants (#1478)

* EnableBanking: skip CARD-* counterparty in name

# Conflicts:
#	test/models/enable_banking_entry/processor_test.rb

# Conflicts:
#	test/models/enable_banking_entry/processor_test.rb

* Fix whitespace in remittance_information array

Whitespace added before 'ACME SHOP' in remittance_information.

Signed-off-by: Juan José Mata <jjmata@jjmata.com>

* Fix merchant creation for Wise and prefer remittance for Entry name if counterparty is CARD-XXX

* Fix review

* Handle scalars

* Handle empty strings

* Fix review

* Make truncate not use ellipsis at the end

---------

Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: quentinreytinas <quentin@reytinas.fr>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
This commit is contained in:
Daniel Tschinder
2026-04-16 17:44:42 +02:00
committed by GitHub
parent 3eedf5137d
commit d415672247
2 changed files with 197 additions and 22 deletions

View File

@@ -208,4 +208,154 @@ class EnableBankingEntry::ProcessorTest < ActiveSupport::TestCase
entry = @account.entries.find_by!(external_id: "enable_banking_ref_noextra")
assert_nil entry.transaction&.extra&.dig("enable_banking")
end
def build_processor(data)
EnableBankingEntry::Processor.new(data, enable_banking_account: Object.new)
end
def build_name(data)
build_processor(data).send(:name)
end
test "skips technical card counterparty and falls back to remittance_information" do
name = build_name(
credit_debit_indicator: "CRDT",
debtor_name: "CARD-1234",
remittance_information: [ "ACME SHOP" ],
bank_transaction_code: { description: "Card Purchase" }
)
assert_equal "ACME SHOP", name
end
test "uses counterparty when it is human readable" do
name = build_name(
credit_debit_indicator: "CRDT",
debtor_name: "ACME SHOP",
remittance_information: [ "Receipt #42" ],
bank_transaction_code: { description: "Transfer" }
)
assert_equal "ACME SHOP", name
end
test "falls back to top-level counterparty name when nested name is blank" do
processor = build_processor(
credit_debit_indicator: "CRDT",
debtor: { name: "" },
debtor_name: "ACME SHOP"
)
assert_equal "ACME SHOP", processor.send(:name)
merchant = stub(id: 789)
import_adapter = mock("import_adapter")
import_adapter.expects(:find_or_create_merchant).with(
provider_merchant_id: "enable_banking_merchant_c0b09f27a4375bb8d8d477ed552a9aa1",
name: "ACME SHOP",
source: "enable_banking"
).returns(merchant)
processor.stubs(:import_adapter).returns(import_adapter)
assert_equal merchant, processor.send(:merchant)
end
test "builds merchant from remittance when counterparty is technical card id" do
processor = build_processor(
credit_debit_indicator: "CRDT",
debtor_name: "CARD-1234",
remittance_information: [ "ACME SHOP" ],
bank_transaction_code: { description: "Card Purchase" }
)
merchant = stub(id: 123)
import_adapter = mock("import_adapter")
import_adapter.expects(:find_or_create_merchant).with(
provider_merchant_id: "enable_banking_merchant_c0b09f27a4375bb8d8d477ed552a9aa1",
name: "ACME SHOP",
source: "enable_banking"
).returns(merchant)
processor.stubs(:import_adapter).returns(import_adapter)
assert_equal merchant, processor.send(:merchant)
end
test "uses remittance fallback for debit technical card counterparty" do
processor = build_processor(
credit_debit_indicator: "DBIT",
creditor_name: "CARD-1234",
remittance_information: [ "ACME SHOP" ],
bank_transaction_code: { description: "Card Purchase" }
)
assert_equal "ACME SHOP", processor.send(:name)
merchant = stub(id: 321)
import_adapter = mock("import_adapter")
import_adapter.expects(:find_or_create_merchant).with(
provider_merchant_id: "enable_banking_merchant_c0b09f27a4375bb8d8d477ed552a9aa1",
name: "ACME SHOP",
source: "enable_banking"
).returns(merchant)
processor.stubs(:import_adapter).returns(import_adapter)
assert_equal merchant, processor.send(:merchant)
end
test "truncates remittance-derived merchant names before persisting" do
long_name = "A" * 150
truncated_name = "A" * 100
processor = build_processor(
credit_debit_indicator: "CRDT",
debtor_name: "CARD-1234",
remittance_information: [ long_name ]
)
merchant = stub(id: 654)
import_adapter = mock("import_adapter")
import_adapter.expects(:find_or_create_merchant).with(
provider_merchant_id: "enable_banking_merchant_#{Digest::MD5.hexdigest(truncated_name.downcase)}",
name: truncated_name,
source: "enable_banking"
).returns(merchant)
processor.stubs(:import_adapter).returns(import_adapter)
assert_equal merchant, processor.send(:merchant)
end
test "uses string remittance fallback for technical card counterparty" do
processor = build_processor(
credit_debit_indicator: "CRDT",
debtor_name: "CARD-1234",
remittance_information: "ACME SHOP"
)
assert_equal "ACME SHOP", processor.send(:name)
merchant = stub(id: 456)
import_adapter = mock("import_adapter")
import_adapter.expects(:find_or_create_merchant).with(
provider_merchant_id: "enable_banking_merchant_c0b09f27a4375bb8d8d477ed552a9aa1",
name: "ACME SHOP",
source: "enable_banking"
).returns(merchant)
processor.stubs(:import_adapter).returns(import_adapter)
assert_equal merchant, processor.send(:merchant)
end
test "does not build merchant from remittance when counterparty is blank" do
processor = build_processor(
credit_debit_indicator: "CRDT",
debtor_name: nil,
remittance_information: [ "Invoice 12345" ]
)
assert_nil processor.send(:merchant)
end
end