import: bring in the ORG and flag a company card is read by
Import dropped a company's ORG and the flag that marks it so;
it opened as a person, blank name boxes in a row.
Assisted-by: Claude Opus 5.5 via Claude Code
diff --git a/lib/pro_tacts/import/vcf.rb b/lib/pro_tacts/import/vcf.rb
index 68a7b59..ec5248f 100644
--- a/lib/pro_tacts/import/vcf.rb
+++ b/lib/pro_tacts/import/vcf.rb
@@ -38,8 +38,11 @@ module ProTacts
# an import brings in. The envelope (BEGIN, END, VERSION, UID),
# the fields a screen shows (Contact's own readers: N, FN,
# NICKNAME, TEL, EMAIL, ADR, NOTE, PHOTO, and the X-ABLabel that
- # names a row), and BDAY, which the store takes into the model on
- # the way in
+ # names a row), the two a company card is read by (ORG, whose
+ # name the editor's Organization field falls back to and which
+ # the dashboard's search reads, and X-ABShowAs, which puts that
+ # field there — docs/plans/2026-09-24-company-cards.md), and
+ # BDAY, which the store takes into the model on the way in
# (docs/plans/2026-09-11-every-birthday-in-the-model.md).
#
# Everything else is unknown, which here means "no screen will
@@ -48,7 +51,7 @@ module ProTacts
# importing one would only pad the cards with what nobody can
# read.
KNOWN = [
- *%w[BEGIN END VERSION UID N FN NICKNAME BDAY TEL EMAIL ADR NOTE PHOTO],
+ *%w[BEGIN END VERSION UID N FN NICKNAME BDAY TEL EMAIL ADR NOTE PHOTO ORG X-ABSHOWAS],
LABEL,
].freeze #: Array[String]
diff --git a/test/pro_tacts/admin/test_import_pages.rb b/test/pro_tacts/admin/test_import_pages.rb
index e9f2b93..3d19452 100644
--- a/test/pro_tacts/admin/test_import_pages.rb
+++ b/test/pro_tacts/admin/test_import_pages.rb
@@ -278,6 +278,39 @@ class AdminImportPagesTest < Minitest::Test
end
end
+ # The shape macOS writes a company in (test/fixtures/cards/
+ # company.vcf): N empty, the name in FN and ORG, and the flag. It
+ # opens in the company editor and comes in as a company.
+ def test_a_company_card_comes_in_as_a_company
+ company = <<~CARD.gsub("\n", "\r\n")
+ BEGIN:VCARD
+ VERSION:3.0
+ N:;;;;
+ FN:Bletchley Park
+ ORG:Bletchley Park Trust;
+ X-ABShowAs:COMPANY
+ UID:GHI-789
+ END:VCARD
+ CARD
+ with_contacts({}) do |store|
+ id = upload(company)
+
+ get "/import/#{id}/0"
+
+ refute_includes last_response.body, "not imported"
+ assert_includes last_response.body, "<span>Organization</span>"
+ assert_includes last_response.body, %(name="last" value="Bletchley Park")
+
+ save(id, 0, first: "", last: "Bletchley Park")
+
+ assert_equal 303, last_response.status
+ park = store.contacts.fetch(0)
+
+ assert_predicate park, :company?
+ assert_equal "Bletchley Park Trust;", park.organization
+ end
+ end
+
def test_an_index_past_the_end_of_the_file_is_not_found
with_contacts({}) do |_store|
id = upload(JANE)
diff --git a/test/pro_tacts/import/test_vcf.rb b/test/pro_tacts/import/test_vcf.rb
index 7c7d9b4..1175783 100644
--- a/test/pro_tacts/import/test_vcf.rb
+++ b/test/pro_tacts/import/test_vcf.rb
@@ -162,6 +162,29 @@ class ImportVcfTest < Minitest::Test
assert Vcf.cards(revised).fetch(0).card?
end
+ # A company card is read by its flag and its ORG
+ # (docs/plans/2026-09-24-company-cards.md), so both come in and
+ # neither is a decision; without them it would arrive as a person.
+ def test_reading_a_company_card_keeps_what_makes_it_one
+ company = <<~CARD.gsub("\n", "\r\n")
+ BEGIN:VCARD
+ VERSION:3.0
+ N:;;;;
+ FN:Bletchley Park
+ ORG:Bletchley Park Trust;
+ X-ABShowAs:COMPANY
+ UID:GHI-789
+ END:VCARD
+ CARD
+ cards = Vcf.cards(company)
+
+ reading = Vcf.read(cards.fetch(0))
+
+ assert_equal company, reading.card.to_s
+ assert_empty reading.dropped
+ assert_empty Vcf.unknown(cards)
+ end
+
def test_reading_a_card_leaves_behind_what_no_screen_shows
reading = Vcf.read(Vcf.cards(JANE).fetch(0))