Skip to content

Commit

Permalink
Rework ADSform
Browse files Browse the repository at this point in the history
* remove ADS.owner_siret and ADS.owner_license_number, move these fields
  to ADSUser
* add constraints
  • Loading branch information
brmzkw committed Mar 28, 2024
1 parent 7547869 commit 3247a14
Show file tree
Hide file tree
Showing 19 changed files with 622 additions and 291 deletions.
8 changes: 0 additions & 8 deletions mesads/app/admin/ads.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,6 @@ def has_delete_permission(self, request, obj=None):
"prefecture",
"owner_name",
"owner_siret",
# Rewrite titles to limit the width of the column.
admin.display(description="Carte pro. tit.")(
lambda ads: ads.owner_license_number or "-"
),
admin.display(description="Exploitée par titulaire ?", boolean=True)(
lambda ads: ads.used_by_owner
),
"ads_users",
)

Expand All @@ -175,7 +168,6 @@ def has_delete_permission(self, request, obj=None):

list_filter = [
ADSPeriodListFilter,
"used_by_owner",
"adsuser__status",
ADSUsersCount,
"attribution_type",
Expand Down
15 changes: 5 additions & 10 deletions mesads/app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,7 @@ class Meta:
"owner_phone",
"owner_mobile",
"owner_email",
"used_by_owner",
"owner_license_number",
)
widgets = {
# used_by_owner has null=True because the field is not set for new
# ADS, but we don't want to allow null values for old ADS. Use a
# BooleanSelect instead of the default NullBooleanSelect.
# Note, we could use a checkbox instead of a select.
"used_by_owner": BooleanSelect(),
}

