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

[Structures] Nouveau champ super_badge et méthode pour le calculer #1008

Merged
merged 5 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 36 additions & 21 deletions lemarche/siaes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin):
"siret",
"kind",
"city",
"super_badge",
"user_count_with_link",
"tender_email_send_count_annotated_with_link",
"tender_detail_display_count_annotated_with_link",
Expand All @@ -153,6 +154,7 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin):
"is_first_page",
HasUserFilter,
"kind",
"super_badge",
"geo_range",
"source",
"networks",
Expand All @@ -163,27 +165,31 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin):

autocomplete_fields = ["sectors", "networks", "groups"]
# prepopulated_fields = {"slug": ("name",)}
readonly_fields = [field for field in Siae.READONLY_FIELDS if field not in ("coords")] + [
"siren",
"sector_count_with_link",
"network_count_with_link",
"group_count_with_link",
"offer_count_with_link",
"label_count_with_link",
"client_reference_count_with_link",
"user_count_with_link",
"image_count_with_link",
"coords_display",
"logo_url",
"logo_url_display",
"tender_count_annotated_with_link",
"tender_email_send_count_annotated_with_link",
"tender_email_link_click_count_annotated_with_link",
"tender_detail_display_count_annotated_with_link",
"tender_detail_contact_click_count_annotated_with_link",
"logs_display",
"import_raw_object_display",
]
readonly_fields = (
[field for field in Siae.READONLY_FIELDS if field not in ("coords")]
+ [f"{field}_last_updated" for field in Siae.TRACK_UPDATE_FIELDS if field not in ("address")]
+ [
"siren",
"sector_count_with_link",
"network_count_with_link",
"group_count_with_link",
"offer_count_with_link",
"label_count_with_link",
"client_reference_count_with_link",
"user_count_with_link",
"image_count_with_link",
"coords_display",
"logo_url",
"logo_url_display",
"tender_count_annotated_with_link",
"tender_email_send_count_annotated_with_link",
"tender_email_link_click_count_annotated_with_link",
"tender_detail_display_count_annotated_with_link",
"tender_detail_contact_click_count_annotated_with_link",
"logs_display",
"import_raw_object_display",
]
)
formfield_overrides = {
ChoiceArrayField: {"widget": forms.CheckboxSelectMultiple(attrs={"class": "custom-checkbox-select-multiple"})},
}
Expand Down Expand Up @@ -302,6 +308,15 @@ class SiaeAdmin(FieldsetsInlineMixin, gis_admin.OSMGeoAdmin):
)
},
),
(
"Badge 'Super prestataire inclusif'",
{
"fields": (
"super_badge",
"super_badge_last_updated",
)
},
),
(
"Stats",
{
Expand Down
31 changes: 31 additions & 0 deletions lemarche/siaes/migrations/0069_siae_super_badge_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 4.2.2 on 2023-12-06 16:49

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("siaes", "0068_siae_tender_count_fields"),
]

operations = [
migrations.AddField(
model_name="siae",
name="super_badge",
field=models.BooleanField(
blank=True,
help_text="Champ recalculé à intervalles réguliers",
null=True,
verbose_name="Badge 'Super prestataire inclusif'",
),
),
migrations.AddField(
model_name="siae",
name="super_badge_last_updated",
field=models.DateTimeField(
blank=True,
null=True,
verbose_name="Date de dernière mise à jour du badge 'Super prestataire inclusif'",
),
),
]
35 changes: 34 additions & 1 deletion lemarche/siaes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ class Siae(models.Model):
"tender_detail_contact_click_count",
]
FIELDS_STATS_TIMESTAMPS = ["signup_date", "content_filled_basic_date", "created_at", "updated_at"]
FIELDS_STATS = FIELDS_STATS_COUNT + FIELDS_STATS_TIMESTAMPS + ["completion_rate"]
FIELDS_STATS = FIELDS_STATS_COUNT + FIELDS_STATS_TIMESTAMPS + ["super_badge", "completion_rate"]
READONLY_FIELDS = (
FIELDS_FROM_C1 + FIELDS_FROM_C2 + FIELDS_FROM_QPV + FIELDS_FROM_ZRR + FIELDS_FROM_API_ENTREPRISE + FIELDS_STATS
)
Expand All @@ -564,6 +564,7 @@ class Siae(models.Model):
# update coords
"address",
# set last_updated fields
"super_badge",
"employees_insertion_count",
"employees_permanent_count",
"ca",
Expand Down Expand Up @@ -707,6 +708,14 @@ class Siae(models.Model):
)
# ForeignKeys: offers, client_references, labels_old, images

# super badge
super_badge = models.BooleanField(
"Badge 'Super prestataire inclusif'", help_text=RECALCULATED_FIELD_HELP_TEXT, blank=True, null=True
)
super_badge_last_updated = models.DateTimeField(
verbose_name="Date de dernière mise à jour du badge 'Super prestataire inclusif'", blank=True, null=True
)

