Skip to content

Commit

Permalink
Merge branch 'staging' into 1439-option-pour-ajouter-des-synonymes-au…
Browse files Browse the repository at this point in the history
…-moment-de-remplacer-une-demande-dingrédient
  • Loading branch information
hfroot committed Jan 15, 2025
2 parents e42366b + a9e7694 commit da5a866
Show file tree
Hide file tree
Showing 46 changed files with 1,841 additions and 188 deletions.
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=bind,source=requirements.txt,target=requirements.txt \
python -m pip install -r requirements.txt

# Switch to the non-privileged user to run the application.
USER appuser

# Copy the source code into the container.
COPY . .

Expand Down
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
build:
docker compose build

run:
docker compose up

bash:
docker compose run --user root server bash -rm

clean:
docker image prune
docker container prune
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ avec `git commit -m 'my message' --no-verify`.
### Installation avec docker (_méthode 3_)

```
docker compose build
docker compose up
docker compose run -rm server bash
make build
make run
make bash
python manage.py migrate
```

Expand Down
1 change: 1 addition & 0 deletions api/serializers/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ class Meta:
"id",
"file",
"type",
"type_display",
"name",
)
read_only_fields = ("file",)
Expand Down
2 changes: 1 addition & 1 deletion api/tests/test_company.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def test_update_company_ko_unauthenticated(self):

def test_update_company_ko_bad_data(self):
self.login(self.supervisor)
self.payload["email"] = ""
self.payload["phone_number"] = ""
response = self.put(self.url(pk=self.company.id), self.payload)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

Expand Down
64 changes: 57 additions & 7 deletions api/tests/test_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
VisaRoleFactory,
PlantSynonymFactory,
)
from data.models import Attachment, Declaration, Snapshot, DeclaredMicroorganism, DeclaredPlant
from data.models import Attachment, Declaration, DeclaredMicroorganism, DeclaredPlant, Snapshot

from .utils import authenticate

Expand Down Expand Up @@ -1497,6 +1497,56 @@ def test_sort_declarations_by_instruction_limit(self):
self.assertEqual(results[1]["id"], declaration_middle.id)
self.assertEqual(results[2]["id"], declaration_last.id)

@authenticate
def test_sort_declarations_by_instruction_limit_with_visa(self):
"""
Le refus d'un visa ne doit pas compter pour le triage par date limite de réponse
"""
InstructionRoleFactory(user=authenticate.user)

today = timezone.now()

declaration_less_urgent = AwaitingInstructionDeclarationFactory()
snapshot_less_urgent = SnapshotFactory(
declaration=declaration_less_urgent, status=declaration_less_urgent.status
)
snapshot_less_urgent.creation_date = today - timedelta(days=1)
snapshot_less_urgent.save()

declaration_more_urgent = AwaitingInstructionDeclarationFactory()
snapshot_more_urgent = SnapshotFactory(
declaration=declaration_more_urgent, status=declaration_more_urgent.status
)
snapshot_more_urgent.creation_date = today - timedelta(days=10)
snapshot_more_urgent.save()

# Le snapshot du refus de visa ne doit pas affecter la date limite de réponse
snapshot_visa_refusal = SnapshotFactory(
declaration=declaration_more_urgent,
status=declaration_more_urgent.status,
action=Snapshot.SnapshotActions.REFUSE_VISA,
)
snapshot_visa_refusal.creation_date = today - timedelta(days=1)
snapshot_visa_refusal.save()

# Triage par date limite d'instruction
sort_url = f"{reverse('api:list_all_declarations')}?ordering=responseLimitDate"
response = self.client.get(sort_url, format="json")
results = response.json()["results"]
self.assertEqual(len(results), 2)

self.assertEqual(results[0]["id"], declaration_more_urgent.id)
self.assertEqual(results[1]["id"], declaration_less_urgent.id)

# Triage par date limite d'instruction inversé
reverse_sort_url = f"{reverse('api:list_all_declarations')}?ordering=-responseLimitDate"
response = self.client.get(reverse_sort_url, format="json")
results = response.json()["results"]
self.assertEqual(len(results), 2)

self.assertEqual(results[0]["id"], declaration_less_urgent.id)
self.assertEqual(results[1]["id"], declaration_more_urgent.id)