def __init__(self, epci=None, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -164,7 +155,11 @@ def _should_delete_form(self, form):
ADSUserFormSet = inlineformset_factory(
ADS,
ADSUser,
fields=("status", "name", "siret", "license_number"),
# It is important to leave "deleted_at" in the fields, otherwise
# django.db.models.constraints.CheckConstraint.validate() will silently skip
# the evaluation of the constraints using this field.
# Does it suck? Yes. Did I spend 2 days to figure it out? Also yes.
fields=("status", "name", "siret", "license_number", "deleted_at"),
can_delete=True,
extra=0,
formset=AutoDeleteADSUserFormSet,
Expand Down
54 changes: 0 additions & 54 deletions mesads/app/management/commands/fix_ads_user_and_used_by_owner.py

This file was deleted.

3 changes: 3 additions & 0 deletions mesads/app/management/commands/import_ads.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ def load_ads(self, cols, override=False):
self.excel.idx("email du titulaire"),
)

raise RuntimeError(
"The field ADS.used_by_owner has been removed. Please update this code if you need to import ADS."
)
ads.used_by_owner = self.parse_bool(
cols,
self.excel.idx("ads exploitée par son titulaire"),
Expand Down
35 changes: 35 additions & 0 deletions mesads/app/migrations/0073_alter_adsuser_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.1.9 on 2024-03-11 09:46

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("app", "0072_alter_ads_owner_name"),
]

operations = [
migrations.AlterField(
model_name="adsuser",
name="status",
field=models.CharField(
blank=True,
choices=[
(
"titulaire_exploitant",
"Le titulaire de l'ADS (personne physique)",
),
(
"legal_representative",
"Le représentant légal de la société titulaire de l'ADS (gérant ou président non salarié)",
),
("salarie", "Salarié du titulaire de l'ADS"),
("cooperateur", "Le locataire-coopérateur de l'ADS"),
("locataire_gerant", "Le locataire-gérant de l'ADS"),
("autre", "Autre"),
],
max_length=255,
verbose_name="Modalité d'exploitation de l'ADS",
),
),
]
36 changes: 36 additions & 0 deletions mesads/app/migrations/0074_fix_adsuser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 4.1.9 on 2024-03-11 10:43

from django.db import migrations


def upgrade(apps, schema_editor):
"""Fix ADSUser data, see https://trello.com/c/dG9fG0wC"""

ADS = apps.get_model("app", "ADS")
ADSUser = apps.get_model("app", "ADSUser")

for ads in ADS.objects.filter(used_by_owner=True):
ads_user = ADSUser(
ads=ads,
status="titulaire_exploitant",
license_number=ads.owner_license_number,
name="",
siret="",
)
ads_user.save()

for ads in ADS.objects.filter(used_by_owner=False):
for ads_user in ads.adsuser_set.all():
if ads_user.status in ("titulaire_exploitant", "autre"):
ads_user.status = "legal_representative"
ads_user.save()


class Migration(migrations.Migration):
dependencies = [
("app", "0073_alter_adsuser_status"),
]

operations = [
migrations.RunPython(upgrade),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Generated by Django 4.1.9 on 2024-03-11 10:53

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("app", "0074_fix_adsuser"),
]

operations = [
migrations.RemoveConstraint(
model_name="ads",
name="used_by_owner_null_for_new_ads",
),
migrations.RemoveConstraint(
model_name="ads",
name="owner_license_number_empty_if_not_used_by_owner",
),
migrations.RemoveField(
model_name="ads",
name="owner_license_number",
),
migrations.RemoveField(
model_name="ads",
name="used_by_owner",
),
migrations.AlterField(
model_name="adsuser",
name="status",
field=models.CharField(
blank=True,
choices=[
(
"titulaire_exploitant",
"Le titulaire de l'ADS (personne physique)",
),
(
"legal_representative",
"Le représentant légal de la société titulaire de l'ADS (gérant ou président non salarié)",
),
("salarie", "Salarié du titulaire de l'ADS"),
("cooperateur", "Le locataire-coopérateur de l'ADS"),
("locataire_gerant", "Le locataire-gérant de l'ADS"),
],
max_length=255,
verbose_name="Modalité d'exploitation de l'ADS",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.1.9 on 2024-03-11 11:03

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("app", "0075_remove_ads_used_by_owner_null_for_new_ads_and_more"),
]

operations = [
migrations.AddConstraint(
model_name="adsuser",
constraint=models.UniqueConstraint(
condition=models.Q(
("deleted_at__isnull", True), ("status", "titulaire_exploitant")
),
fields=("ads", "status"),
name="only_one_titulaire_exploitant",
violation_error_message="Il ne peut y avoir qu'un seul titulaire par ADS.",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 4.1.9 on 2024-03-11 14:58

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("app", "0076_adsuser_only_one_titulaire_exploitant"),
]

operations = [
migrations.AddConstraint(
model_name="adsuser",
constraint=models.CheckConstraint(
check=models.Q(
("deleted_at__isnull", False),
models.Q(("name", ""), ("status", "titulaire_exploitant")),
models.Q(("status", "titulaire_exploitant"), _negated=True),
_connector="OR",
),
name="name_empty_for_titulaire_exploitant",
violation_error_message="Le nom du conducteur ne peut être renseigné que s'il ne s'agit pas du titulaire de l'ADS.",
),
),
migrations.AddConstraint(
model_name="adsuser",
constraint=models.CheckConstraint(
check=models.Q(
("deleted_at__isnull", False),
models.Q(("siret", ""), ("status", "titulaire_exploitant")),
models.Q(("status", "titulaire_exploitant"), _negated=True),
_connector="OR",
),
name="siret_empty_for_titulaire_exploitant",
violation_error_message="Le SIRET du conducteur ne peut être renseigné que s'il ne s'agit pas du titulaire de l'ADS.",
),
),
]
40 changes: 40 additions & 0 deletions mesads/app/migrations/0078_fix_adsuser_legal_representative.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.1.9 on 2024-03-11 15:01

from django.db import migrations


def upgrade(apps, schema_editor):
"""Fix ADSUser data, see https://trello.com/c/dG9fG0wC"""
ADSUser = apps.get_model("app", "ADSUser")

for ads_user in ADSUser.objects.filter(status="legal_representative").all():
if ads_user.siret == "":
continue

# ADSUser siret and ADS siret are similar, remove the siret from ADSUser
if ads_user.ads.owner_siret == ads_user.siret:
ads_user.siret = ""
ads_user.save()
continue

# Values are different. Discard the SIRET from ADSUser, assuming it is wrong
if ads_user.ads.owner_siret != "":
ads_user.siret = ""
ads_user.save()
continue

# ADS.owner_siret is empty, let's use the one from ADSUser
ads_user.ads.owner_siret = ads_user.siret
ads_user.ads.save()
ads_user.siret = ""
ads_user.save()


class Migration(migrations.Migration):
dependencies = [
("app", "0077_adsuser_name_empty_for_titulaire_exploitant_and_more"),
]

operations = [
migrations.RunPython(upgrade),
]
22 changes: 22 additions & 0 deletions mesads/app/migrations/0079_fix_adsuser_salarie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.1.9 on 2024-03-11 15:27

from django.db import migrations


def upgrade(apps, schema_editor):
"""Fix ADSUser data, see https://trello.com/c/dG9fG0wC"""
ADSUser = apps.get_model("app", "ADSUser")

for ads_user in ADSUser.objects.filter(status="salarie").exclude(siret="").all():
ads_user.siret = ""
ads_user.save()


class Migration(migrations.Migration):
dependencies = [
("app", "0078_fix_adsuser_legal_representative"),
]

operations = [
migrations.RunPython(upgrade),
]
Loading

0 comments on commit 3247a14

Please sign in to comment.