diff --git a/plugins/polio/admin.py b/plugins/polio/admin.py index 888cbd9496..f2dae16423 100644 --- a/plugins/polio/admin.py +++ b/plugins/polio/admin.py @@ -332,7 +332,7 @@ def save_related(self, request, form, formsets, change): class ChronogramTaskAdminInline(admin.StackedInline): model = ChronogramTask extra = 0 - raw_id_fields = ("user_in_charge", "created_by", "updated_by") + raw_id_fields = ("created_by", "updated_by") readonly_fields = ( "created_at", "created_by", @@ -342,12 +342,7 @@ class ChronogramTaskAdminInline(admin.StackedInline): ) def get_queryset(self, request): - return ( - super() - .get_queryset(request) - .valid() - .select_related("chronogram__round", "user_in_charge", "created_by", "updated_by") - ) + return super().get_queryset(request).valid().select_related("chronogram__round", "created_by", "updated_by") @admin.register(Chronogram) diff --git a/plugins/polio/api/chronogram/serializers.py b/plugins/polio/api/chronogram/serializers.py index a06449a7d5..bc0ee09acb 100644 --- a/plugins/polio/api/chronogram/serializers.py +++ b/plugins/polio/api/chronogram/serializers.py @@ -87,11 +87,6 @@ class Meta: "get_status_display": {"read_only": True}, } - def to_representation(self, instance): - representation = super().to_representation(instance) - representation["user_in_charge"] = UserNestedSerializer(instance.user_in_charge, read_only=True).data - return representation - class ChronogramSerializer(DynamicFieldsModelSerializer, serializers.ModelSerializer): campaign_obr_name = serializers.CharField(source="round.campaign.obr_name") diff --git a/plugins/polio/api/chronogram/views.py b/plugins/polio/api/chronogram/views.py index d477912a3a..b36994318e 100644 --- a/plugins/polio/api/chronogram/views.py +++ b/plugins/polio/api/chronogram/views.py @@ -57,7 +57,7 @@ def get_queryset(self) -> QuerySet: .filter(round_id__in=rounds_ids) .select_related("round__campaign", "created_by", "updated_by") .prefetch_related(Prefetch("tasks", queryset=ChronogramTask.objects.valid())) - .prefetch_related("tasks__user_in_charge", "tasks__created_by", "tasks__updated_by") + .prefetch_related("tasks__created_by", "tasks__updated_by") .order_by("created_at") ) @@ -130,7 +130,7 @@ def get_queryset(self) -> QuerySet: return ( ChronogramTask.objects.valid() .filter(chronogram__round__campaign__in=campaigns) - .select_related("chronogram__round", "user_in_charge", "created_by", "updated_by") + .select_related("chronogram__round", "created_by", "updated_by") .order_by("created_at") ) diff --git a/plugins/polio/js/src/domains/Chronogram/Chronogram/types.ts b/plugins/polio/js/src/domains/Chronogram/Chronogram/types.ts index 34e4e31aa7..b5b638bcb3 100644 --- a/plugins/polio/js/src/domains/Chronogram/Chronogram/types.ts +++ b/plugins/polio/js/src/domains/Chronogram/Chronogram/types.ts @@ -27,7 +27,7 @@ export type ChronogramTask = { deadline_date: string; // Date status: string; get_status_display: string; - user_in_charge: User; + user_in_charge: string; delay_in_days: number; comment: string; // Optional fields. diff --git a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Modals/ChronogramTaskCreateEditModal.tsx b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Modals/ChronogramTaskCreateEditModal.tsx index a2222384f9..b27ec792e2 100644 --- a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Modals/ChronogramTaskCreateEditModal.tsx +++ b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Modals/ChronogramTaskCreateEditModal.tsx @@ -14,7 +14,6 @@ import * as Permission from '../../../../../../../../hat/assets/js/apps/Iaso/uti import TextInput from '../../../../../../../../hat/assets/js/apps/Iaso/domains/pages/components/TextInput'; import { EditIconButton } from '../../../../../../../../hat/assets/js/apps/Iaso/components/Buttons/EditIconButton'; import { InputWithInfos } from '../../../../../../../../hat/assets/js/apps/Iaso/components/InputWithInfos'; -import { useGetProfilesDropdown } from '../../../../../../../../hat/assets/js/apps/Iaso/domains/teams/hooks/requests/useGetProfilesDropdown'; import MESSAGES from '../messages'; import { ChronogramTask } from '../../Chronogram/types'; @@ -45,9 +44,6 @@ const CreateEditChronogramTaskModal: FunctionComponent = ({ }) => { const { formatMessage } = useSafeIntl(); - const { data: profilesDropdown, isFetching: isFetchingProfiles } = - useGetProfilesDropdown(); - const { mutate: confirm } = useCreateEditChronogramTask(); const schema = useChronogramTaskSchema(); const formik = useFormik({ @@ -59,7 +55,7 @@ const CreateEditChronogramTaskModal: FunctionComponent = ({ description_fr: chronogramTask?.description_fr, start_offset_in_days: chronogramTask?.start_offset_in_days, status: chronogramTask?.status, - user_in_charge: chronogramTask?.user_in_charge.id, + user_in_charge: chronogramTask?.user_in_charge, comment: chronogramTask?.comment, }, enableReinitialize: true, @@ -158,9 +154,7 @@ const CreateEditChronogramTaskModal: FunctionComponent = ({ diff --git a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Table/useChronogramDetailsTableColumn.tsx b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Table/useChronogramDetailsTableColumn.tsx index a44090ac73..299a16f8d5 100644 --- a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Table/useChronogramDetailsTableColumn.tsx +++ b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/Table/useChronogramDetailsTableColumn.tsx @@ -63,8 +63,7 @@ export const useChronogramDetailsTableColumn = ( { Header: formatMessage(MESSAGES.labelUserInCharge), id: 'user_in_charge', - accessor: row => - row.user_in_charge.full_name || row.user_in_charge.username, + accessor: 'user_in_charge', sortable: false, }, { diff --git a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/hooks/validation.ts b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/hooks/validation.ts index de264abdd3..af4b6af3dd 100644 --- a/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/hooks/validation.ts +++ b/plugins/polio/js/src/domains/Chronogram/ChronogramDetails/hooks/validation.ts @@ -24,7 +24,7 @@ export const useChronogramTaskSchema = () => { .string() .trim() .required(formatMessage(MESSAGES.validationFieldRequired)), - user_in_charge: yup.number().nullable(), + user_in_charge: yup.string().trim().nullable(), comment: yup.string().trim(), }); }; diff --git a/plugins/polio/migrations/0194_chronogramtask_user_in_charge_new.py b/plugins/polio/migrations/0194_chronogramtask_user_in_charge_new.py new file mode 100644 index 0000000000..b099e90c30 --- /dev/null +++ b/plugins/polio/migrations/0194_chronogramtask_user_in_charge_new.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.14 on 2024-08-27 14:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("polio", "0193_alter_incidentreport_stock_correction"), + ] + + operations = [ + migrations.AddField( + model_name="chronogramtask", + name="user_in_charge_new", + field=models.CharField(blank=True, max_length=255), + ), + ] diff --git a/plugins/polio/migrations/0195_migrate_chronogramtask_user_in_charge.py b/plugins/polio/migrations/0195_migrate_chronogramtask_user_in_charge.py new file mode 100644 index 0000000000..f82651ed2a --- /dev/null +++ b/plugins/polio/migrations/0195_migrate_chronogramtask_user_in_charge.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.14 on 2024-08-27 14:49 + +from django.db import migrations + + +def migrate_data_forward(apps, schema_editor): + ChronogramTask = apps.get_model("polio", "ChronogramTask") + tasks = ChronogramTask.objects.filter(user_in_charge__isnull=False).select_related("user_in_charge") + objs = [] + for task in tasks: + user = task.user_in_charge + user_str = "" + if user.first_name and user.last_name: + user_str = f"{user.first_name} {user.last_name}" + elif user.first_name or user.last_name: + user_str = user.first_name or user.last_name + elif user.username: + user_str = user.username + if user_str: + task.user_in_charge_new = user_str + objs.append(task) + ChronogramTask.objects.bulk_update(objs, ["user_in_charge_new"]) + + +class Migration(migrations.Migration): + dependencies = [ + ("polio", "0194_chronogramtask_user_in_charge_new"), + ] + + operations = [migrations.RunPython(migrate_data_forward, migrations.RunPython.noop, elidable=True)] diff --git a/plugins/polio/migrations/0196_remove_chronogramtask_user_in_charge_new_and_more.py b/plugins/polio/migrations/0196_remove_chronogramtask_user_in_charge_new_and_more.py new file mode 100644 index 0000000000..1c389a884a --- /dev/null +++ b/plugins/polio/migrations/0196_remove_chronogramtask_user_in_charge_new_and_more.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.14 on 2024-08-27 15:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("polio", "0195_migrate_chronogramtask_user_in_charge"), + ] + + operations = [ + migrations.RemoveField( + model_name="chronogramtask", + name="user_in_charge", + ), + migrations.RenameField( + model_name="chronogramtask", + old_name="user_in_charge_new", + new_name="user_in_charge", + ), + ] diff --git a/plugins/polio/models/chronogram.py b/plugins/polio/models/chronogram.py index 0094bfebc9..44e714c121 100644 --- a/plugins/polio/models/chronogram.py +++ b/plugins/polio/models/chronogram.py @@ -145,9 +145,7 @@ class Status(models.TextChoices): description = TranslatedField(models.TextField(max_length=300), {"fr": {"blank": True}}) start_offset_in_days = models.IntegerField(default=0) status = models.CharField(max_length=15, choices=Status.choices, default=Status.PENDING) - user_in_charge = models.ForeignKey( - User, null=True, blank=True, on_delete=models.SET_NULL, related_name="chronogram_tasks" - ) + user_in_charge = models.CharField(max_length=255, blank=True) comment = models.TextField(max_length=300, blank=True) created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( diff --git a/plugins/polio/tests/api/test_chronogram_serializers.py b/plugins/polio/tests/api/test_chronogram_serializers.py index ddd7bb26c3..71ba04675f 100644 --- a/plugins/polio/tests/api/test_chronogram_serializers.py +++ b/plugins/polio/tests/api/test_chronogram_serializers.py @@ -51,7 +51,7 @@ def setUpTestData(cls): description_en="Ordering markers", description_fr="Assurer la commande des marqueurs", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", comment="Comment", ) @@ -73,7 +73,7 @@ def test_serialize_chronogram_task(self): "deadline_date": "2024-06-27", "status": "PENDING", "get_status_display": "Not started", - "user_in_charge": {"id": self.user.id, "username": "test", "full_name": "John Doe"}, + "user_in_charge": "John Doe", "delay_in_days": 0, "comment": "Comment", "created_at": "2024-06-27T14:00:00Z", @@ -98,7 +98,7 @@ def test_serialize_chronogram_task(self): "deadline_date": "2024-06-27", "status": "PENDING", "get_status_display": "Pas commencé", - "user_in_charge": {"id": self.user.id, "username": "test", "full_name": "John Doe"}, + "user_in_charge": "John Doe", "delay_in_days": 0, "comment": "Comment", "created_at": "2024-06-27T14:00:00Z", @@ -116,7 +116,7 @@ def test_deserialize_chronogram_task(self): "description_fr": "Foo FR", "start_offset_in_days": 0, "status": ChronogramTask.Status.IN_PROGRESS, - "user_in_charge": self.user.pk, + "user_in_charge": "John Doe", "delay_in_days": 0, "comment": "Comment", } @@ -131,7 +131,7 @@ def test_deserialize_chronogram_task(self): self.assertEqual(chronogram_task.description_fr, "Foo FR") self.assertEqual(chronogram_task.start_offset_in_days, 0) self.assertEqual(chronogram_task.status, "IN_PROGRESS") - self.assertEqual(chronogram_task.user_in_charge, self.user) + self.assertEqual(chronogram_task.user_in_charge, "John Doe") self.assertEqual(chronogram_task.comment, "Comment") self.assertEqual(chronogram_task.created_by, self.user) self.assertEqual(chronogram_task.created_at, TODAY) diff --git a/plugins/polio/tests/api/test_chronogram_views.py b/plugins/polio/tests/api/test_chronogram_views.py index 3cc0b0ebac..150c054c49 100644 --- a/plugins/polio/tests/api/test_chronogram_views.py +++ b/plugins/polio/tests/api/test_chronogram_views.py @@ -54,7 +54,7 @@ def setUpTestData(cls): description_en="Ordering markers", description_fr="Assurer la commande des marqueurs", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", comment="Comment", ) @@ -82,7 +82,7 @@ def test_create_ok(self): "description_fr": "Baz FR", "start_offset_in_days": 0, "status": ChronogramTask.Status.IN_PROGRESS, - "user_in_charge": self.user.pk, + "user_in_charge": "John Doe", "comment": "Comment", } response = self.client.post("/api/polio/chronograms/tasks/", data=data, format="json") @@ -93,7 +93,7 @@ def test_create_ok(self): self.assertEqual(chronogram_task.description_en, "Baz EN") self.assertEqual(chronogram_task.description_fr, "Baz FR") self.assertEqual(chronogram_task.start_offset_in_days, 0) - self.assertEqual(chronogram_task.user_in_charge, self.user) + self.assertEqual(chronogram_task.user_in_charge, "John Doe") self.assertEqual(chronogram_task.comment, "Comment") self.assertEqual(chronogram_task.created_by, self.user) self.assertEqual(chronogram_task.created_at, TODAY) @@ -345,7 +345,7 @@ def setUpTestData(cls): description_en="Foo EN", description_fr="Foo FR", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", ) ChronogramTask.objects.create( period=Period.DURING, @@ -353,7 +353,7 @@ def setUpTestData(cls): description_en="Bar EN", description_fr="Bar FR", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", ) ChronogramTask.objects.create( period=Period.AFTER, @@ -361,7 +361,7 @@ def setUpTestData(cls): description_en="Baz EN", description_fr="BaZ FR", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", ) def test_get_without_auth(self): @@ -377,7 +377,7 @@ def test_get_without_perm(self): def test_get_ok(self): self.client.force_authenticate(self.user) - with self.assertNumQueries(7): + with self.assertNumQueries(6): response = self.client.get(f"/api/polio/chronograms/{self.chronogram.pk}/") self.assertJSONResponse(response, 200) self.assertEqual( @@ -396,7 +396,7 @@ def test_get_ok(self): def test_get_all_fields_ok(self): self.client.force_authenticate(self.user) - with self.assertNumQueries(7): + with self.assertNumQueries(6): response = self.client.get(f"/api/polio/chronograms/{self.chronogram.pk}/?fields=:all") self.assertJSONResponse(response, 200) self.assertEqual(len(response.data["tasks"]), 3) diff --git a/plugins/polio/tests/models/test_chronogram.py b/plugins/polio/tests/models/test_chronogram.py index 75dd70f4cc..0a724af8e4 100644 --- a/plugins/polio/tests/models/test_chronogram.py +++ b/plugins/polio/tests/models/test_chronogram.py @@ -52,7 +52,7 @@ def setUpTestData(cls): description_en="Ordering markers", description_fr="Assurer la commande des marqueurs", start_offset_in_days=-20, - user_in_charge=cls.user, + user_in_charge="John Doe", comment="Comment 1", ) cls.chronogram_task_2 = ChronogramTask.objects.create( @@ -61,7 +61,7 @@ def setUpTestData(cls): description_en="Daily supervision of logistics activities", description_fr="Supervision journalière des activités logistiques", start_offset_in_days=0, - user_in_charge=cls.user, + user_in_charge="John Doe", comment="Comment 2", ) cls.chronogram_task_3 = ChronogramTask.objects.create( @@ -70,7 +70,7 @@ def setUpTestData(cls): description_en="Share waste destruction report", description_fr="Partager le rapport de destruction des déchets", start_offset_in_days=14, - user_in_charge=cls.user, + user_in_charge="John Doe", comment="Comment 2", ) @@ -137,14 +137,14 @@ def test_percentage_of_completion(self): status=ChronogramTask.Status.DONE, chronogram=self.chronogram, start_offset_in_days=i, - user_in_charge=self.user, + user_in_charge="John Doe", ) ChronogramTask.objects.create( period=Period.DURING, status=ChronogramTask.Status.DONE, chronogram=self.chronogram, start_offset_in_days=0, - user_in_charge=self.user, + user_in_charge="John Doe", ) with self.assertNumQueries(1):