diff --git a/lemarche/tenders/admin.py b/lemarche/tenders/admin.py index 531a93496..f29d4157d 100644 --- a/lemarche/tenders/admin.py +++ b/lemarche/tenders/admin.py @@ -209,6 +209,8 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin): "siae_detail_cocontracting_click_count_annotated_with_link", "siae_detail_not_interested_click_count_annotated_with_link", "siae_ai_count_annotated_with_link", + "siae_transactioned_source", + "siae_transactioned_last_updated", "logs_display", "extra_data_display", "source", @@ -336,12 +338,9 @@ class TenderAdmin(FieldsetsInlineMixin, admin.ModelAdmin): "Transaction ?", { "fields": ( - "survey_transactioned_send_date", - "survey_transactioned_answer", - "survey_transactioned_amount", - "survey_transactioned_feedback", - "survey_transactioned_answer_date", + *Tender.FIELDS_SURVEY_TRANSACTIONED, "siae_transactioned", + "siae_transactioned_source", "siae_transactioned_last_updated", ) }, diff --git a/lemarche/tenders/constants.py b/lemarche/tenders/constants.py index d3fcbfbdc..0a91ebbbc 100644 --- a/lemarche/tenders/constants.py +++ b/lemarche/tenders/constants.py @@ -152,6 +152,15 @@ (SOURCE_TALLY, "TALLY"), ) +TENDER_SIAE_TRANSACTIONED_SOURCE_ADMIN = "ADMIN" +TENDER_SIAE_TRANSACTIONED_SOURCE_AUTHOR = "AUTHOR" +TENDER_SIAE_TRANSACTIONED_SOURCE_SIAE = "SIAE" +TENDER_SIAE_TRANSACTIONED_SOURCE_CHOICES = ( + (TENDER_SIAE_TRANSACTIONED_SOURCE_ADMIN, "Admin"), + (TENDER_SIAE_TRANSACTIONED_SOURCE_AUTHOR, "Auteur"), + (TENDER_SIAE_TRANSACTIONED_SOURCE_SIAE, "Structure"), +) + TENDER_SIAE_SOURCE_EMAIL = "EMAIL" TENDER_SIAE_SOURCE_DASHBOARD = "DASHBOARD" TENDER_SIAE_SOURCE_LINK = "LINK" diff --git a/lemarche/tenders/migrations/0080_tender_siae_transactioned_source_and_more.py b/lemarche/tenders/migrations/0080_tender_siae_transactioned_source_and_more.py new file mode 100644 index 000000000..a95b2ab7a --- /dev/null +++ b/lemarche/tenders/migrations/0080_tender_siae_transactioned_source_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 4.2.9 on 2024-03-11 15:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("tenders", "0079_tender_siae_transactioned_last_updated"), + ] + + operations = [ + migrations.AddField( + model_name="tender", + name="siae_transactioned_source", + field=models.CharField( + blank=True, + choices=[("ADMIN", "Admin"), ("AUTHOR", "Auteur"), ("SIAE", "Structure")], + help_text="Champ mis à jour automatiquement", + max_length=20, + null=True, + verbose_name="Abouti à une transaction : source", + ), + ), + migrations.AlterField( + model_name="tender", + name="siae_transactioned_last_updated", + field=models.DateTimeField( + blank=True, + help_text="Champ mis à jour automatiquement", + null=True, + verbose_name="Abouti à une transaction : date de mise à jour", + ), + ), + ] diff --git a/lemarche/tenders/models.py b/lemarche/tenders/models.py index 1191408f1..27db6d84f 100644 --- a/lemarche/tenders/models.py +++ b/lemarche/tenders/models.py @@ -21,7 +21,12 @@ from lemarche.tenders.utils import find_amount_ranges from lemarche.users.models import User from lemarche.utils.apis import api_elasticsearch -from lemarche.utils.constants import ADMIN_FIELD_HELP_TEXT, MARCHE_BENEFIT_CHOICES, RECALCULATED_FIELD_HELP_TEXT +from lemarche.utils.constants import ( + ADMIN_FIELD_HELP_TEXT, + AUTO_FIELD_HELP_TEXT, + MARCHE_BENEFIT_CHOICES, + RECALCULATED_FIELD_HELP_TEXT, +) from lemarche.utils.fields import ChoiceArrayField from lemarche.utils.urls import get_object_admin_url @@ -514,8 +519,19 @@ class Tender(models.Model): blank=True, null=True, ) + siae_transactioned_source = models.CharField( + verbose_name="Abouti à une transaction : source", + help_text=AUTO_FIELD_HELP_TEXT, + max_length=20, + choices=tender_constants.TENDER_SIAE_TRANSACTIONED_SOURCE_CHOICES, + blank=True, + null=True, + ) siae_transactioned_last_updated = models.DateTimeField( - "Abouti à une transaction : date de mise à jour", blank=True, null=True + verbose_name="Abouti à une transaction : date de mise à jour", + help_text=AUTO_FIELD_HELP_TEXT, + blank=True, + null=True, ) amount_exact = models.PositiveIntegerField( verbose_name="Montant exact du besoin", help_text=ADMIN_FIELD_HELP_TEXT, blank=True, null=True diff --git a/lemarche/utils/constants.py b/lemarche/utils/constants.py index 697318793..4f87050c8 100644 --- a/lemarche/utils/constants.py +++ b/lemarche/utils/constants.py @@ -1,6 +1,7 @@ EMPTY_CHOICE = (("", ""),) ADMIN_FIELD_HELP_TEXT = "Champ renseigné par un ADMIN" +AUTO_FIELD_HELP_TEXT = "Champ mis à jour automatiquement" RECALCULATED_FIELD_HELP_TEXT = "Champ recalculé à intervalles réguliers" MARCHE_BENEFIT_TIME = "TIME" diff --git a/lemarche/www/tenders/tests.py b/lemarche/www/tenders/tests.py index 8fcf7a4ee..d6f702c72 100644 --- a/lemarche/www/tenders/tests.py +++ b/lemarche/www/tenders/tests.py @@ -1789,6 +1789,7 @@ def test_only_tender_author_with_sesame_token_can_call_tender_survey_transaction def test_update_tender_stats_on_tender_survey_transactioned_answer_true(self): self.assertIsNone(Tender.objects.get(id=self.tender.id).survey_transactioned_answer) self.assertIsNone(Tender.objects.get(id=self.tender.id).siae_transactioned) + self.assertIsNone(Tender.objects.get(id=self.tender.id).siae_transactioned_source) self.assertIsNone(Tender.objects.get(id=self.tender.id).siae_transactioned_last_updated) # load with answer 'True': partial form url = self.url + self.user_buyer_1_sesame_query_string + "&answer=True" @@ -1796,6 +1797,10 @@ def test_update_tender_stats_on_tender_survey_transactioned_answer_true(self): self.assertEqual(response.status_code, 200) self.assertTrue(Tender.objects.get(id=self.tender.id).survey_transactioned_answer) self.assertTrue(Tender.objects.get(id=self.tender.id).siae_transactioned) + self.assertEqual( + Tender.objects.get(id=self.tender.id).siae_transactioned_source, + tender_constants.TENDER_SIAE_TRANSACTIONED_SOURCE_AUTHOR, + ) self.assertIsNotNone(Tender.objects.get(id=self.tender.id).siae_transactioned_last_updated) # fill in form response = self.client.post( @@ -1883,11 +1888,20 @@ def test_only_tender_author_with_sesame_token_can_call_tender_siae_survey_transa # full form displayed (but should never happen) def test_update_tender_stats_on_tender_siae_survey_transactioned_answer_true(self): + ts = TenderSiae.objects.get(tender=self.tender, siae=self.siae) + self.assertIsNone(ts.survey_transactioned_answer) + self.assertIsNone(ts.tender.siae_transactioned) + self.assertIsNone(ts.tender.siae_transactioned_source) + self.assertIsNone(ts.tender.siae_transactioned_last_updated) # load with answer 'True': partial form url = self.url + self.user_siae_1_sesame_query_string + "&answer=True" response = self.client.get(url, follow=True) self.assertEqual(response.status_code, 200) - self.assertTrue(TenderSiae.objects.get(tender=self.tender, siae=self.siae).survey_transactioned_answer) + ts = TenderSiae.objects.get(tender=self.tender, siae=self.siae) + self.assertTrue(ts.survey_transactioned_answer) + self.assertTrue(ts.tender.siae_transactioned) + self.assertEqual(ts.tender.siae_transactioned_source, tender_constants.TENDER_SIAE_TRANSACTIONED_SOURCE_SIAE) + self.assertIsNotNone(ts.tender.siae_transactioned_last_updated) # fill in form response = self.client.post( url, data={"survey_transactioned_amount": 1000, "survey_transactioned_feedback": "Feedback"}, follow=True diff --git a/lemarche/www/tenders/views.py b/lemarche/www/tenders/views.py index 0fad60fb9..3c8f9ce23 100644 --- a/lemarche/www/tenders/views.py +++ b/lemarche/www/tenders/views.py @@ -622,7 +622,9 @@ def get(self, request, *args, **kwargs): # update tender self.object.survey_transactioned_answer = survey_transactioned_answer self.object.survey_transactioned_answer_date = timezone.now() - self.object.siae_transactioned = survey_transactioned_answer + if self.object.siae_transactioned is None: + self.object.siae_transactioned = survey_transactioned_answer + self.object.siae_transactioned_source = tender_constants.TENDER_SIAE_TRANSACTIONED_SOURCE_AUTHOR self.object.save() else: pass @@ -685,10 +687,17 @@ def get(self, request, *args, **kwargs): if survey_transactioned_answer in ["True", "False"]: # transform survey_transactioned_answer into bool survey_transactioned_answer = survey_transactioned_answer == "True" - # update tender + # update tendersiae self.object.survey_transactioned_answer = survey_transactioned_answer self.object.survey_transactioned_answer_date = timezone.now() self.object.save() + # update tender + if self.object.tender.siae_transactioned is None: + self.object.tender.siae_transactioned = survey_transactioned_answer + self.object.tender.siae_transactioned_source = ( + tender_constants.TENDER_SIAE_TRANSACTIONED_SOURCE_SIAE + ) + self.object.tender.save() else: pass # TODO or not? "answer" should always be passed