@authenticate
def test_update_article(self):
"""
Expand Down Expand Up @@ -1682,7 +1732,7 @@ def test_get_single_declared_ingredient(self):
ingredient = DeclaredIngredientFactory(declaration=declaration)

response = self.client.get(
reverse("api:declared_element", kwargs={"pk": ingredient.id, "type": "ingredient"}), format="json"
reverse("api:declared_element", kwargs={"pk": ingredient.id, "type": "other-ingredient"}), format="json"
)
body = response.json()
self.assertEqual(body["id"], ingredient.id)
Expand All @@ -1700,7 +1750,7 @@ def test_cannot_get_declared_element_unknown_type(self):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.json()["globalError"],
"Unknown type: 'unknown' not in ['plant', 'microorganism', 'substance', 'ingredient']",
"Unknown type: 'unknown' not in ['plant', 'microorganism', 'substance', 'other-ingredient']",
)

def test_get_declared_element_not_allowed_not_authenticated(self):
Expand All @@ -1718,7 +1768,7 @@ def test_get_declared_element_not_allowed_not_authenticated(self):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

response = self.client.get(
reverse("api:declared_element", kwargs={"pk": 1, "type": "ingredient"}), format="json"
reverse("api:declared_element", kwargs={"pk": 1, "type": "other-ingredient"}), format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

Expand All @@ -1738,7 +1788,7 @@ def test_get_declared_element_not_allowed_not_instructor(self):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

response = self.client.get(
reverse("api:declared_element", kwargs={"pk": 1, "type": "ingredient"}), format="json"
reverse("api:declared_element", kwargs={"pk": 1, "type": "other-ingredient"}), format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

Expand Down Expand Up @@ -1779,7 +1829,7 @@ def test_request_info_declared_element_not_allowed_not_instructor(self):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

response = self.client.get(
reverse("api:declared_element_request_info", kwargs={"pk": 1, "type": "ingredient"}), format="json"
reverse("api:declared_element_request_info", kwargs={"pk": 1, "type": "other-ingredient"}), format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

Expand Down Expand Up @@ -1819,7 +1869,7 @@ def test_reject_declared_element_not_allowed_not_instructor(self):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

response = self.client.get(
reverse("api:declared_element_reject", kwargs={"pk": 1, "type": "ingredient"}), format="json"
reverse("api:declared_element_reject", kwargs={"pk": 1, "type": "other-ingredient"}), format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

Expand Down
4 changes: 4 additions & 0 deletions api/views/declaration/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ def filter_queryset(self, request, queryset, view):
"""
Cette fonction vise à réproduire la property "response_limit_date" du modèle Declaration
mais dans la couche DB (avec des querysets) afin de pouvoir filtrer dessus.
⚠️ Attention : Tout changement effectué dans cette fonction doit aussi être reflété dans
data/models/declaration.py > response_limit_date
"""
order_by_response_limit, desc = self.order_by_response_limit(request)

Expand All @@ -302,6 +305,7 @@ def filter_queryset(self, request, queryset, view):
Snapshot.objects.filter(
declaration=OuterRef("pk"), status=Declaration.DeclarationStatus.AWAITING_INSTRUCTION
)
.exclude(action=Snapshot.SnapshotActions.REFUSE_VISA)
.order_by("-creation_date" if order_by_response_limit else "creation_date")
.values("creation_date")[:1]
)
Expand Down
2 changes: 1 addition & 1 deletion api/views/declaration/declared_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class ElementMappingMixin:
"synonym_model": SubstanceSynonym,
"serializer": DeclaredSubstanceSerializer,
},
"ingredient": {
"other-ingredient": {
"model": DeclaredIngredient,
"element_model": Ingredient,
"synonym_model": IngredientSynonym,
Expand Down
12 changes: 11 additions & 1 deletion data/behaviours/auto_validable.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,15 @@ class Meta:
abstract = True

def save(self, *args, **kwargs):
self.full_clean()
"""
* fields_with_no_validation est un set
"""
fields_with_no_validation = kwargs.pop("fields_with_no_validation", ())
if fields_with_no_validation:
self.clean_fields(exclude=fields_with_no_validation)
self.clean()
self.validate_unique()
self.validate_constraints()
else:
self.full_clean()
super().save(*args, **kwargs)
Loading

0 comments on commit da5a866

Please sign in to comment.