-
Notifications
You must be signed in to change notification settings - Fork 0
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
Option pour remplacer un ingrédient demandé par un ingrédient existant #1334
base: staging
Are you sure you want to change the base?
Conversation
This is to cut down on the size of the file as more actions are added
276a7b6
to
803d024
Compare
This is a simplification of the needs to reduce the scope of the PR
…ing with element of wrong type
…tion summary view
This is an initial simple implementation that needs to be updated to hide alert once recalculation has happened
@@ -103,7 +103,23 @@ def update(self, instance, validated_data): | |||
) | |||
|
|||
|
|||
class DeclaredIngredientCommonSerializer(PrivateFieldsSerializer): | |||
class DeclaredElementNestedField: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cette refacto avait du sens quand j'ai commencé la PR. Maintenant, elle paraît un peu hors scope mais je l'ai laissée dedans car je trouve que c'est cool quand même de ne pas dupliquer la logique de create
@@ -1638,7 +1638,9 @@ def test_get_single_declared_plant(self): | |||
declaration = DeclarationFactory() | |||
plant = DeclaredPlantFactory(declaration=declaration) | |||
|
|||
response = self.client.get(reverse("api:declared_plant", kwargs={"pk": plant.id}), format="json") | |||
response = self.client.get( | |||
reverse("api:declared_element", kwargs={"pk": plant.id, "type": "plant"}), format="json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dans cette PR, j'ai du changer l'API de REST vers RPC pour avoir un meilleur contrôle sur les actions de demande de plus d'infos (fait dans une PR avant), refus (aussi dans une autre PR), et le remplacement (le cible de cette PR).
Surtout, la refacto nous donne la possibilité de ne pas envoyer le statut et aussi de modifier des champs liés, comme mettre le champ new
à False
Pendant ce changement, j'ai remarqué que c'est possible de changer l'API pour reduire la duplication de code entre 4 types d'element et 4 actions par demande.
Alors ici, on voit que j'ai remplacé l'api:declared_plant
avec api:declared_element... "type": "plant"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'accord avec toi, ces actions semblent être plus transactionnelles qu'autre chose, du coup une approche RPC me semble plus adapté 👍
reverse("api:declared_microorganism", kwargs={"pk": microorganism.id}), | ||
{"requestStatus": DeclaredMicroorganism.AddableStatus.INFORMATION, "requestPrivateNotes": "some notes"}, | ||
response = self.client.post( | ||
reverse("api:declared_element_request_info", kwargs={"pk": microorganism.id, "type": "microorganism"}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avec la refacto, un appel REST vers api:declared_x
est devenu un appel vers api:declared_x_action
self.assertEqual(microorganism.request_status, DeclaredMicroorganism.AddableStatus.INFORMATION) | ||
|
||
@authenticate | ||
def test_reject_declared_element(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il y avait pas un test pour le refus d'ingrédient avant
@@ -1753,3 +1808,46 @@ def test_status_visible_to_instructor(self): | |||
m = declared_microorganisms[0] | |||
self.assertIn("requestStatus", m) | |||
self.assertIn("requestPrivateNotes", m) | |||
|
|||
@authenticate | |||
def test_replace_declared_plant(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enfin on arrive aux tests ajoutés pour vérifier la vraie nouvelle fonctionnalité de cette PR 🎉
@@ -21,18 +21,22 @@ | |||
path("elements/autocomplete/", views.AutocompleteView.as_view(), name="substance_autocomplete"), | |||
# Declared elements | |||
path("new-declared-elements/", views.DeclaredElementsView.as_view(), name="list_new_declared_elements"), | |||
path("declared-elements/plants/<int:pk>", views.DeclaredPlantView.as_view(), name="declared_plant"), | |||
path("declared-elements/<str:type>/<int:pk>", views.DeclaredElementView.as_view(), name="declared_element"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maintenant le nouveau api c'est:
pour lire: declared-elements/<type>/<id>
pour prendre une decision: declared-elements/<type>/<id>/<action name>
(avant c'etait declared-elements/<type en pluriel>/<id>
REST)
permission_classes = [(IsInstructor | IsVisor)] | ||
serializer_class = DeclaredPlantSerializer | ||
queryset = DeclaredPlant.objects.all() | ||
class ElementMappingMixin: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
au lieu d'avoir une vue dédiée pour chaque type d'element, ce mixin nous donne les clés pour avoir une vue par besoin (Retrieve, Refus, Demande d'infos, Remplacement, etc...)
@@ -77,6 +77,15 @@ | |||
/> | |||
|
|||
<p class="font-bold mt-8">Substances contenues dans la composition :</p> | |||
<DsfrAlert v-if="replacedRequestsWithSubstances.length" type="warning" class="mb-4"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
est-ce que c'est un pb que cet avertissement va rester même après l'aller-retour instructrice - déclarant - instructrice ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Peut-être on pourra ajuster le message 🤔
« Les ingrédients suivantes, ajoutés pour remplacer une demande, rajoutent des substances dans la composition.
Veuillez vérifier que les doses totales des substances restent pertinentes. »
Ou enfin qqchose du genre, sans forcément dire qu'il faut toujours contacter le pro.
@blur="hasFocus = false" | ||
@keydown="checkKeyboardNav($event)" | ||
/> | ||
<div :class="hideSearchButton ? '' : 'flex items-end'"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avant, quand hideSearchButton
est false
le label du champ DsfrInput
(quand donné) est affiché à côté du champ et non pas au dessus. Ce changement repare ça
@@ -0,0 +1,48 @@ | |||
<template> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pendant une refacto, j'ai créé ce fichier pour améliorer le focus du code principal dans index.vue
validated_data[self.nested_field_name] = self.nested_model.objects.get(pk=element.get("id")) | ||
except self.nested_model.DoesNotExist: | ||
raise ProjectAPIException( | ||
field_errors={f"declared_{self.nested_field_name}s": "L'ingrédient spécifiée n'existe pas."} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il faudra adapter aussi le message de l'exception non ? Genre
field_errors={f"declared_{self.nested_field_name}s": f"L'objet « ${self.nested_field_name} » spécifiée n'existe pas."}
@@ -1638,7 +1638,9 @@ def test_get_single_declared_plant(self): | |||
declaration = DeclarationFactory() | |||
plant = DeclaredPlantFactory(declaration=declaration) | |||
|
|||
response = self.client.get(reverse("api:declared_plant", kwargs={"pk": plant.id}), format="json") | |||
response = self.client.get( | |||
reverse("api:declared_element", kwargs={"pk": plant.id, "type": "plant"}), format="json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'accord avec toi, ces actions semblent être plus transactionnelles qu'autre chose, du coup une approche RPC me semble plus adapté 👍
@@ -1753,3 +1808,46 @@ def test_status_visible_to_instructor(self): | |||
m = declared_microorganisms[0] | |||
self.assertIn("requestStatus", m) | |||
self.assertIn("requestPrivateNotes", m) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Est-ce que ça vaut la peine d'ajouter un test sur les permissions pour ces nouveaux endpoints ? Similaire à test_get_declared_element_not_allowed_not_instructor
@@ -77,6 +77,15 @@ | |||
/> | |||
|
|||
<p class="font-bold mt-8">Substances contenues dans la composition :</p> | |||
<DsfrAlert v-if="replacedRequestsWithSubstances.length" type="warning" class="mb-4"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Peut-être on pourra ajuster le message 🤔
« Les ingrédients suivantes, ajoutés pour remplacer une demande, rajoutent des substances dans la composition.
Veuillez vérifier que les doses totales des substances restent pertinentes. »
Ou enfin qqchose du genre, sans forcément dire qu'il faut toujours contacter le pro.
@@ -85,6 +87,10 @@ const props = defineProps({ | |||
type: Boolean, | |||
default: false, | |||
}, | |||
optional: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Est-ce que ça serait plus cohérent avec l'API des inputs de le nommer required
? et donc par la suite dans la ligne 11 :required="required"
.
Surtout que de cette façon les autres composants utilisant ElementAutocomplete
et n'envoyant pas explicitement la prop se retrouveront avec un changement de comportement : leur champ deviendra obligatoire.
<DsfrBadge v-if="result.novelFood" label="Novel Food" small type="new" /> | ||
<ElementStatusBadge v-if="result.status" :text="result.status" /> | ||
</div> | ||
<!-- TODO: make this a tag and align with badges, check DSFR --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
D'ailleurs on essaie de faire les commentaires en français dans le code. On n'est pas non plus hyper strictes mais p-e pour les prochains mieux de le faire en FR pour avoir une certaine cohérence.
<div v-if="modalToOpen === 'replace'"> | ||
<p v-if="cannotReplace"> | ||
Ce n'est pas possible pour l'instant de remplacer une demande avec un ingrédient d'un type different. | ||
Veuillez contacter l'équipe Compl'Alim pour résoudre le substitution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Veuillez contacter l'équipe Compl'Alim pour résoudre le substitution. | |
Veuillez contacter l'équipe Compl'Alim pour effectuer la substitution. |
.json() | ||
// TODO: is this handling errors nicely? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On peut le tester en envoyant un BadRequest programmatiquement, si tu veux on peut regarder ensemble
Dans le scope : fonctionnalité pour trouver un ingrédient de même type et remplacer une demande avec.
Hors du scope : ajout de synonyme en même temps; remplacement d'une demande par un ingrédient d'autre type (par ex microorganisme avec plante), à faire à la main pour l'instant
Control de la demande
Il y a une explication quand le remplacement est bloqué au cause du type
Quand la demande a été remplacée :
MAJ du badge pour les instructrices
NB: Les déclarants vont voir le nom du remplacement si ils vont regarder la déclaration.
Calculation de substances
Le tableau de substances est déjà automatiquement recalculé. Cette PR ajoute un avertissement au dessus si il y a des remplacements qui ont des substances.
NB: pour l'instant, cet avertissement est toujours affiché pour l'instructrice. Question: est-ce que c'est acceptable en premier temps ?