diff --git a/datahub/investment_lead/migrations/0011_alter_eyblead_intent_alter_eyblead_landing_timeframe_and_more.py b/datahub/investment_lead/migrations/0011_alter_eyblead_intent_alter_eyblead_landing_timeframe_and_more.py new file mode 100644 index 000000000..b8126287e --- /dev/null +++ b/datahub/investment_lead/migrations/0011_alter_eyblead_intent_alter_eyblead_landing_timeframe_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.16 on 2024-12-11 21:51 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('investment_lead', '0010_alter_eyblead_hiring'), + ] + + operations = [ + migrations.AlterField( + model_name='eyblead', + name='intent', + field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=256), default=list, size=6), + ), + migrations.AlterField( + model_name='eyblead', + name='landing_timeframe', + field=models.CharField(blank=True, default='', max_length=256), + ), + migrations.AlterField( + model_name='eyblead', + name='spend', + field=models.CharField(blank=True, default='', max_length=256), + ), + ] diff --git a/datahub/investment_lead/models.py b/datahub/investment_lead/models.py index 0bdda936e..2a92abb5e 100644 --- a/datahub/investment_lead/models.py +++ b/datahub/investment_lead/models.py @@ -39,50 +39,6 @@ class EYBLead(InvestmentLead): user's unique ID. """ - class IntentChoices(models.TextChoices): - SET_UP_NEW_PREMISES = 'SET_UP_NEW_PREMISES', 'Set up new premises' - SET_UP_A_NEW_DISTRIBUTION_CENTRE = ( - 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', - 'Set up a new distribution centre', - ) - ONWARD_SALES_AND_EXPORTS_FROM_THE_UK = ( - 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', - 'Onward sales and exports from the UK', - ) - RESEARCH_DEVELOP_AND_COLLABORATE = ( - 'RESEARCH_DEVELOP_AND_COLLABORATE', - 'Research, develop and collaborate', - ) - FIND_PEOPLE_WITH_SPECIALIST_SKILLS = ( - 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', - 'Find people with specialist skills', - ) - OTHER = 'OTHER', 'Other' - - class SpendChoices(models.TextChoices): - # Legacy choice - FIVE_HUNDRED_THOUSAND_ONE_TO_ONE_MILLION = '500001-1000000', '£500,001 - £1,000,000' - ONE_MILLION_ONE_TO_TWO_MILLION = '1000001-2000000', '£1,000,001 - £2,000,000' - TWO_MILLION_ONE_TO_FIVE_MILLION = '2000001-5000000', '£2,000,001 - £5,000,000' - FIVE_MILLION_ONE_TO_TEN_MILLION = '5000001-10000000', '£5,000,001 - £10,000,000' - TEN_MILLION_ONE_PLUS = '10000001+', 'More than £10 million' - SPECIFIC_AMOUNT = 'SPECIFIC_AMOUNT', 'Specific amount' - - # Current choices - LESS_THAN_TEN_THOUSAND = '0-9999', 'Less than £10,000' - TEN_THOUSAND_TO_FIVE_HUNDRED_THOUSAND = '10000-500000', '£10,000 to £500,000' - FIVE_HUNDRED_THOUSAND_TO_ONE_MILLION = '500000-1000000', '£500,000 to £1 million' - ONE_MILLION_TO_TWO_MILLION = '1000000-2000000', '£1 million to £2 million' - TWO_MILLION_TO_FIVE_MILLION = '2000000-5000000', '£2 million to £5 million' - FIVE_MILLION_TO_TEN_MILLION = '5000000-10000000', '£5 million to £10 million' - MORE_THAN_TEN_MILLION = '10000000+', 'More than £10 million' - - class LandingTimeframeChoices(models.TextChoices): - UNDER_SIX_MONTHS = 'UNDER_SIX_MONTHS', 'In the next 6 months' - SIX_TO_TWELVE_MONTHS = 'SIX_TO_TWELVE_MONTHS', '6 to 12 months' - ONE_TO_TWO_YEARS = 'ONE_TO_TWO_YEARS', '1 to 2 years' - OVER_TWO_YEARS = 'OVER_TWO_YEARS', "In more than 2 years' time" - # EYB triage fields triage_hashed_uuid = models.CharField(max_length=CHAR_FIELD_MAX_LENGTH, default='', blank=True) triage_created = models.DateTimeField(null=True, blank=True) @@ -101,7 +57,7 @@ class LandingTimeframeChoices(models.TextChoices): default=list, ) intent = ArrayField( - models.CharField(max_length=CHAR_FIELD_MAX_LENGTH, choices=IntentChoices.choices), + models.CharField(max_length=CHAR_FIELD_MAX_LENGTH), size=6, default=list, ) @@ -124,7 +80,7 @@ class LandingTimeframeChoices(models.TextChoices): max_length=CHAR_FIELD_MAX_LENGTH, default='', blank=True, ) spend = models.CharField( - max_length=CHAR_FIELD_MAX_LENGTH, choices=SpendChoices.choices, default='', blank=True, + max_length=CHAR_FIELD_MAX_LENGTH, default='', blank=True, ) spend_other = models.CharField(max_length=CHAR_FIELD_MAX_LENGTH, default='', blank=True) is_high_value = models.BooleanField(default=None, null=True) @@ -170,7 +126,6 @@ class LandingTimeframeChoices(models.TextChoices): default='', max_length=CHAR_FIELD_MAX_LENGTH, blank=True, - choices=LandingTimeframeChoices.choices, ) # Related fields diff --git a/datahub/investment_lead/serializers.py b/datahub/investment_lead/serializers.py index e314ea29b..32ad4556a 100644 --- a/datahub/investment_lead/serializers.py +++ b/datahub/investment_lead/serializers.py @@ -180,7 +180,6 @@ class Meta(BaseEYBLeadSerializer.Meta): sectorSubSub = serializers.CharField( # noqa: N815 read_only=True, required=False, allow_null=True, ) - # Can't use MultipleChoiceField here as it returns a set rather than a list and raises db error intent = serializers.ListField(required=False, allow_null=True, allow_empty=True, default=list) intentOther = serializers.CharField( # noqa: N815 source='intent_other', required=False, allow_null=True, allow_blank=True, default='', @@ -198,8 +197,7 @@ class Meta(BaseEYBLeadSerializer.Meta): hiring = serializers.CharField( required=False, allow_null=True, allow_blank=True, default='', ) - spend = serializers.ChoiceField( - choices=EYBLead.SpendChoices.choices, + spend = serializers.CharField( required=False, allow_null=True, allow_blank=True, default='', ) spendOther = serializers.CharField( # noqa: N815 @@ -379,9 +377,8 @@ class Meta(BaseEYBLeadSerializer.Meta): agreeInfoEmail = serializers.BooleanField( # noqa: N815 source='agree_info_email', required=False, allow_null=True, default=None, ) - landingTimeframe = serializers.ChoiceField( # noqa: N815 + landingTimeframe = serializers.CharField( # noqa: N815 source='landing_timeframe', - choices=EYBLead.LandingTimeframeChoices.choices, required=False, allow_null=True, allow_blank=True, @@ -499,21 +496,3 @@ class Meta(BaseEYBLeadSerializer.Meta): ) company = NestedRelatedField(Company) investment_projects = NestedRelatedField(InvestmentProject, many=True) - - def get_related_fields_representation(self, instance): - """Provides related fields in a representation-friendly format. - - Specifically, we want to convert `UPPER_CASE` values to `Sentence case` labels - for choice fields. - """ - return { - 'intent': [ - EYBLead.IntentChoices(intent_choice).label - for intent_choice in instance.intent - ], - 'spend': EYBLead.SpendChoices(instance.spend).label - if instance.spend else None, - 'landing_timeframe': EYBLead.LandingTimeframeChoices( - instance.landing_timeframe, - ).label if instance.landing_timeframe else None, - } diff --git a/datahub/investment_lead/test/factories.py b/datahub/investment_lead/test/factories.py index 66254e23c..efe2ac3ea 100644 --- a/datahub/investment_lead/test/factories.py +++ b/datahub/investment_lead/test/factories.py @@ -10,11 +10,40 @@ from datahub.company.test.factories import CompanyFactory from datahub.core import constants from datahub.core.test.factories import to_many_field -from datahub.investment_lead.models import EYBLead from datahub.metadata.models import Sector -HIRING_CHOICES = ['1-10', '11-50', '51-100', '101+', 'NO_PLANS_TO_HIRE_YET'] +INTENT_CHOICES = [ + 'SET_UP_NEW_PREMISES', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', + 'RESEARCH_DEVELOP_AND_COLLABORATE', + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'OTHER', +] + +SPEND_CHOICES = [ + '0-499999', + '500000-1000000', + '1000000-2500000', + '2500000-5000000', + '5000000+', +] + +LANDING_TIME_FRAME_CHOICES = [ + 'UNDER_SIX_MONTHS', + 'SIX_TO_TWELVE_MONTHS', + 'ONE_TO_TWO_YEARS', + 'OVER_TWO_YEARS', +] + +HIRING_CHOICES = [ + '1-5', + '6-10', + '11-20', + '21+', + 'NO_PLANS_TO_HIRE_YET', +] fake = Faker(locale='en_GB') @@ -39,14 +68,14 @@ class Meta: triage_modified = factory.LazyFunction(datetime.now) sector = factory.LazyAttribute(lambda o: random.choice(list(Sector.objects.all()))) intent = factory.LazyAttribute( - lambda o: random.sample(EYBLead.IntentChoices.values, k=random.randint(1, 4)), + lambda o: random.sample(INTENT_CHOICES, k=random.randint(1, 4)), ) intent_other = '' proposed_investment_region_id = constants.UKRegion.wales.value.id proposed_investment_city = 'Cardiff' proposed_investment_location_none = False hiring = factory.LazyAttribute(lambda o: random.choice(HIRING_CHOICES)) - spend = factory.LazyAttribute(lambda o: random.choice(EYBLead.SpendChoices.values)) + spend = factory.LazyAttribute(lambda o: random.choice(SPEND_CHOICES)) spend_other = '' is_high_value = factory.Faker('pybool') @@ -70,7 +99,7 @@ class Meta: agree_terms = factory.Faker('pybool') agree_info_email = factory.Faker('pybool') landing_timeframe = factory.LazyAttribute( - lambda o: random.choice(EYBLead.LandingTimeframeChoices.values), + lambda o: random.choice(LANDING_TIME_FRAME_CHOICES), ) # EYB marketing fields @@ -117,7 +146,7 @@ def eyb_lead_user_record_faker(overrides: dict | None = None) -> dict: 'telephoneNumber': fake.phone_number(), 'agreeTerms': fake.pybool(), 'agreeInfoEmail': fake.pybool(), - 'landingTimeframe': random.choice(EYBLead.LandingTimeframeChoices.values), + 'landingTimeframe': random.choice(LANDING_TIME_FRAME_CHOICES), } if overrides: data.update(overrides) @@ -143,13 +172,13 @@ def eyb_lead_triage_record_faker(overrides: dict | None = None) -> dict: 'sector': level_zero_segment, 'sectorSub': level_one_segment, 'sectorSubSub': level_two_segment, - 'intent': random.sample(EYBLead.IntentChoices.values, k=random.randint(1, 4)), + 'intent': random.sample(INTENT_CHOICES, k=random.randint(1, 4)), 'intentOther': '', 'location': constants.UKRegion.wales.value.name, 'locationCity': 'Cardiff', 'locationNone': False, 'hiring': random.choice(HIRING_CHOICES), - 'spend': random.choice(EYBLead.SpendChoices.values), + 'spend': random.choice(SPEND_CHOICES), 'spendOther': '', 'isHighValue': fake.pybool(), } diff --git a/datahub/investment_lead/test/test_serializers.py b/datahub/investment_lead/test/test_serializers.py index 736cc57bc..30bbba019 100644 --- a/datahub/investment_lead/test/test_serializers.py +++ b/datahub/investment_lead/test/test_serializers.py @@ -91,16 +91,14 @@ def test_related_field_conversion(self, eyb_lead_triage_data): assert validated_data['sector'].pk == mining_sector.pk assert validated_data['proposed_investment_region'].pk == wales_region.pk - def test_create_lead_from_invalid_choice_and_related_data(self, eyb_lead_triage_data): - """Tests invalid choice-field and related-field data raises validation errors.""" + def test_create_lead_from_invalid_choice(self, eyb_lead_triage_data): + """Tests invalid choice-field data raises validation errors.""" eyb_lead_triage_data.update({ 'location': 'Invalid location name', - 'spend': 'Invalid spend choice', }) serializer = CreateEYBLeadTriageSerializer(data=eyb_lead_triage_data) assert not serializer.is_valid() assert 'location' in serializer.errors - assert 'spend' in serializer.errors def test_create_lead_from_invalid_sector_data(self, eyb_lead_triage_data): """Tests invalid sector data raises validation errors.""" @@ -232,16 +230,14 @@ def test_related_field_conversion(self, eyb_lead_user_data): validated_data = serializer.validated_data assert validated_data['address_country'].pk == canada_country.pk - def test_create_lead_from_invalid_choice_and_related_data(self, eyb_lead_user_data): - """Tests invalid choice-field and related-field data raises validation errors.""" + def test_create_lead_from_invalid_related_data(self, eyb_lead_user_data): + """Tests invalid related-field data raises validation errors.""" eyb_lead_user_data.update({ 'companyLocation': 'Invalid country name', - 'landingTimeframe': 'Invalid landing timeframe choice', }) serializer = CreateEYBLeadUserSerializer(data=eyb_lead_user_data) assert not serializer.is_valid() assert 'companyLocation' in serializer.errors - assert 'landingTimeframe' in serializer.errors @pytest.mark.parametrize( 'value', diff --git a/datahub/investment_lead/test/utils.py b/datahub/investment_lead/test/utils.py index 04fd813d2..3fb69ece0 100644 --- a/datahub/investment_lead/test/utils.py +++ b/datahub/investment_lead/test/utils.py @@ -119,16 +119,13 @@ def assert_retrieved_eyb_lead_data(instance: EYBLead, data: dict): assert_datetimes(instance.triage_created, data['triage_created']) assert_datetimes(instance.triage_modified, data['triage_modified']) assert str(instance.sector.id) == data['sector']['id'] - assert [ - EYBLead.IntentChoices(intent_choice).label - for intent_choice in instance.intent - ] == data['intent'] + assert instance.intent == data['intent'] assert instance.intent_other == data['intent_other'] assert str(instance.proposed_investment_region.id) == data['proposed_investment_region']['id'] assert instance.proposed_investment_city == data['proposed_investment_city'] assert instance.proposed_investment_location_none == data['proposed_investment_location_none'] assert instance.hiring == data['hiring'] - assert EYBLead.SpendChoices(instance.spend).label == data['spend'] + assert instance.spend == data['spend'] assert instance.spend_other == data['spend_other'] assert instance.is_high_value == data['is_high_value'] @@ -152,8 +149,7 @@ def assert_retrieved_eyb_lead_data(instance: EYBLead, data: dict): assert instance.telephone_number == data['telephone_number'] assert instance.agree_terms == data['agree_terms'] assert instance.agree_info_email == data['agree_info_email'] - assert EYBLead.LandingTimeframeChoices(instance.landing_timeframe).label \ - == data['landing_timeframe'] + assert instance.landing_timeframe == data['landing_timeframe'] assert [ str(ip.id) for ip in instance.investment_projects.all() ] == [