diff --git a/lemarche/siaes/management/commands/create_siae_activities.py b/lemarche/siaes/management/commands/create_siae_activities.py index 2698f660c..4a7790916 100644 --- a/lemarche/siaes/management/commands/create_siae_activities.py +++ b/lemarche/siaes/management/commands/create_siae_activities.py @@ -1,6 +1,6 @@ +import lemarche.siaes.constants as siae_constants from lemarche.perimeters.models import Perimeter from lemarche.siaes.models import Siae, SiaeActivity -from lemarche.siaes.utils import match_location_to_perimeter from lemarche.utils.commands import BaseCommand from lemarche.utils.data import reset_app_sql_sequences @@ -48,8 +48,7 @@ def handle(self, *args, **options): self.stdout_info("-" * 80) self.stdout_info("Creating SiaeActivities") for index, siae in enumerate(siae_qs): - siae_location: Perimeter | None = match_location_to_perimeter(siae) - self.create_siae_activities(siae, siae_location=siae_location) + self.create_siae_activities(siae) if (index % 500) == 0: self.stdout_info(f"{index}...") @@ -63,10 +62,9 @@ def handle(self, *args, **options): ] self.stdout_messages_success(msg_success) - self.stdout_warning(f"No location found for {siae} (post_code empty)") return None - def create_siae_activities(self, siae: Siae, siae_location: Perimeter = None): + def create_siae_activities(self, siae: Siae): """ - sector_group / sectors: we look at the existing siae sectors, and create an activity per sector group - presta_type: we look at the existing siae presta_types @@ -79,14 +77,43 @@ def create_siae_activities(self, siae: Siae, siae_location: Perimeter = None): siae_sector_group_ids = list(set(siae.sectors.values_list("group", flat=True))) # For each SectorGroup, create a SiaeActivity for sector_group_id in siae_sector_group_ids: - siae_activity = SiaeActivity.objects.create( - siae=siae, - sector_group_id=sector_group_id, - presta_type=siae.presta_type, - location=siae_location, - geo_range=siae.geo_range, - geo_range_custom_distance=siae.geo_range_custom_distance, - ) + match siae.geo_range: + case siae_constants.GEO_RANGE_COUNTRY: + siae_activity = SiaeActivity.objects.create( + siae=siae, + sector_group_id=sector_group_id, + presta_type=siae.presta_type, + geo_range=siae_constants.GEO_RANGE_COUNTRY, + ) + case siae_constants.GEO_RANGE_CUSTOM: + siae_activity = SiaeActivity.objects.create( + siae=siae, + sector_group_id=sector_group_id, + presta_type=siae.presta_type, + geo_range=siae_constants.GEO_RANGE_CUSTOM, + geo_range_custom_distance=siae.geo_range_custom_distance, + ) + case siae_constants.GEO_RANGE_REGION: + siae_activity = SiaeActivity.objects.create( + siae=siae, + sector_group_id=sector_group_id, + presta_type=siae.presta_type, + geo_range=siae_constants.GEO_RANGE_ZONES, + ) + region = Perimeter.objects.get(kind=Perimeter.KIND_REGION, name=siae.region) + siae_activity.locations.add(region) + case siae_constants.GEO_RANGE_DEPARTMENT: + siae_activity = SiaeActivity.objects.create( + siae=siae, + sector_group_id=sector_group_id, + presta_type=siae.presta_type, + geo_range=siae_constants.GEO_RANGE_ZONES, + ) + department = Perimeter.objects.get(kind=Perimeter.KIND_DEPARTMENT, insee_code=siae.department) + siae_activity.locations.add(department) + case _: + self.stdout_warning(f"Unknown geo_range: {siae.geo_range}") + continue siae_activity.sectors.set(siae.sectors.filter(group_id=sector_group_id)) - # self.stdout_info(f"Created {len(siae_sector_group_ids)} activities for {siae}") + self.stdout_info(f"Created {len(siae_sector_group_ids)} activities for {siae}") diff --git a/lemarche/siaes/tests/__init__.py b/lemarche/siaes/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lemarche/siaes/tests/test_commands.py b/lemarche/siaes/tests/test_commands.py new file mode 100644 index 000000000..5729c7726 --- /dev/null +++ b/lemarche/siaes/tests/test_commands.py @@ -0,0 +1,102 @@ +from django.core.management import call_command +from django.test import TransactionTestCase + +from lemarche.perimeters.factories import PerimeterFactory +from lemarche.perimeters.models import Perimeter +from lemarche.sectors.factories import SectorFactory +from lemarche.siaes import constants as siae_constants +from lemarche.siaes.factories import SiaeFactory +from lemarche.siaes.models import SiaeActivity + + +class SiaeActivitiesCreateCommandTest(TransactionTestCase): + def setUp(self): + self.sector1 = SectorFactory() + self.sector2 = SectorFactory() + self.sector3 = SectorFactory() + + region_name = "Collectivités d'outre-mer" + + self.perimeter_department = PerimeterFactory( + name="Saint-Martin", kind=Perimeter.KIND_DEPARTMENT, insee_code="978", region_code="97" + ) + self.perimeter_region = PerimeterFactory(name=region_name, kind=Perimeter.KIND_REGION, insee_code="R97") + + self.siae1 = SiaeFactory( + is_active=True, + kind=siae_constants.KIND_AI, + presta_type=[siae_constants.PRESTA_PREST, siae_constants.PRESTA_BUILD], + geo_range=siae_constants.GEO_RANGE_COUNTRY, + ) + self.siae1.sectors.set([self.sector1, self.sector2]) + + self.siae2 = SiaeFactory( + is_active=True, + kind=siae_constants.KIND_EA, + presta_type=[siae_constants.PRESTA_DISP], + geo_range=siae_constants.GEO_RANGE_CUSTOM, + ) + self.siae2.sectors.set([self.sector3]) + + self.siae3 = SiaeFactory( + is_active=True, + kind=siae_constants.KIND_EA, + presta_type=[siae_constants.PRESTA_PREST], + geo_range=siae_constants.GEO_RANGE_REGION, + department="987", + region=region_name, + ) + self.siae3.sectors.set([self.sector3]) + + self.siae4 = SiaeFactory( + is_active=True, + kind=siae_constants.KIND_EA, + presta_type=[siae_constants.PRESTA_DISP], + geo_range=siae_constants.GEO_RANGE_DEPARTMENT, + department="978", + region=region_name, + ) + self.siae4.sectors.set([self.sector2, self.sector3]) + + def test_create_activities(self): + call_command("create_siae_activities", dry_run=True) + self.assertEqual(SiaeActivity.objects.count(), 0) + + call_command("create_siae_activities") + self.assertEqual(SiaeActivity.objects.count(), 2 + 1 + 1 + 2) + siae1_activities = SiaeActivity.objects.filter(siae=self.siae1) + self.assertEqual(siae1_activities.count(), 2) + self.assertEqual(siae1_activities.filter(sectors__in=[self.sector1]).count(), 1) + self.assertEqual(siae1_activities.filter(sectors__in=[self.sector2]).count(), 1) + for siae_activity in siae1_activities: + with self.subTest(siae_activity=siae_activity): + self.assertEqual(siae_activity.presta_type, [siae_constants.PRESTA_PREST, siae_constants.PRESTA_BUILD]) + self.assertEqual(siae_activity.geo_range, siae_constants.GEO_RANGE_COUNTRY) + self.assertEqual(siae_activity.locations.count(), 0) + + siae2_activities = SiaeActivity.objects.filter(siae=self.siae2) + self.assertEqual(siae2_activities.count(), 1) + self.assertEqual(siae2_activities.first().presta_type, [siae_constants.PRESTA_DISP]) + self.assertEqual(siae2_activities.first().geo_range, siae_constants.GEO_RANGE_CUSTOM) + self.assertEqual(siae2_activities.first().geo_range_custom_distance, self.siae2.geo_range_custom_distance) + self.assertEqual(siae2_activities.filter(sectors__in=[self.sector3]).count(), 1) + self.assertEqual(siae2_activities.first().locations.count(), 0) + + siae3_activities = SiaeActivity.objects.filter(siae=self.siae3) + self.assertEqual(siae3_activities.count(), 1) + self.assertEqual(siae3_activities.filter(sectors__in=[self.sector3]).count(), 1) + self.assertEqual(siae3_activities.first().presta_type, [siae_constants.PRESTA_PREST]) + self.assertEqual(siae3_activities.first().geo_range, siae_constants.GEO_RANGE_ZONES) + self.assertEqual(siae3_activities.first().locations.count(), 1) + self.assertEqual(siae3_activities.first().locations.first(), self.perimeter_region) + + siae4_activities = SiaeActivity.objects.filter(siae=self.siae4) + self.assertEqual(siae4_activities.count(), 2) + self.assertEqual(siae4_activities.filter(sectors__in=[self.sector2]).count(), 1) + self.assertEqual(siae4_activities.filter(sectors__in=[self.sector3]).count(), 1) + for siae_activity in siae4_activities: + with self.subTest(siae_activity=siae_activity): + self.assertEqual(siae_activity.presta_type, [siae_constants.PRESTA_DISP]) + self.assertEqual(siae_activity.geo_range, siae_constants.GEO_RANGE_ZONES) + self.assertEqual(siae_activity.locations.count(), 1) + self.assertEqual(siae_activity.locations.first(), self.perimeter_department) diff --git a/lemarche/siaes/tests.py b/lemarche/siaes/tests/test_models.py similarity index 98% rename from lemarche/siaes/tests.py rename to lemarche/siaes/tests/test_models.py index 4b306440b..506664c51 100644 --- a/lemarche/siaes/tests.py +++ b/lemarche/siaes/tests/test_models.py @@ -623,17 +623,6 @@ def test_calculate_etablissement_count(self): self.siae_with_siret_inactive = SiaeFactory(siret="12312312312347", is_active=False) self.assertEqual(siae_utils.calculate_etablissement_count(self.siae_with_siret_1), 2) - def test_match_location_to_perimeter(self): - self.siae_grenoble_from_post_code = SiaeFactory(post_code="38000") - self.siae_grenoble_from_insee_code = SiaeFactory(post_code="38185") - self.grenoble_perimeter = PerimeterFactory(**PERIMETER_GRENOBLE) - self.assertEqual( - siae_utils.match_location_to_perimeter(self.siae_grenoble_from_post_code), self.grenoble_perimeter - ) - self.assertEqual( - siae_utils.match_location_to_perimeter(self.siae_grenoble_from_insee_code), self.grenoble_perimeter - ) - class SiaeActivitiesTest(TestCase): @classmethod diff --git a/lemarche/siaes/utils.py b/lemarche/siaes/utils.py index 83beaa0b4..639355357 100644 --- a/lemarche/siaes/utils.py +++ b/lemarche/siaes/utils.py @@ -1,4 +1,3 @@ -from lemarche.perimeters.models import Perimeter from lemarche.siaes.models import Siae @@ -6,32 +5,3 @@ def calculate_etablissement_count(siae: Siae): if siae.siren: return Siae.objects.filter(is_active=True, siret__startswith=siae.siren).count() return 0 - - -def match_location_to_perimeter(siae: Siae): - """ - Find the Siae's location based on the post_code (and city) - - first do a post_code search - - if multiple perimeters returned, try to match with the city - - if still multiple results returned, return None - """ - if siae.post_code: - location_results_from_siae_post_code = Perimeter.objects.post_code_search( - siae.post_code, include_insee_code=True - ) - - if not location_results_from_siae_post_code.exists(): - print(f"No location found for {siae} (with post_code {siae.post_code})") - return None - elif location_results_from_siae_post_code.count() == 1: - return location_results_from_siae_post_code.first() - else: - # found multiple locations with the post_code, try to match with the city - if siae.city: - location_results_from_siae_city = Perimeter.objects.name_search(siae.city) - if location_results_from_siae_city.count(): - if location_results_from_siae_post_code.first() == location_results_from_siae_post_code.first(): - return location_results_from_siae_post_code.first() - else: - print(f"Multiple locations found for {siae} (with post_code {siae.post_code})") - return None