Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/workflow/api/xero/reprocess_xero.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ def sync_xero_phone_methods(company: Company) -> list[str]:
Returns the normalized numbers that were newly created, so the caller can
dispatch a call rematch for them.
"""
# A merged company's numbers live on the company it was merged into. Its
# archived Xero contact keeps the phones (and is still fetched with
# include_archived=True), so syncing it would collide with the winner's
# rows under the one-number-one-company rule.
if company.merged_into_id:
return []
phones = company.raw_json.get("_phones", []) if company.raw_json else []
if not isinstance(phones, list):
return []
Expand Down
22 changes: 22 additions & 0 deletions apps/workflow/tests/test_sync_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,28 @@ def test_duplicate_phone_owner_crashes_sync_and_persists_app_error(self) -> None
self.assertIn("+6421555123", app_error.message)
self.assertIn("Existing Phone Owner", app_error.message)

def test_merged_company_phones_are_not_synced(self) -> None:
"""A merged company's archived Xero contact keeps its phones, but they
now belong to the winner — syncing must skip, not collide."""
winner = Company.objects.create(
name="Winner", xero_last_modified=timezone.now()
)
ContactMethod.objects.create(
company=winner,
method_type=ContactMethod.MethodType.PHONE,
value="021 555 123",
)
merged = self._client_with_phone("Merged Loser")
merged.merged_into = winner
merged.save()
before = AppError.objects.count()

created = sync_xero_phone_methods(merged) # must not raise

self.assertEqual(created, [])
self.assertEqual(ContactMethod.objects.filter(company=merged).count(), 0)
self.assertEqual(AppError.objects.count(), before)

def test_resync_of_existing_number_is_grandfathered(self) -> None:
"""Re-syncing a company's own already-stored number must not raise."""
owner = self._client_with_phone("Phone Owner")
Expand Down
Loading