diff --git a/backend/leads/services.py b/backend/leads/services.py index 391ce101..3236330b 100644 --- a/backend/leads/services.py +++ b/backend/leads/services.py @@ -22,7 +22,8 @@ def conversion_account_name(lead): """The name of the account a conversion files ``lead`` under.""" if lead.company_name: return lead.company_name - return f"{lead.first_name} {lead.last_name}" + parts = [(p or "").strip() for p in (lead.first_name, lead.last_name)] + return " ".join(p for p in parts if p) or f"Lead {lead.id}" def conversion_refusal(request, lead): @@ -33,7 +34,7 @@ def conversion_refusal(request, lead): open would make it theirs (and every contact linked to it). That is refused. An account they can open, or no match at all, is fine. - ``lead`` only needs ``company_name``, ``first_name`` and ``last_name``, so + ``lead`` only needs ``id``, ``company_name``, ``first_name`` and ``last_name``, so a view can ask with the values a save is about to write, before writing. """ matches = Account.objects.filter( diff --git a/backend/leads/tests/test_convert_requires_account_access.py b/backend/leads/tests/test_convert_requires_account_access.py index f87e31ef..d2e424c8 100644 --- a/backend/leads/tests/test_convert_requires_account_access.py +++ b/backend/leads/tests/test_convert_requires_account_access.py @@ -25,7 +25,7 @@ from accounts.models import Account from common.models import Comment from contacts.models import Contact from leads.models import Lead -from leads.services import convert_lead_to_account +from leads.services import conversion_account_name, convert_lead_to_account from opportunity.models import Opportunity pytestmark = pytest.mark.django_db @@ -314,3 +314,35 @@ class TestAllowedWithAccountAccess: account = Account.objects.get(id=response.json()["account_id"]) assert account.name == "Elsewhere Inc" assert set(hidden_account.assigned_to.all()) == {admin_profile} + + +class TestConversionAccountName: + @pytest.mark.parametrize( + "first_name, last_name, expected", + [ + ("Ada", None, "Ada"), + (None, "Smith", "Smith"), + ("Ada", "Smith", "Ada Smith"), + (" ", "Smith", "Smith"), + (" Ada ", " ", "Ada"), + ], + ) + def test_account_name_skips_missing_name_parts( + self, first_name, last_name, expected + ): + lead = SimpleNamespace( + id="abc", company_name=None, first_name=first_name, last_name=last_name + ) + assert conversion_account_name(lead) == expected + + def test_account_name_for_nameless_lead_has_no_none(self): + lead = SimpleNamespace( + id="abc", company_name=None, first_name=None, last_name=None + ) + assert conversion_account_name(lead) == "Lead abc" + + def test_account_name_for_whitespace_only_names_falls_back(self): + lead = SimpleNamespace( + id="abc", company_name=None, first_name=" ", last_name=" " + ) + assert conversion_account_name(lead) == "Lead abc"