Skip to content

Commit

Permalink
Avenants tableau logements facultatif (#1421)
Browse files Browse the repository at this point in the history
* Avenants tableau logements facultatif

* Ignore tableau logement for residence and foyer

* emove limitation to avenants
  • Loading branch information
syldb authored May 27, 2024
1 parent c8c4ca2 commit 9194461
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 64 deletions.
28 changes: 23 additions & 5 deletions conventions/forms/convention_form_logements.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,31 @@ class BaseLogementFormSet(BaseFormSet):
programme_id: int = None
lot_id: int = None
nb_logements: int = None
optional_errors: list = []
ignore_optional_errors = False

def is_valid(self):
return super().is_valid() and len(self.optional_errors) == 0

def clean(self):
self.manage_non_empty_validation()
self.manage_designation_validation()
self.manage_same_loyer_par_metre_carre()
self.manage_edd_consistency()
self.manage_nb_logement_consistency()
self.manage_coefficient_propre()

if self.ignore_optional_errors:
return
self.optional_errors = []
self.manage_non_empty_validation()
self.manage_nb_logement_consistency()

def manage_non_empty_validation(self):
"""
Validation: la liste des logements ne peut pas être vide
"""
if len(self.forms) == 0:
error = ValidationError("La liste des logements ne peut pas être vide")
self._non_form_errors.append(error)
self.optional_errors.append(error)

def manage_designation_validation(self):
"""
Expand Down Expand Up @@ -359,7 +368,7 @@ def manage_nb_logement_consistency(self):
f"Le nombre de logement à conventionner ({self.nb_logements}) "
+ f"ne correspond pas au nombre de logements déclaré ({self.total_form_count()})"
)
self._non_form_errors.append(error)
self.optional_errors.append(error)

def manage_coefficient_propre(self):
"""
Expand Down Expand Up @@ -450,9 +459,18 @@ class BaseFoyerResidenceLogementFormSet(BaseFormSet):
# les champs suivants sont utilisés pour la validation des données
# ils sont initialisés avant la validation
nb_logements: int = None
optional_errors: list = []
ignore_optional_errors = False

def is_valid(self):
return super().is_valid() and len(self.optional_errors) == 0

def clean(self):
self.loan_should_be_consistent()

if self.ignore_optional_errors:
return
self.optional_errors = []
self.manage_nb_logement_consistency()

def manage_nb_logement_consistency(self):
Expand All @@ -465,7 +483,7 @@ def manage_nb_logement_consistency(self):
f"Le nombre de logement à conventionner ({self.nb_logements}) "
+ f"ne correspond pas au nombre de logements déclaré ({self.total_form_count()})"
)
self._non_form_errors.append(error)
self.optional_errors.append(error)

