Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
chloend committed Nov 14, 2024
1 parent 7687ecb commit 4cf5fc5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 54 deletions.
11 changes: 8 additions & 3 deletions lemarche/crm/management/commands/crm_brevo_sync_companies.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,23 @@ def handle(self, recently_updated: bool, **options):
siaes_qs = siaes_qs.filter(updated_at__gte=two_weeks_ago)
self.stdout.write(f"Sync Siae > Brevo: {siaes_qs.count()} recently updated")

# Step 2: loop on the siaes
# Step 2: Add the 90-day limited annotations
siaes_qs = siaes_qs.with_tender_stats()

# Step 3: loop on the siaes
for index, siae in enumerate(siaes_qs):
print(f"HANDLE : Siae id : {siae.id}, old siae.extra_data = {siae.extra_data}")
new_extra_data = {
"completion_rate": siae.completion_rate,
"tender_email_send_count": siae.tender_email_send_count,
"recent_tender_detail_click_count": siae.recent_tender_detail_click_count,
"recent_tender_email_send_count": getattr(siae, "tender_email_send_count_annotated", 0),
"recent_tender_detail_click_count": getattr(siae, "tender_detail_contact_click_count_annotated", 0),
}
# extra_data update if needed
if siae.extra_data != new_extra_data:
siae.extra_data = new_extra_data
siae.save(update_fields=["extra_data"])

print(f"HANDLE : Siae id : {siae.id}, new siae.extra_data = {siae.extra_data}")
api_brevo.create_or_update_company(siae)
if (index % 10) == 0: # avoid API rate-limiting
time.sleep(1)
Expand Down
102 changes: 69 additions & 33 deletions lemarche/crm/tests.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,69 @@
from datetime import timedelta
from unittest.mock import MagicMock, patch

from django.core.management import call_command
from django.test import TestCase
from django.utils import timezone

from lemarche.siaes.factories import SiaeFactory
from lemarche.siaes.models import Siae
from lemarche.tenders.factories import TenderFactory
from lemarche.tenders.models import TenderSiae
from lemarche.users.factories import UserFactory
from lemarche.users.models import User
from lemarche.utils.apis.api_brevo import create_or_update_company
from lemarche.utils.urls import get_object_admin_url, get_object_share_url


now = timezone.now()
date_tomorrow = now + timedelta(days=1)


class CrmBrevoSyncCompaniesCommandTests(TestCase):
@classmethod
def setUpTestData(cls):
"""Siae instances initialization"""
cls.siae1 = SiaeFactory(name="Test Company 1")
cls.siae2 = SiaeFactory()
cls.recent_date = timezone.now() - timedelta(days=30)
cls.old_date = timezone.now() - timedelta(days=100)

cls.siae_1 = SiaeFactory(name="Test Company 1")
cls.siae_2 = SiaeFactory()

cls.user_siae = UserFactory(kind=User.KIND_SIAE)
cls.siae_with_tender_1 = SiaeFactory(users=[cls.user_siae])
cls.tender_with_siae_1 = TenderFactory(siaes=[cls.siae_with_tender_1], deadline_date=date_tomorrow)
TenderSiae.objects.create(
tender=cls.tender_with_siae_1,
siae=cls.siae_with_tender_1,
email_send_date=timezone.now(),
detail_contact_click_date=timezone.now(),
)

@patch("lemarche.utils.apis.api_brevo.sib_api_v3_sdk.Body")
def test_create_or_update_company_with_mocked_body(self, mock_body):
"""Test create_or_update_company with mocked body"""
mock_body_instance = MagicMock()
mock_body.return_value = mock_body_instance

create_or_update_company(self.siae1)
create_or_update_company(self.siae_1)

expected_attributes = {
"domain": self.siae1.website,
"phone_number": self.siae1.contact_phone_display,
"app_id": self.siae1.id,
"domain": self.siae_1.website,
"phone_number": self.siae_1.contact_phone_display,
"app_id": self.siae_1.id,
"siae": True,
"active": self.siae1.is_active,
"description": self.siae1.description,
"kind": self.siae1.kind,
"address_street": self.siae1.address,
"address_post_code": self.siae1.post_code,
"address_city": self.siae1.city,
"contact_email": self.siae1.contact_email,
"logo_url": self.siae1.logo_url,
"geo_range": self.siae1.geo_range,
"app_url": get_object_share_url(self.siae1),
"app_admin_url": get_object_admin_url(self.siae1),
**self.siae1.extra_data, # includes completion_rate, tender_email_send_count, etc.
"active": self.siae_1.is_active,
"description": self.siae_1.description,
"kind": self.siae_1.kind,
"address_street": self.siae_1.address,
"address_post_code": self.siae_1.post_code,
"address_city": self.siae_1.city,
"contact_email": self.siae_1.contact_email,
"logo_url": self.siae_1.logo_url,
"geo_range": self.siae_1.geo_range,
"app_url": get_object_share_url(self.siae_1),
"app_admin_url": get_object_admin_url(self.siae_1),
**self.siae_1.extra_data, # includes completion_rate, tender_email_send_count, etc.
}

mock_body.assert_called_once_with(name="Test Company 1", attributes=expected_attributes)
Expand All @@ -49,44 +73,56 @@ def test_new_siaes_are_synced_in_brevo(self, mock_create_or_update_company):
"""Test new siaes are synced in brevo"""
call_command("crm_brevo_sync_companies")

