Skip to content

Commit

Permalink
fix(Activités des structures): Adaptation de la commande de reprise d…
Browse files Browse the repository at this point in the history
…e stock pour créer les activités (#1476)
  • Loading branch information
SebastienReuiller authored Oct 29, 2024
1 parent 94e0680 commit 9f497e6
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 55 deletions.
55 changes: 41 additions & 14 deletions lemarche/siaes/management/commands/create_siae_activities.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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}...")

Expand All @@ -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
Expand All @@ -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}")
Empty file.
102 changes: 102 additions & 0 deletions lemarche/siaes/tests/test_commands.py
Original file line number Diff line number Diff line change
@@ -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)
11 changes: 0 additions & 11 deletions lemarche/siaes/tests.py → lemarche/siaes/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 0 additions & 30 deletions lemarche/siaes/utils.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,7 @@
from lemarche.perimeters.models import Perimeter
from lemarche.siaes.models import Siae


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

0 comments on commit 9f497e6

Please sign in to comment.