# C2 (ETP)
c2_etp_count = models.FloatField("Nombre d'ETP (C2)", blank=True, null=True)
c2_etp_count_date_saisie = models.DateField("Date de saisie du nombre d'ETP (C2)", blank=True, null=True)
Expand Down Expand Up @@ -1072,6 +1081,19 @@ def source_display(self):
else:
return "l'ASP"

@property
def super_badge_calculated(self):
if (
(self.user_count >= 1)
and (self.completion_rate and self.completion_rate >= 80)
and (self.tender_email_send_count >= 1)
):
tender_view_rate = round(100 * self.tender_email_link_click_count / self.tender_email_send_count)
tender_interested_rate = round(100 * self.tender_detail_contact_click_count / self.tender_email_send_count)
if (tender_view_rate >= 40) or (tender_interested_rate >= 20):
return True
return False

@property
def completion_rate_calculated(self):
score, total = 0, 0
Expand Down Expand Up @@ -1141,6 +1163,17 @@ def siae_user_requests_pending_count(self):
def get_absolute_url(self):
return reverse("siae:detail", kwargs={"slug": self.slug})

def set_super_badge(self):
update_fields_list = ["super_badge"]
siae_super_badge_current_value = self.super_badge
self.super_badge = self.super_badge_calculated

if self.super_badge != siae_super_badge_current_value:
self.super_badge_last_updated = timezone.now()
update_fields_list.append("super_badge_last_updated")

self.save(update_fields=update_fields_list)


@receiver(post_save, sender=Siae)
def siae_post_save(sender, instance, **kwargs):
Expand Down
64 changes: 64 additions & 0 deletions lemarche/siaes/tests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.test import TestCase
from django.utils import timezone

from lemarche.labels.factories import LabelFactory
from lemarche.networks.factories import NetworkFactory
Expand Down Expand Up @@ -175,6 +176,38 @@ def test_kind_parent_property(self):
self.assertEqual(self.siae_ei.kind_parent, "Insertion")
self.assertEqual(self.siae_esat.kind_parent, "Handicap")

def test_super_badge_computed_property(self):
siae_1 = SiaeFactory(user_count=0)
siae_2 = SiaeFactory(user_count=1, completion_rate=50)
siae_3 = SiaeFactory(
user_count=1, completion_rate=80, tender_email_send_count=10, tender_email_link_click_count=3
)
siae_4 = SiaeFactory(
user_count=1,
completion_rate=80,
tender_email_send_count=10,
tender_email_link_click_count=3,
tender_detail_contact_click_count=1,
)
siae_super_badge_1 = SiaeFactory(
user_count=1,
completion_rate=80,
tender_email_send_count=10,
tender_email_link_click_count=4,
tender_detail_contact_click_count=1,
)
siae_super_badge_2 = SiaeFactory(
user_count=1,
completion_rate=80,
tender_email_send_count=10,
tender_email_link_click_count=3,
tender_detail_contact_click_count=3,
)
for siae in [siae_1, siae_2, siae_3, siae_4]:
self.assertFalse(siae.super_badge_calculated)
for siae in [siae_super_badge_1, siae_super_badge_2]:
self.assertTrue(siae.super_badge_calculated)


class SiaeModelSaveTest(TestCase):
def setUp(self):
Expand Down Expand Up @@ -333,6 +366,37 @@ def test_update_last_updated_fields(self):
# siae = Siae.objects.get(id=siae.id) # we need to fetch it again to make sure
# self.assertNotEqual(siae.coords, None)

def test_set_super_badge(self):
# None -> True
siae_super_badge_1 = SiaeFactory(
user_count=1,
completion_rate=80,
tender_email_send_count=10,
tender_email_link_click_count=4,
tender_detail_contact_click_count=1,
)
self.assertIsNone(siae_super_badge_1.super_badge)
self.assertIsNone(siae_super_badge_1.super_badge_last_updated)
siae_super_badge_1.set_super_badge()
self.assertTrue(siae_super_badge_1.super_badge)
self.assertIsNotNone(siae_super_badge_1.super_badge_last_updated)
# True -> True
siae_super_badge_2 = SiaeFactory(
user_count=1,
completion_rate=80,
tender_email_send_count=10,
tender_email_link_click_count=3,
tender_detail_contact_click_count=3,
super_badge=True,
super_badge_last_updated=timezone.now(),
)
self.assertTrue(siae_super_badge_2.super_badge)
self.assertIsNotNone(siae_super_badge_2.super_badge_last_updated)
siae_super_badge_last_updated_current_value = siae_super_badge_2.super_badge_last_updated
siae_super_badge_2.set_super_badge()
self.assertTrue(siae_super_badge_2.super_badge)
self.assertEqual(siae_super_badge_2.super_badge_last_updated, siae_super_badge_last_updated_current_value)


class SiaeModelQuerysetTest(TestCase):
@classmethod
Expand Down