mock_create_or_update_company.assert_any_call(self.siae1)
mock_create_or_update_company.assert_any_call(self.siae2)
mock_create_or_update_company.assert_any_call(self.siae_1)
mock_create_or_update_company.assert_any_call(self.siae_2)
self.assertEqual(mock_create_or_update_company.call_count, 2)

@patch("lemarche.utils.apis.api_brevo.create_or_update_company")
def test_siae_extra_data_is_updated(self, mock_create_or_update_company):
"""Test siae is updated if extra_data is changed."""
initial_extra_data = self.siae2.extra_data.copy()

self.siae2.completion_rate = 70
self.siae2.tender_email_send_count = 10
self.siae2.save()
initial_extra_data = self.siae_with_tender_1.extra_data.copy()
print("TEST : initial_extra_data = ", initial_extra_data)
print("email_send_date : ", self.siae_with_tender_1.tendersiae_set.first().email_send_date)
print("detail_contact_click_date : ", self.siae_with_tender_1.tendersiae_set.first().detail_contact_click_date)
# Simulate updates
siae_with_tender_stats = Siae.objects.with_tender_stats().filter(id=self.siae_with_tender_1.id).first()
# siae_with_tender_stats.update(
# email_send_date=now - timedelta(days=45),
# detail_contact_click_date=now - timedelta(days=30),
# )
print("email_send_date : ", siae_with_tender_stats.email_send_date)
print("detail_contact_click_date : ", siae_with_tender_stats.detail_contact_click_date)

call_command("crm_brevo_sync_companies", recently_updated=True)

self.assertTrue(mock_create_or_update_company.called)
self.siae_with_tender_1.refresh_from_db()

self.siae2.refresh_from_db()
expected_extra_data = {
"completion_rate": self.siae2.completion_rate,
"tender_email_send_count": self.siae2.tender_email_send_count,
"recent_tender_detail_click_count": self.siae2.recent_tender_detail_click_count,
"completion_rate": self.siae_with_tender_1.completion_rate,
"recent_tender_email_send_count": siae_with_tender_stats.tender_email_send_count_annotated,
"recent_tender_detail_click_count": siae_with_tender_stats.tender_detail_contact_click_count_annotated,
}

self.assertNotEqual(initial_extra_data, expected_extra_data, "siae.extra_data aurait dût être mis à jour.")
print("TEST : self.siae_2.extra_data = ", self.siae_with_tender_1.extra_data)
print(("TEST : expected_extra_data = ", expected_extra_data))
self.assertNotEqual(initial_extra_data, expected_extra_data, "siae.extra_data aurait dû être mis à jour.")
self.assertEqual(
self.siae_with_tender_1.extra_data, expected_extra_data, "siae.extra_data n'est pas conforme aux attentes."
)

@patch("lemarche.utils.apis.api_brevo.create_or_update_company")
def test_siae_extra_data_is_not_updated_if_no_change(self, mock_create_or_update_company):
"""Test siae is not updated if no change in extra_data."""
initial_extra_data = self.siae2.extra_data.copy()
initial_extra_data = self.siae_2.extra_data.copy()

call_command("crm_brevo_sync_companies", recently_updated=True)

self.assertTrue(mock_create_or_update_company.called)

self.siae2.refresh_from_db()
self.siae_2.refresh_from_db()
self.assertEqual(
initial_extra_data,
self.siae2.extra_data,
self.siae_2.extra_data,
"siae.extra_data a été mis à jour alors qu'il n'y avait pas de changement.",
)
22 changes: 4 additions & 18 deletions lemarche/siaes/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import timedelta
# from datetime import datetime, timedelta
from uuid import uuid4

from django.conf import settings
Expand Down Expand Up @@ -497,9 +497,10 @@ def filter_with_tender_tendersiae_status(self, tender, tendersiae_status=None):

return qs.distinct()

def with_tender_stats(self):
def with_tender_stats(self, days=0):
"""
Enrich each Siae with stats on their linked Tender
Enrich each Siae with stats on their linked Tender.
Optionally, limit the stats to the last `days` days.
"""
return self.annotate(
tender_count_annotated=Count("tenders", distinct=True),
Expand Down Expand Up @@ -968,14 +969,6 @@ def __init__(self, *args, **kwargs):
for field_name in self.TRACK_UPDATE_FIELDS:
setattr(self, f"__previous_{field_name}", getattr(self, field_name))

# siae.extra_data tracked for updates in Brevo sync command
if not self.extra_data:
self.extra_data = {
"completion_rate": self.completion_rate,
"tender_email_send_count": self.tender_email_send_count,
"recent_tender_detail_click_count": self.recent_tender_detail_click_count,
}

def set_slug(self, with_uuid=False):
"""
The slug field should be unique.
Expand Down Expand Up @@ -1303,13 +1296,6 @@ def elasticsearch_index_metadata(self):

return metadata

@property
def recent_tender_detail_click_count(self):
"""Calcule le nombre de clics récents pour cette instance de Siae."""
if not self.pk:
return 0
return self.tendersiae_set.filter(detail_contact_click_date__gte=timezone.now() - timedelta(days=90)).count()

def sectors_list_string(self, display_max=3):
sectors_name_list = self.sectors.form_filter_queryset().values_list("name", flat=True)
if display_max and len(sectors_name_list) > display_max:
Expand Down

0 comments on commit 4cf5fc5

Please sign in to comment.