def loan_should_be_consistent(self):
"""
Expand Down
6 changes: 6 additions & 0 deletions conventions/services/logements.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ def _logements_atomic_update(self):
self.formset.programme_id = self.convention.programme_id
self.formset.lot_id = self.convention.lot_id
self.formset.nb_logements = int(self.request.POST.get("nb_logements") or 0)
self.formset.ignore_optional_errors = self.request.POST.get(
"ignore_optional_errors", False
)
formset_is_valid = self.formset.is_valid()

if form_is_valid and formset_is_valid:
Expand Down Expand Up @@ -341,6 +344,9 @@ def _foyer_residence_logements_atomic_update(self):
self.formset = FoyerResidenceLogementFormSet(initformset)
self.formset.lot_id = self.convention.lot_id
self.formset.nb_logements = int(self.request.POST.get("nb_logements") or 0)
self.formset.ignore_optional_errors = self.request.POST.get(
"ignore_optional_errors", False
)
formset_is_valid = self.formset.is_valid()

self.form = LotFoyerResidenceLgtsDetailsForm(
Expand Down
74 changes: 58 additions & 16 deletions conventions/tests/services/test_logements_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from decimal import Decimal

from django.forms import model_to_dict
from django.forms import ValidationError, model_to_dict
from django.http import HttpRequest
from django.test import TestCase

Expand Down Expand Up @@ -47,6 +47,11 @@ def setUp(self):
convention=convention, request=request
)

avenant = convention.clone(request.user, convention_origin=convention)
self.service_avenant = ConventionLogementsService(
convention=avenant, request=request
)

def test_get(self):
self.service.get()
self.assertEqual(self.service.return_status, utils.ReturnStatus.ERROR)
Expand Down Expand Up @@ -129,13 +134,26 @@ def test_save_fails_on_nb_logements(self):
"nb_logements": "3",
}
self.service.save()
self.assertEqual(
self.service.formset.non_form_errors(),
[
"Le nombre de logement à conventionner (3) ne correspond pas au nombre"
+ " de logements déclaré (2)"
],
)
assert self.service.formset.optional_errors == [
ValidationError(
"Le nombre de logement à conventionner (3) ne correspond pas au nombre de logements déclaré (2)"
)
]
assert self.service.formset.non_form_errors() == []

def test_save_fails_on_nb_logements_avenants(self):
self.service_avenant.request.POST = {
"uuid": str(self.service_avenant.convention.lot.uuid),
**logement_success_payload,
"nb_logements": "3",
}
self.service_avenant.save()
assert self.service_avenant.formset.optional_errors == [
ValidationError(
"Le nombre de logement à conventionner (3) ne correspond pas au nombre de logements déclaré (2)"
)
]
assert self.service_avenant.formset.non_form_errors() == []


class ConventionFoyerResidenceLogementsServiceTests(TestCase):
Expand Down Expand Up @@ -165,6 +183,11 @@ def setUp(self):
convention=convention, request=request
)

avenant = convention.clone(request.user, convention_origin=convention)
self.service_avenant = ConventionFoyerResidenceLogementsService(
convention=avenant, request=request
)

def test_get(self):
self.service.get()
self.assertEqual(self.service.return_status, utils.ReturnStatus.ERROR)
Expand Down Expand Up @@ -243,14 +266,12 @@ def test_save_fails_on_nb_logements(self):
}
self.service.save()
self.assertEqual(self.service.return_status, utils.ReturnStatus.ERROR)
self.assertTrue(self.service.formset.non_form_errors())
self.assertEqual(
self.service.formset.non_form_errors(),
[
"Le nombre de logement à conventionner (2) "
+ "ne correspond pas au nombre de logements déclaré (3)"
],
)
assert self.service.formset.optional_errors == [
ValidationError(
"Le nombre de logement à conventionner (2) ne correspond pas au nombre de logements déclaré (3)"
)
]
assert self.service.formset.non_form_errors() == []

def test_save_fails_on_surface_habitable_totale(self):
self.service.request.POST = {
Expand All @@ -261,3 +282,24 @@ def test_save_fails_on_surface_habitable_totale(self):
}
self.service.save()
self.assertTrue(self.service.form.has_error("surface_habitable_totale"))

def test_save_fails_on_nb_logements_avenant(self):

self.service_avenant.request.POST = {
**foyer_residence_logements_success_payload,
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-2-uuid": "",
"form-2-designation": "b2",
"form-2-typologie": "T2",
"form-2-surface_habitable": "16.00",
"form-2-loyer": "160.00",
}
self.service_avenant.save()
self.assertEqual(self.service_avenant.return_status, utils.ReturnStatus.ERROR)
assert self.service_avenant.formset.optional_errors == [
ValidationError(
"Le nombre de logement à conventionner (2) ne correspond pas au nombre de logements déclaré (3)"
)
]
assert self.service_avenant.formset.non_form_errors() == []
42 changes: 42 additions & 0 deletions templates/conventions/common/form_optional_errors_modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% if formset.optional_errors and formset.total_error_count == 0 %}
<input data-fr-opened="true" aria-controls="fr-modal-2" type="hidden">
<dialog aria-labelledby="fr-modal-2-title" id="fr-modal-2" data-fr-opened="true" class="fr-modal" role="dialog" >
<div class="fr-container fr-container--fluid fr-container-md">
<div class="fr-grid-row fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-modal__body">
<div class="fr-modal__header">
<button class="fr-link--close fr-link" type="button" aria-controls="fr-modal-2">Fermer</button>
</div>
<div class="fr-modal__content">
<h1 id="fr-modal-2-title" class="fr-modal__title">
<span class="fr-icon-arrow-right-line fr-icon--lg"></span>
Attention
</h1>
{% for error in formset.optional_errors %}
<p id="text-input-error-desc-error" class="fr-error-text modal__error-text">
{{ error.message }}
</p>
{% endfor %}

</div>
<div class="fr-modal__footer">
<ul class="fr-btns-group fr-btns-group--right fr-btns-group--inline fr-btns-group--inline-lg fr-btns-group--icon-left">
<li>
<button class="fr-btn fr-btn--secondary" type="button" aria-controls="fr-modal-2">
Corriger
</button>
</li>
<li>
<button class="fr-btn fr-icon-checkbox-line" name='ignore_optional_errors' value=1>
Valider quand même
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</dialog>
{% endif %}
44 changes: 1 addition & 43 deletions templates/conventions/edd.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,49 +60,7 @@ <h4 class="fr-mb-1w">EDD Simplifié</h4>
</p>
{% endfor %}

{% if formset.optional_errors and formset.total_error_count == 0 %}

<input data-fr-opened="true" aria-controls="fr-modal-2" type="hidden">
<dialog aria-labelledby="fr-modal-2-title" id="fr-modal-2" data-fr-opened="true" class="fr-modal" role="dialog" >
<div class="fr-container fr-container--fluid fr-container-md">
<div class="fr-grid-row fr-grid-row--center">
<div class="fr-col-12 fr-col-md-8 fr-col-lg-6">
<div class="fr-modal__body">
<div class="fr-modal__header">
<button class="fr-link--close fr-link" type="button" aria-controls="fr-modal-2">Fermer</button>
</div>
<div class="fr-modal__content">
<h1 id="fr-modal-2-title" class="fr-modal__title">
<span class="fr-icon-arrow-right-line fr-icon--lg"></span>
Attention
</h1>
{% for error in formset.optional_errors %}
<p id="text-input-error-desc-error" class="fr-error-text modal__error-text">
{{ error.message }}
</p>
{% endfor %}

</div>
<div class="fr-modal__footer">
<ul class="fr-btns-group fr-btns-group--right fr-btns-group--inline fr-btns-group--inline-lg fr-btns-group--icon-left">
<li>
<button class="fr-btn fr-btn--secondary" type="button" aria-controls="fr-modal-2">
Corriger
</button>
</li>
<li>
<button class="fr-btn fr-icon-checkbox-line" name='ignore_optional_errors' value=1>
Valider quand même
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</dialog>
{% endif %}
{% include "conventions/common/form_optional_errors_modal.html" %}

{% for error in formset.optional_errors %}
<p id="text-input-error-desc-error" class="fr-error-text">
Expand Down
1 change: 1 addition & 0 deletions templates/conventions/foyer_residence_logements.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
{% csrf_token %}
{% include "conventions/common/form_foyer_residence_logements.html"%}
{% include "conventions/common/form_footer_button.html" %}
{% include "conventions/common/form_optional_errors_modal.html" %}
</form>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions templates/conventions/logements.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
{% csrf_token %}
{% include "conventions/common/form_logements.html"%}
{% include "conventions/common/form_footer_button.html" %}
{% include "conventions/common/form_optional_errors_modal.html" %}
</form>
</div>
</div>
Expand Down

0 comments on commit 9194461

Please sign in to comment.