Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Siae): Permettre aux structures de changer leur nom commercial #1552

Merged
merged 9 commits into from
Dec 5, 2024
59 changes: 49 additions & 10 deletions lemarche/siaes/management/commands/sync_with_emplois_inclusion.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import logging
import os
import re

from django.conf import settings
from django.contrib.gis.geos import GEOSGeometry
from django.core.management.base import CommandError
from django.db.models import Q
from django.utils import timezone
from stdnum.fr import siret

Expand All @@ -15,10 +17,13 @@
from lemarche.utils.data import rename_dict_key


logger = logging.getLogger(__name__)


UPDATE_FIELDS = [
# "name", # what happens to the slug if the name is updated?
"brand",
# "kind"
# "brand", # see UPDATE_FIELDS_IF_EMPTY
"kind",
"siret",
"siret_is_valid",
"naf",
Expand All @@ -39,6 +44,8 @@
"c1_last_sync_date",
]

UPDATE_FIELDS_IF_EMPTY = ["brand"]

C1_EXTRA_KEYS = ["convention_is_active", "convention_asp_id"]


Expand Down Expand Up @@ -206,9 +213,13 @@ def filter_c1_export(self, c1_list):
c1_list_filtered = []

for c1_siae in c1_list:
if c1_siae["kind"] not in ("RESERVED",):
c1_list_filtered.append(c1_siae)

if c1_siae["kind"] not in ("RESERVED",): # do nothing if kind is filtered as reserved
if c1_siae["kind"] in siae_constants.KIND_INSERTION_LIST + siae_constants.KIND_HANDICAP_LIST:
c1_list_filtered.append(c1_siae)
else:
logger.error(
f"Kind not supported: {c1_siae['kind']}/{c1_siae['id']}/{c1_siae['name']}/{c1_siae['siret']}"
)
return c1_list_filtered

def c4_update(self, c1_list, dry_run):
Expand Down Expand Up @@ -243,11 +254,21 @@ def c4_create_siae(self, c1_siae, dry_run):
c1_siae["contact_email"] = c1_siae["admin_email"] or c1_siae["email"]
c1_siae["contact_phone"] = c1_siae["phone"]

# create object
# create object if brand is empty or not already used
if not dry_run:
siae = Siae.objects.create(**c1_siae)
self.add_siae_to_contact_list(siae)
self.stdout_info(f"New Siae created / {siae.id} / {siae.name} / {siae.siret}")
if (
"brand" not in c1_siae
or c1_siae["brand"] == ""
or not Siae.objects.filter(Q(name=c1_siae["brand"]) | Q(brand=c1_siae["brand"])).exists()
):
siae = Siae.objects.create(**c1_siae)

self.add_siae_to_contact_list(siae)
self.stdout_info(f"New Siae created / {siae.id} / {siae.name} / {siae.siret}")
else:
logger.error(
f"Brand name is already used by another SIAE: '{c1_siae['brand']}' / name: '{c1_siae['name']}'"
)

def add_siae_to_contact_list(self, siae: Siae):
if siae.kind != "OPCS" and siae.is_active:
Expand All @@ -272,5 +293,23 @@ def c4_update_siae(self, c1_siae, c4_siae, dry_run):
if key in c1_siae:
c1_siae_filtered[key] = c1_siae[key]

Siae.objects.filter(c1_id=c4_siae.c1_id).update(**c1_siae_filtered) # avoid updated_at change
# update fields only if empty
for key in UPDATE_FIELDS_IF_EMPTY:
if key in c1_siae and not getattr(c4_siae, key, None):
c1_siae_filtered[key] = c1_siae[key]

# update siae only if brand is empty or not already used
if (
"brand" not in c1_siae_filtered
or c1_siae_filtered["brand"] == ""
or not Siae.objects.exclude(c1_id=c4_siae.c1_id)
.filter(Q(name=c1_siae_filtered["brand"]) | Q(brand=c1_siae_filtered["brand"]))
.exists()
):
Siae.objects.filter(c1_id=c4_siae.c1_id).update(**c1_siae_filtered) # avoid updated_at change
else:
logger.error(
f"Brand name is already used by another SIAE: '{c1_siae['brand']}' / name: '{c1_siae['name']}'"
)

# self.stdout_info(f"Siae updated / {c4_siae.id} / {c4_siae.siret}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.2.15 on 2024-11-27 16:41

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("siaes", "0077_remove_siaeactivity_location_siaeactivity_locations_and_more"),
]

operations = [
migrations.AlterField(
model_name="historicalsiae",
name="brand",
field=models.CharField(blank=True, max_length=255, verbose_name="Nom commercial"),
),
migrations.AlterField(
model_name="siae",
name="brand",
field=models.CharField(blank=True, max_length=255, verbose_name="Nom commercial"),
),
]
17 changes: 15 additions & 2 deletions lemarche/siaes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.measure import D
from django.contrib.postgres.search import TrigramSimilarity # SearchVector
from django.core.exceptions import ValidationError
from django.db import IntegrityError, models, transaction
from django.db.models import (
BooleanField,
Expand Down Expand Up @@ -536,7 +537,7 @@ class Siae(models.Model):
FIELDS_FROM_C1 = [
"name",
"slug", # generated from 'name'
"brand",
# "brand", # see UPDATE_FIELDS_IF_EMPTY in management/commands/sync_with_emplois_inclusion.py
"siret",
"naf",
"website",
Expand Down Expand Up @@ -617,7 +618,7 @@ class Siae(models.Model):

name = models.CharField(verbose_name="Raison sociale", max_length=255)
slug = models.SlugField(verbose_name="Slug", max_length=255, unique=True)
brand = models.CharField(verbose_name="Enseigne", max_length=255, blank=True)
brand = models.CharField(verbose_name="Nom commercial", max_length=255, blank=True)
kind = models.CharField(
verbose_name="Type de structure",
max_length=6,
Expand Down Expand Up @@ -1245,6 +1246,18 @@ def set_super_badge(self):

self.save(update_fields=update_fields_list)

def clean(self):
SebastienReuiller marked this conversation as resolved.
Show resolved Hide resolved
"""
Validate that brand is not used as a brand or name by another Siae
Does not use a unique constraint on model because it allows blank values and checks two fields simultaneously.
"""
super().clean()
if self.brand:
# Check if brand is used as name by another Siae
name_exists = Siae.objects.exclude(id=self.id).filter(Q(name=self.brand) | Q(brand=self.brand)).exists()
if name_exists:
raise ValidationError({"brand": "Ce nom commercial est déjà utilisé par une autre structure."})


@receiver(post_save, sender=Siae)
def siae_post_save(sender, instance, **kwargs):
Expand Down
Loading
Loading