diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2022-11-15 16:29:30 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2022-12-12 12:23:19 +0100 |
commit | cda77c979e232386ef24ea7a04600f16f3c32c98 (patch) | |
tree | 7d53e762723338913594ccdb42c6fa08c4bfb5ef /archaeological_files/forms.py | |
parent | 4746cd2938df3cf87ae338d22eb4f67f35bac960 (diff) | |
download | Ishtar-cda77c979e232386ef24ea7a04600f16f3c32c98.tar.bz2 Ishtar-cda77c979e232386ef24ea7a04600f16f3c32c98.zip |
File module refactoring - more tests for files
Diffstat (limited to 'archaeological_files/forms.py')
-rw-r--r-- | archaeological_files/forms.py | 415 |
1 files changed, 346 insertions, 69 deletions
diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py index a75e5bf34..9466d7d52 100644 --- a/archaeological_files/forms.py +++ b/archaeological_files/forms.py @@ -34,12 +34,19 @@ from ishtar_common.utils import ugettext_lazy as _ from ishtar_common.models import ( Person, Organization, + Town, valid_id, valid_ids, person_type_pks_lazy, person_type_pk_lazy, organization_type_pks_lazy, + organization_type_pk_lazy, + get_sra_agent_label, get_sra_agent_head_scientist_label, + get_orga_general_contractor_label, + get_general_contractor_label, + get_orga_planning_service_label, + get_responsible_planning_service_label, ) from ishtar_common.models_common import Department from archaeological_operations.models import ActType, AdministrativeAct, OperationType @@ -65,8 +72,6 @@ from archaeological_operations.forms import ( AdministrativeActForm, AdministrativeActOpeFormSelection, AdministrativeActModifForm, - ParcelForm, - ParcelFormSet, ) from ishtar_common import widgets from bootstrap_datepicker.widgets import DatePicker @@ -194,25 +199,12 @@ class FileFormMultiSelection(LockForm, MultiSearchForm): ) -class FileFormGeneral(ManageOldType): +class FileFormGeneral(CustomForm, ManageOldType): form_label = _("General") - associated_models = { - "in_charge": Person, - "related_file": models.File, - "file_type": models.FileType, - } - in_charge = forms.IntegerField( - label=_("Person in charge"), - widget=widgets.JQueryAutoComplete( - reverse_lazy( - "autocomplete-person", args=[person_type_pks_lazy(["sra_agent"])] - ), - limit={"person_types": [person_type_pk_lazy("sra_agent")]}, - associated_model=Person, - new=True, - ), - validators=[valid_id(Person)], - ) + form_admin_name = _("Archaeological file - 010 - General") + form_slug = "file-010-general" + associated_models = {"file_type": models.FileType} + file_type = forms.ChoiceField(label=_("File type"), choices=[]) year = forms.IntegerField( label=_("Year"), initial=lambda: datetime.datetime.now().year, @@ -221,56 +213,22 @@ class FileFormGeneral(ManageOldType): validators.MaxValueValidator(2100), ], ) - numeric_reference = forms.IntegerField( - label=_("Numeric reference"), widget=forms.HiddenInput, required=False - ) - internal_reference = forms.CharField( - label=_("Other reference"), max_length=60, required=False - ) - name = forms.CharField(label=_("Name"), required=False, max_length=100) creation_date = forms.DateField( label=_("Creation date"), initial=get_now, widget=DatePicker ) - file_type = forms.ChoiceField(label=_("File type"), choices=[]) - related_file = forms.IntegerField( - label=_("Related file"), - required=False, - widget=widgets.JQueryAutoComplete( - reverse_lazy("autocomplete-file"), associated_model=models.File - ), - validators=[valid_id(models.File)], - ) - comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) - total_surface = forms.FloatField( - required=False, - widget=widgets.AreaWidget, - label=_("Total surface (m2)"), - validators=[ - validators.MinValueValidator(0), - validators.MaxValueValidator(999999999), - ], - ) - address = forms.CharField(label=_("Main address"), widget=forms.Textarea) - address_complement = forms.CharField( - label=_("Main address - complement"), required=False + reception_date = forms.DateField( + label=_("Reception date"), initial=get_now, widget=DatePicker ) - def __init__(self, *args, **kwargs): - super(FileFormGeneral, self).__init__(*args, **kwargs) - if "file_type" in self.fields: - self.fields["file_type"].choices = models.FileType.get_types( - initial=self.init_data.get("file_type") - ) - self.fields["file_type"].help_text = models.FileType.get_help() - q = ( - models.File.objects.filter(internal_reference__isnull=False) - .exclude(internal_reference="") - .order_by("-pk") - ) - if q.count() and "internal_reference" in self.fields: - lbl = self.fields["internal_reference"].label - lbl += _("<br/>(last recorded: %s)") % (q.all()[0].internal_reference) - self.fields["internal_reference"].label = mark_safe(lbl) + TYPES = [ + FieldType("file_type", models.FileType), + ] + + def clean_reception_date(self): + value = self.cleaned_data.get("reception_date", None) + if value and value > datetime.date.today(): + raise forms.ValidationError(_("Reception date cannot be after today.")) + return value class FileFormGeneralRO(FileFormGeneral): @@ -295,10 +253,239 @@ class FileFormGeneralRO(FileFormGeneral): return cleaned_data -ParcelFormset = formset_factory(ParcelForm, can_delete=True, formset=ParcelFormSet) -ParcelFormset.form_label = _("Parcels") -ParcelFormset.form_admin_name = _("Archaeological file - 020 - Parcel") -ParcelFormset.form_slug = "file-020-parcels" +class FileFormPreventiveType(CustomForm, ManageOldType, forms.Form): + form_label = "Saisine" + form_admin_name = _("Archaeological file - 013 - Preventive - Saisine") + form_slug = "file-013-preventivesaisine" + associated_models = { + "saisine_type": models.SaisineType, + "permit_type": models.PermitType, + } + permit_type = forms.ChoiceField(label=_("Permit type"), required=False, choices=[]) + saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[]) + TYPES = [ + FieldType("saisine_type", models.SaisineType), + ] + + def __init__(self, *args, **kwargs): + super(FileFormPreventiveType, self).__init__(*args, **kwargs) + self.fields["permit_type"].choices = models.PermitType.get_types( + default="NP", initial=self.init_data.get("permit_type") + ) + self.fields["permit_type"].help_text = models.PermitType.get_help() + + +class FileFormPlanning(CustomForm, ManageOldType): + form_label = _("Planning") + form_admin_name = _("Archaeological file - 017 - Preventive - Planning") + form_slug = "file-017-preventiveplanning" + base_models = ["town", "department"] + associated_models = {"town": Town, "department": Department} + HEADERS = {} + HEADERS["town"] = FormHeader(_("Localisation")) + name = forms.CharField(label=_("Planning name"), required=False, max_length=100) + town = widgets.Select2MultipleField( + model=Town, label=_("Towns"), required=False, remote=True + ) + department = widgets.Select2MultipleField( + model=Department, + label=_("Departments"), + required=False, + help_text=_("Only relevant when no town is provided."), + ) + locality = forms.CharField(label=_("Locality"), max_length=100, required=False) + address = forms.CharField( + label=_("Address (number/street)"), + widget=forms.Textarea(attrs={"placeholder": _("Number/street")}), + required=False, + ) + postal_code = forms.CharField(label=_("Postal code"), max_length=10, required=False) + HEADERS["total_surface"] = FormHeader(_("Surfaces")) + total_surface = forms.FloatField( + required=False, + widget=widgets.AreaWidget, + label=_("Total surface (m2)"), + validators=[ + validators.MinValueValidator(0), + validators.MaxValueValidator(999999999), + ], + ) + total_developed_surface = forms.FloatField( + widget=widgets.AreaWidget, + label=_("Total developed surface (m2)"), + required=False, + validators=[ + validators.MinValueValidator(0), + validators.MaxValueValidator(999999999), + ], + ) + + +class FileFormResearchAddress(CustomForm, forms.Form): + form_label = _("Address") + form_admin_name = _("Archaeological file - 015 - Research - Address") + form_slug = "file-015-researchplanning" + base_models = ["town", "department"] + associated_models = {"town": Town, "department": Department} + name = forms.CharField(label=_("Project name"), required=False, max_length=100) + town = widgets.Select2MultipleField( + model=Town, label=_("Towns"), required=False, remote=True + ) + department = widgets.Select2MultipleField( + model=Department, label=_("Departments"), required=False + ) + locality = forms.CharField(label=_("Locality"), max_length=100, required=False) + address = forms.CharField( + label=_("Address (number/street)"), + widget=forms.Textarea(attrs={"placeholder": _("Number/street")}), + required=False, + ) + postal_code = forms.CharField(label=_("Postal code"), max_length=10, required=False) + + +class FileFormGeneralContractor(CustomForm, ManageOldType): + form_label = _("General contractor") + form_admin_name = _("Archaeological file - 030 - General contractor") + form_slug = "file-030-generalcontractor" + + associated_models = { + "general_contractor": models.Person, + "corporation_general_contractor": models.Organization, + } + + corporation_general_contractor = forms.IntegerField( + label=_("General contractor"), + widget=widgets.JQueryAutoComplete( + reverse_lazy( + "autocomplete-organization", + args=[ + organization_type_pks_lazy(["general_contractor"]), + ], + ), + limit={ + "organization_type": [organization_type_pk_lazy("general_contractor")] + }, + tips=lazy(get_orga_general_contractor_label), + associated_model=models.Organization, + new=True, + detail=True, + modify=True, + ), + validators=[valid_id(models.Organization)], + ) + general_contractor = forms.IntegerField( + label=_("In charge"), + required=False, + widget=widgets.JQueryAutoComplete( + reverse_lazy( + "autocomplete-person", + args=[person_type_pks_lazy(["general_contractor"])], + ), + associated_model=Person, + limit={"person_types": [person_type_pk_lazy("general_contractor")]}, + tips=lazy(get_general_contractor_label), + detail=True, + modify=True, + new=True, + ), + validators=[valid_id(Person)], + ) + + def clean(self): + general_contractor = self.cleaned_data.get("general_contractor", None) + corporation_general_contractor = self.cleaned_data.get( + "corporation_general_contractor", None + ) + if general_contractor and corporation_general_contractor: + try: + person = models.Person.objects.get(pk=general_contractor) + except models.Person.DoesNotExist: + raise forms.ValidationError(_("Non existing person.")) + if ( + not person.attached_to + or person.attached_to.pk != corporation_general_contractor + ): + raise forms.ValidationError( + _( + "The organization of the person in charge differs from the " + "general contractor." + ) + ) + return self.cleaned_data + + +class FileFormPlanningService(CustomForm, IshtarForm): + form_label = _("Planning service") + form_admin_name = _("Archaeological file - 040 - Planning service") + form_slug = "file-040-planningservice" + associated_models = { + "responsible_town_planning_service": models.Person, + "planning_service": models.Organization, + } + + planning_service = forms.IntegerField( + label=_("Planning service"), + required=False, + widget=widgets.JQueryAutoComplete( + reverse_lazy( + "autocomplete-organization", + args=[organization_type_pks_lazy(["planning_service"])], + ), + associated_model=models.Organization, + limit={ + "organization_type": [organization_type_pk_lazy(["planning_service"])], + }, + tips=lazy(get_orga_planning_service_label), + new=True, + detail=True, + modify=True, + ), + validators=[valid_id(models.Organization)], + ) + responsible_town_planning_service = forms.IntegerField( + label=_("In charge"), + required=False, + widget=widgets.JQueryAutoComplete( + reverse_lazy( + "autocomplete-person", + args=[person_type_pks_lazy(["responsible_planning_service"])], + ), + associated_model=Person, + limit={ + "person_types": [person_type_pk_lazy("responsible_planning_service")] + }, + dynamic_limit=["planning_service"], + tips=lazy(get_responsible_planning_service_label), + detail=True, + modify=True, + new=True, + ), + validators=[valid_id(Person)], + ) + permit_reference = forms.CharField( + label=_("File reference"), required=False, max_length=200 + ) + planning_service_date = forms.DateField( + label=_("Date of planning service file"), widget=DatePicker, required=False + ) + + def clean(self): + responsible = self.cleaned_data["responsible_town_planning_service"] + orga = self.cleaned_data["planning_service"] + if responsible: + try: + person = models.Person.objects.get(pk=responsible) + except models.Person.DoesNotExist: + raise forms.ValidationError(_("Non existing person.")) + if not person.attached_to or person.attached_to.pk != orga: + raise forms.ValidationError( + _( + "The organization of the person in charge differs from the " + "planning service." + ) + ) + return self.cleaned_data + class FileFormPreventive(ManageOldType, forms.Form): @@ -447,6 +634,96 @@ class FileFormResearch(CustomForm, ManageOldType, forms.Form): self.fields["requested_operation_type"].help_text = OperationType.get_help() +class FileFormInstruction(CustomForm, IshtarForm): + form_label = _("Instruction") + form_admin_name = _("Archaeological file - 050 - Instruction") + form_slug = "file-050-instruction" + associated_models = {"in_charge": models.Person, "related_file": models.File} + in_charge = forms.IntegerField( + label=_("File managed by"), + widget=widgets.JQueryAutoComplete( + reverse_lazy( + "autocomplete-person", args=[person_type_pks_lazy(["sra_agent"])] + ), + limit={"person_types": [person_type_pk_lazy("sra_agent")]}, + tips=lazy(get_sra_agent_label), + associated_model=Person, + new=True, + ), + validators=[valid_id(Person)], + ) + related_file = forms.IntegerField( + label=_("Related file"), + required=False, + widget=widgets.JQueryAutoComplete( + reverse_lazy("autocomplete-file"), associated_model=models.File + ), + validators=[valid_id(models.File)], + ) + comment = forms.CharField(label=_("Comment"), widget=forms.Textarea, required=False) + instruction_deadline = forms.DateField(widget=DatePicker, required=False) + year = forms.IntegerField( + label=_("Year"), + validators=[ + validators.MinValueValidator(1000), + validators.MaxValueValidator(2100), + ], + ) + numeric_reference = forms.IntegerField(label=_("Numeric reference"), required=False) + numeric_reference_is_readonly = True + end_date = forms.DateField(widget=DatePicker, required=False) + + def __init__(self, *args, **kwargs): + c_year = datetime.date.today().year + if "year" in kwargs: + c_year = kwargs.pop("year") + saisine_type = None + if "saisine_type" in kwargs: + saisine_type = kwargs.pop("saisine_type") + reception_date = None + if "reception_date" in kwargs: + reception_date = kwargs.pop("reception_date") + if "data" in kwargs and kwargs["data"]: + kwargs["data"][kwargs.get("prefix", "") + "-year"] = c_year + + super(FileFormInstruction, self).__init__(*args, **kwargs) + self.fields["year"].initial = c_year + + self.fields["year"].widget.attrs.update({"readonly": "readonly"}) + c_num = 0 + q = models.File.objects.filter( + numeric_reference__isnull=False, year=c_year + ).order_by("-numeric_reference") + if q.count(): + c_num = q.all()[0].numeric_reference + lbl = self.fields["numeric_reference"].label + self.fields["numeric_reference"].label = mark_safe(lbl) + self.fields["numeric_reference"].initial = c_num + 1 + if self.numeric_reference_is_readonly: + self.fields["numeric_reference"].widget.attrs["readonly"] = True + if reception_date and saisine_type: + if type(reception_date) == str: + try: + reception_date = datetime.datetime.strptime( + reception_date, "%d/%m/%Y" + ) + self.fields["instruction_deadline"].initial = ( + reception_date + + datetime.timedelta(days=saisine_type.delay or 0) + ).strftime("%Y-%m-%d") + except ValueError: + pass + + def clean_numeric_reference(self): + if self.numeric_reference_is_readonly: + return self.fields["numeric_reference"].initial + return self.cleaned_data["numeric_reference"] + + +class FileFormInstructionEdit(FileFormInstruction): + numeric_reference_is_readonly = False + + class FinalFileClosingForm(FinalForm): confirm_msg = " " confirm_end_msg = _("Would you like to close this archaeological file?") |