diff --git a/lemarche/crm/tests.py b/lemarche/crm/tests.py new file mode 100644 index 000000000..4ebacaeea --- /dev/null +++ b/lemarche/crm/tests.py @@ -0,0 +1,200 @@ +from datetime import timedelta +from unittest.mock import 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 + + +now = timezone.now() +date_tomorrow = now + timedelta(days=1) +old_date = timezone.now() - timedelta(days=91) +recent_date = now - timedelta(days=10) + + +class CrmBrevoSyncCompaniesCommandTest(TestCase): + @classmethod + def setUpTestData(cls): + """Siae instances initialization""" + cls.user_siae = UserFactory(kind=User.KIND_SIAE) + cls.siae_with_name = SiaeFactory(name="Test Company 1") + cls.siae_with_user = SiaeFactory(users=[cls.user_siae]) + cls.siae_with_brevo_id = SiaeFactory( + brevo_company_id="123456789", + completion_rate=50, + ) + + cls.tender_1 = TenderFactory(deadline_date=date_tomorrow) + cls.tender_2 = TenderFactory(deadline_date=date_tomorrow) + + TenderSiae.objects.create( + tender=cls.tender_1, + siae=cls.siae_with_user, + detail_contact_click_date=recent_date, + ) + + TenderSiae.objects.create( + tender=cls.tender_1, + siae=cls.siae_with_brevo_id, + email_send_date=recent_date, + detail_contact_click_date=old_date, + ) + + cls.siae_with_user_stats = Siae.objects.with_tender_stats().filter(id=cls.siae_with_user.id).first() + cls.siae_with_brevo_id_all_stats = ( + Siae.objects.with_tender_stats().filter(id=cls.siae_with_brevo_id.id).first() + ) + cls.siae_with_brevo_id_recent_stats = ( + Siae.objects.with_tender_stats(since_days=90).filter(id=cls.siae_with_brevo_id.id).first() + ) + + # siae_with_brevo_id.extra_data initialization + cls.siae_with_brevo_id.extra_data = { + "TAUX DE COMPLÉTION": cls.siae_with_brevo_id.completion_rate, + "BESOINS REÇUS": cls.siae_with_brevo_id_recent_stats.tender_email_send_count_annotated, + "BESOINS INTERESSÉS": cls.siae_with_brevo_id_recent_stats.tender_detail_contact_click_count_annotated, + } + cls.siae_with_brevo_id.save() + cls.initial_extra_data = cls.siae_with_brevo_id.extra_data.copy() + + def test_annotated_fields_set_up(self): + """Test annotated fields are correctly set up""" + self.assertEqual( + self.siae_with_user_stats.tender_email_send_count_annotated, + 0, + "Le nombre total de besoins reçus devrait être 0", + ) + self.assertEqual( + self.siae_with_user_stats.tender_detail_contact_click_count_annotated, + 1, + "Le nombre total de besoins intéressés devrait être 1", + ) + self.assertEqual( + self.siae_with_brevo_id_all_stats.tender_email_send_count_annotated, + 1, + "Le nombre total de besoins reçus devrait être 1", + ) + self.assertEqual( + self.siae_with_brevo_id_all_stats.tender_detail_contact_click_count_annotated, + 1, + "Le nombre total de besoins intéressés devrait être 1", + ) + self.assertEqual( + self.siae_with_brevo_id_recent_stats.tender_email_send_count_annotated, + 1, + "Le nombre de besoins reçus dans les 90 derniers jours devrait être 1", + ) + self.assertEqual( + self.siae_with_brevo_id_recent_stats.tender_detail_contact_click_count_annotated, + 0, + "Le nombre de besoins intéressés dans les 90 derniers jours devrait être 0", + ) + + @patch("lemarche.utils.apis.api_brevo.create_or_update_company") + 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") + + self.assertEqual(mock_create_or_update_company.call_count, 3) + + def test_siae_has_tender_stats(self): + self.assertIsNotNone( + self.siae_with_user_stats, + "Cette SIAE devrait avoir des statistiques sur les besoins.", + ) + self.assertIsNotNone( + self.siae_with_brevo_id_all_stats, + "Cette SIAE devrait avoir des statistiques sur les besoins.", + ) + + def test_siae_extra_data_is_set_on_first_sync(self): + """Test siae is updated if extra_data is changed.""" + # siae_with_user.extra_data should be empty + initial_extra_data = self.siae_with_user.extra_data.copy() + + call_command("crm_brevo_sync_companies", recently_updated=True) + + self.siae_with_user.refresh_from_db() + + expected_extra_data = { + "TAUX DE COMPLÉTION": self.siae_with_user.completion_rate, + "BESOINS REÇUS": self.siae_with_user_stats.tender_email_send_count_annotated, + "BESOINS INTERESSÉS": self.siae_with_user_stats.tender_detail_contact_click_count_annotated, + } + + self.assertNotEqual(initial_extra_data, expected_extra_data, "siae.extra_data aurait dû être mis à jour.") + self.assertEqual( + self.siae_with_user.extra_data, expected_extra_data, "siae.extra_data n'est pas conforme aux attentes." + ) + + def test_siae_extra_data_is_not_updated_if_no_changes(self): + """Test siae.extra_data is not updated if no changes.""" + call_command("crm_brevo_sync_companies", recently_updated=True) + + self.siae_with_brevo_id.refresh_from_db() + self.assertEqual( + self.initial_extra_data, + self.siae_with_brevo_id.extra_data, + "siae.extra_data a été mis à jour alors qu'il n'y avait pas de changement.", + ) + + def test_fields_update_within_90_days_and_ignore_older_changes(self): + """Test fields update within 90 days and ignore older changes.""" + TenderSiae.objects.create( + tender=self.tender_2, + siae=self.siae_with_brevo_id, + email_send_date=now, + detail_contact_click_date=now, + ) + + call_command("crm_brevo_sync_companies", recently_updated=True) + + self.siae_with_brevo_id_all_stats = ( + Siae.objects.with_tender_stats().filter(id=self.siae_with_brevo_id.id).first() + ) + self.siae_with_brevo_id_recent_stats = ( + Siae.objects.with_tender_stats(since_days=90).filter(id=self.siae_with_brevo_id.id).first() + ) + + # Tender stats without date limit + self.assertEqual( + self.siae_with_brevo_id_all_stats.tender_email_send_count_annotated, + 2, + "Le nombre total des besoins reçus devrait être 2", + ) + self.assertEqual( + self.siae_with_brevo_id_all_stats.tender_detail_contact_click_count_annotated, + 2, + "Le nombre de bsoins interessés devrait être 2", + ) + + # Tender stats with date limit + self.assertEqual( + self.siae_with_brevo_id_recent_stats.tender_email_send_count_annotated, + 2, + "Le nombre de besoins reçus dans les 90 jours devraient être 2", + ) + self.assertEqual( + self.siae_with_brevo_id_recent_stats.tender_detail_contact_click_count_annotated, + 1, + "Les nombre de bsoins interessés dans les 90 jours devraient être 1", + ) + + expected_extra_data = { + "TAUX DE COMPLÉTION": self.siae_with_brevo_id.completion_rate, + "BESOINS REÇUS": self.siae_with_brevo_id_recent_stats.tender_email_send_count_annotated, + "BESOINS INTERESSÉS": self.siae_with_brevo_id_recent_stats.tender_detail_contact_click_count_annotated, + } + + self.assertNotEqual( + self.initial_extra_data, + expected_extra_data, + "Les valeurs récentes dans extra_data devraient être mises à jour en fonction du filtre de 90 jours.", + )