#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (C) 2010-2016 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # See the file COPYING for details. """ Files forms definitions """ import datetime from bootstrap_datepicker.widgets import DateField from django import forms from django.conf import settings from django.core import validators from django.forms.formsets import formset_factory from django.utils.functional import lazy from django.utils.safestring import mark_safe 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 from . import models from ishtar_common.forms import ( FinalForm, get_now, reverse_lazy, TableSelect, ManageOldType, CustomForm, FieldType, IshtarForm, MultiSearchForm, LockForm, CustomFormSearch, DocumentItemSelect, FormHeader, BSForm, ) from ishtar_common.forms_common import get_town_field from archaeological_operations.forms import ( AdministrativeActForm, AdministrativeActOpeFormSelection, AdministrativeActModifForm, ) from ishtar_common import widgets from bootstrap_datepicker.widgets import DatePicker class FileSelect(DocumentItemSelect): _model = models.File form_admin_name = _("File - 001 - Search") form_slug = "file-001-search" search_vector = forms.CharField( label=_("Full text search"), widget=widgets.SearchWidget("archaeological-files", "file"), ) year = forms.IntegerField(label=_("Year")) numeric_reference = forms.IntegerField(label=_("Numeric reference")) internal_reference = forms.CharField(max_length=200, label=_("Other reference")) towns = get_town_field() parcel = forms.CharField(label=_("Parcel")) if settings.ISHTAR_DPTS: towns__numero_insee__startswith = forms.ChoiceField( label=_("Department"), choices=[] ) name = forms.CharField(label=_("File name"), max_length=200) file_type = forms.ChoiceField(label=_("File type"), choices=[]) end_date = forms.NullBooleanField(label=_("Is active?")) development_type = forms.ChoiceField(label=_("Development type"), choices=[]) saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[]) monitoring_justification = forms.ChoiceField(label=_("Monitoring justification"), choices=[]) permit_type = forms.ChoiceField(label=_("Permit type"), choices=[]) permit_reference = forms.CharField(max_length=200, label=_("Permit/order reference")) comment = forms.CharField(label=_("Comment"), max_length=500) in_charge = forms.IntegerField( label=_("In charge"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person", args=[person_type_pk_lazy("sra_agent")] ), associated_model=Person, ), validators=[valid_id(Person)], ) general_contractor = forms.IntegerField( label=_("General contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person", args=[person_type_pk_lazy("general_contractor")] ), associated_model=Person, ), validators=[valid_id(Person)], ) general_contractor__attached_to = forms.IntegerField( label=_("Organization of general contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-organization", args=[organization_type_pks_lazy(["general_contractor"])], ), associated_model=Organization, ), validators=[valid_id(Organization)], ) history_creator = forms.IntegerField( label=_("Created by"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person", args=["0", "user"]), associated_model=Person, ), validators=[valid_id(Person)], ) history_modifier = forms.IntegerField( label=_("Modified by"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person", args=["0", "user"]), associated_model=Person, ), validators=[valid_id(Person)], ) TYPES = [ FieldType("saisine_type", models.SaisineType), FieldType("development_type", models.DevelopmentType), FieldType("monitoring_justification", models.MonitoringJustificationType), FieldType("permit_type", models.PermitType), FieldType("file_type", models.FileType), ] def __init__(self, *args, **kwargs): super(FileSelect, self).__init__(*args, **kwargs) k = "towns__numero_insee__startswith" if settings.ISHTAR_DPTS and k in self.fields: self.fields[k].choices = [("", "--")] + list(settings.ISHTAR_DPTS) class FileFormSelection(LockForm, CustomFormSearch): SEARCH_AND_SELECT = True form_label = _("Archaeological file search") associated_models = {"pk": models.File} currents = {"pk": models.File} pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-file"), FileSelect, models.File, source_full=reverse_lazy("get-file-full"), ), validators=[valid_id(models.File)], ) class FileFormMultiSelection(LockForm, MultiSearchForm): form_label = _("Archaeological file search") associated_models = {"pks": models.File} pk = forms.CharField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-file"), FileSelect, models.File, multiple_select=True, source_full=reverse_lazy("get-file-full"), ), validators=[valid_ids(models.File)], ) class FileFormGeneral(CustomForm, ManageOldType): form_label = _("General") 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, validators=[ validators.MinValueValidator(1000), validators.MaxValueValidator(2100), ], ) creation_date = DateField(label=_("Creation date"), initial=get_now, required=False) reception_date = DateField(label=_("Reception date"), initial=get_now, required=False) 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): year = forms.IntegerField( label=_("Year"), widget=forms.TextInput(attrs={"readonly": True}) ) numeric_reference = forms.IntegerField( label=_("Numeric reference"), widget=forms.TextInput() ) id = forms.IntegerField(label=" ", widget=forms.HiddenInput, required=False) def clean(self): cleaned_data = self.cleaned_data year = cleaned_data.get("year") pk = cleaned_data.get("id") numeric_reference = cleaned_data.get("numeric_reference") q = models.File.objects.filter( year=year, numeric_reference=numeric_reference ).exclude(pk=pk) if numeric_reference and q.count(): raise forms.ValidationError(_("Another file with this numeric id exists.")) return cleaned_data """ 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"), required=False, 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, "development_type": models.DevelopmentType} HEADERS = {} HEADERS["town"] = FormHeader(_("Geographic localisation")) name = forms.CharField(label=_("Planning name"), required=False, max_length=1000) development_type = forms.ChoiceField(label=_("Development type"), choices=[], required=False) 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 (m²)"), validators=[ validators.MinValueValidator(0), validators.MaxValueValidator(999999999), ], ) total_developed_surface = forms.FloatField( widget=widgets.AreaWidget, label=_("Total developed surface (m²)"), required=False, validators=[ validators.MinValueValidator(0), validators.MaxValueValidator(999999999), ], ) TYPES = [ FieldType("development_type", models.DevelopmentType), ] 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"), associated_model=models.Organization, new=True, detail=True, modify=True, ), validators=[valid_id(models.Organization)], required=False ) general_contractor = forms.IntegerField( label=_("In charge"), required=False, widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person"), associated_model=Person, 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, "monitoring_justification": models.MonitoringJustificationType, } planning_service = forms.IntegerField( label=_("Planning service"), required=False, widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-organization"), associated_model=models.Organization, 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"), associated_model=Person, detail=True, modify=True, new=True, ), validators=[valid_id(Person)], ) monitoring_justification = forms.ChoiceField(label=_("Monitoring justification"), choices=[], required=False) permit_reference = forms.CharField( label=_("Permit/order reference"), required=False, max_length=200 ) planning_service_date = DateField(label=_("Date of planning service file"), required=False) TYPES = [ FieldType("monitoring_justification", models.MonitoringJustificationType), ] 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): form_label = _("Preventive informations") associated_models = { "general_contractor": Person, "saisine_type": models.SaisineType, "permit_type": models.PermitType, "responsible_town_planning_service": Person, } general_contractor = forms.IntegerField( label=_("General contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person"), associated_model=Person, new=True, ), validators=[valid_id(Person)], ) responsible_town_planning_service = forms.IntegerField( required=False, label=_("Responsible for planning service"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person", args=[person_type_pks_lazy(["responsible_planning_service"])], ), limit={ "person_types": [person_type_pk_lazy("responsible_planning_service")] }, associated_model=Person, new=True, ), validators=[valid_id(Person)], ) permit_type = forms.ChoiceField(label=_("Permit type"), required=False, choices=[]) permit_reference = forms.CharField( label=_("Permit/order reference"), required=False, validators=[validators.MaxLengthValidator(60)], ) total_developed_surface = forms.FloatField( widget=widgets.AreaWidget, label=_("Total developed surface (m2)"), required=False, validators=[ validators.MinValueValidator(0), validators.MaxValueValidator(999999999), ], ) if settings.COUNTRY == "fr": saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[]) reception_date = DateField(label=_("Reception date"), initial=get_now) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if "saisine_type" in self.fields: self.fields["saisine_type"].choices = models.SaisineType.get_types( initial=self.init_data.get("saisine_type") ) self.fields["saisine_type"].help_text = models.SaisineType.get_help() if "permit_type" in self.fields: self.fields["permit_type"].choices = models.PermitType.get_types( initial=self.init_data.get("permit_type"), default="NP" ) self.fields["permit_type"].help_text = models.PermitType.get_help() """ class FileFormResearch(CustomForm, ManageOldType, forms.Form): form_label = _("Research archaeology") form_admin_name = _("Archaeological file - 045 - Research - General") form_slug = "file-045-research-general" base_model = "department" associated_models = { "scientist": Person, "requested_operation_type": OperationType, "organization": Organization, } scientist = forms.IntegerField( widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person"), associated_model=Person, new=True, detail=True, modify=True, ), label=_("Scientist in charge"), required=False ) requested_operation_type = forms.ChoiceField( label=_("Requested operation type"), choices=[], required=False, ) organization = forms.IntegerField( label=_("Lead organization"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-organization"), associated_model=Organization, new=True, detail=True, modify=True, ), validators=[valid_id(Organization)], required=False, ) if settings.COUNTRY == "fr": cira_advised = forms.NullBooleanField(label="Passage en CIRA", required=False) research_comment = forms.CharField( label=_("Research archaeology comment"), widget=forms.Textarea, required=False ) if settings.COUNTRY == "fr": mh_register = forms.NullBooleanField( label="Sur Monument Historique classé", required=False ) mh_listing = forms.NullBooleanField( label="Sur Monument Historique inscrit", required=False ) classified_area = forms.NullBooleanField(label=_("Classified area"), required=False) protected_area = forms.NullBooleanField(label=_("Protected area"), required=False) def __init__(self, *args, **kwargs): super(FileFormResearch, self).__init__(*args, **kwargs) if "requested_operation_type" in self.fields: self.fields["requested_operation_type"].choices = OperationType.get_types( dct={"preventive": False}, initial=self.init_data.get("requested_operation_type"), ) 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"), associated_model=Person, new=True, ), validators=[valid_id(Person)], required=False ) 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 = DateField(label=_("Instruction deadline"), 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 = DateField(label=_("End date"), 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?") class FinalFileDeleteForm(FinalForm): confirm_msg = " " confirm_end_msg = _("Would you like to delete this archaeological file ?") class FileFormPreventiveDetail(forms.ModelForm, CustomForm, ManageOldType): form_label = _("Preventive file") form_admin_name = _("Preventive file - 020 - Edition form") form_slug = "preventive-020-edition-form" associated_models = {} HEADERS = { "start_date": FormHeader(_("Dates")), "total_developed_surface": FormHeader(_("Surfaces")), "type_of_agreement": FormHeader(_("Archaeological royalties")), } class Meta: model = models.File fields = [ "intervention_period", "study_period", "report_due_period", "start_date", "end_date", "ground_start_date", "ground_end_date", "execution_report_date", "type_of_agreement", "operation_type_for_royalties", "total_developed_surface", "total_surface", "linear_meter", ] pk = forms.IntegerField(label="", required=False, widget=forms.HiddenInput) intervention_period = forms.CharField( label=_("Intervention period"), max_length=200, required=False, ) study_period = forms.CharField( label=_("Study period"), max_length=200, required=False, ) report_due_period = forms.CharField( label=_("Report due period"), max_length=200, required=False, ) start_date = DateField( label=_("Start date"), required=False, widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) end_date = DateField( label=_("End date"), required=False, widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) ground_start_date = DateField( label=_("Ground start date"), required=False, widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) ground_end_date = DateField( label=_("Ground end date"), required=False, widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) execution_report_date = DateField( label=_("Execution report date"), required=False, widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) total_developed_surface = forms.FloatField( widget=widgets.AreaWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), label=_("Total developed surface (m2)"), required=False, validators=[ validators.MinValueValidator(0), validators.MaxValueValidator(999999999), ], ) total_surface = forms.FloatField( required=False, widget=widgets.AreaWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), label=_("Total surface (m2)"), validators=[ validators.MinValueValidator(0), validators.MaxValueValidator(999999999), ], ) linear_meter = forms.IntegerField( label=_("Linear meter (m)"), required=False, widget=widgets.MeterKilometerWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), ) def __init__(self, *args, **kwargs): self.user = None if kwargs.get("user", None): self.user = kwargs.pop("user") super(FileFormPreventiveDetail, self).__init__(*args, **kwargs) if not models.AgreementType.objects.count(): self._remove_fields(("type_of_agreement",)) if not models.OperationTypeForRoyalties.objects.count(): self._remove_fields(("operation_type_for_royalties",)) class FileBaseFormset(forms.BaseModelFormSet): def __init__(self, *args, **kwargs): self.instance = None if "instance" in kwargs: self.instance = kwargs.pop("instance") super().__init__(*args, **kwargs) self.queryset = self.get_base_queryset() def get_base_queryset(self): queryset = self.model.objects.filter(pk=None) if self.instance: queryset = self.model.objects.filter(file_id=self.instance.pk) return queryset def get_form_kwargs(self, index): kwargs = super(FileBaseFormset, self).get_form_kwargs(index) if self.instance: kwargs["file_id"] = self.instance.pk return kwargs INLINE_JOB_FIELDS = [ "man_by_day_planned", "days_planned", "man_by_day_worked", "days_worked", ] JOB_WIDGETS = { "job": forms.Select(attrs={"bs_col_width": "col-lg-6 col-12"}), "man_by_day_planned": forms.NumberInput( attrs={"class": "w-50 form-planned", "bs_col_width": "col-2"} ), "days_planned": forms.NumberInput( attrs={"class": "w-50 form-planned", "bs_col_width": "col-2"} ), "man_by_day_worked": forms.NumberInput( attrs={"class": "w-50 form-worked", "bs_col_width": "col-2"} ), "days_worked": forms.NumberInput( attrs={"class": "w-50 form-worked", "bs_col_width": "col-2"} ), } JOB_LABELS = { "man_by_day_planned": _("Man by day"), "days_planned": _("Days"), "man_by_day_worked": _("Man by day"), "days_worked": _("Days"), "Job": _("Job"), } class PreventiveFileForm(BSForm, forms.ModelForm): file_id = forms.IntegerField(widget=forms.HiddenInput) def __init__(self, *args, **kwargs): self.file_id = kwargs.pop("file_id") super().__init__(*args, **kwargs) self.fields["file_id"].initial = self.file_id self._post_init() def save(self, commit=True): if not self.errors: self.instance.file_id = self.file_id return super().save(commit=commit) class PreventiveFileSimpleForm(BSForm, forms.ModelForm): price_agreement = forms.ModelChoiceField( label=_("Price agreement"), queryset=models.PriceAgreement.objects.filter(available=True) ) class Meta: model = models.File fields = ["price_agreement"] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._post_init() class PreventiveFileGenJobForm(PreventiveFileForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) current_value = None if hasattr(self.instance, "job") and self.instance.job: current_value = self.instance.job price_agreement_id = None q = models.File.objects.filter(pk=self.file_id).values("price_agreement_id") if q.count(): price_agreement_id = q.all()[0]["price_agreement_id"] self.fields["job"].choices = models.Job.get_choices( current_value, price_agreement_id=price_agreement_id ) def save(self, commit=True): item = super().save(commit=True) child = item.job.child if not item or not child: return if not self._meta.model.objects.filter(file_id=item.file_id, job=child).count(): self._meta.model.objects.create( file_id=item.file_id, job=child, man_by_day_planned=item.man_by_day_planned, days_planned=item.days_planned, ) return item class PreventiveFileJobForm(PreventiveFileGenJobForm): class Meta: model = models.PreventiveFileJob fields = ["job"] + INLINE_JOB_FIELDS exclude = ["file"] widgets = JOB_WIDGETS labels = JOB_LABELS class PreventiveFileJobBaseFormSet(FileBaseFormset): model = models.PreventiveFileJob PreventiveFileJobFormSet = formset_factory( PreventiveFileJobForm, formset=PreventiveFileJobBaseFormSet, can_delete=True ) PreventiveFileJobFormSet.form_label = _("Post-excavation") PreventiveFileJobFormSet.form_admin_name = _("Preventive file - 030 - Post-excavation") PreventiveFileJobFormSet.form_slug = "preventive-030-post-excavation" PreventiveFileJobFormSet.extra = 2 #PreventiveFileJobFormSet.dynamic_add = True class PreventiveFileGroundJobForm(PreventiveFileGenJobForm): class Meta: model = models.PreventiveFileGroundJob fields = ["job"] + INLINE_JOB_FIELDS widgets = JOB_WIDGETS labels = JOB_LABELS class PreventiveFileGroundJobBaseFormSet(FileBaseFormset): model = models.PreventiveFileGroundJob PreventiveFileGroundJobFormSet = formset_factory( PreventiveFileGroundJobForm, formset=PreventiveFileGroundJobBaseFormSet, can_delete=True, extra=2 ) PreventiveFileGroundJobFormSet.form_label = _("Ground jobs") PreventiveFileGroundJobFormSet.form_admin_name = _( "Preventive file - 040 - Ground jobs" ) PreventiveFileGroundJobFormSet.form_slug = "preventive-040-ground-jobs" #PreventiveFileGroundJobFormSet.dynamic_add = True COST_LABELS = { "quantity_by_day_planned": _("Quantity"), "days_planned": "", "quantity_by_day_worked": _("Quantity"), "days_worked": "", "equipment_service_cost": _("Equipment / service"), } INLINE_COST_FIELDS = [ "quantity_by_day_planned", "days_planned", "quantity_by_day_worked", "days_worked", ] COST_WIDGETS = { "quantity_by_day_planned": forms.NumberInput( attrs={"class": "w-50 form-planned", "bs_col_width": "col-2"} ), "days_planned": forms.NumberInput( attrs={"class": "w-50 form-planned unit-form", "bs_col_width": "col-2"} ), "quantity_by_day_worked": forms.NumberInput( attrs={"class": "w-50 form-worked", "bs_col_width": "col-2"} ), "days_worked": forms.NumberInput( attrs={"class": "w-50 form-worked unit-form", "bs_col_width": "col-2"} ), "equipment_service_cost": forms.Select( attrs={"class": "form-cost", "bs_col_width": "col-lg-6 col-12"} ), } class PreventiveFileEquipmentServiceForm(PreventiveFileForm): type_filter = None class Meta: model = models.PreventiveFileEquipmentServiceCost fields = ["equipment_service_cost"] + INLINE_COST_FIELDS widgets = COST_WIDGETS labels = COST_LABELS def __init__(self, *args, **kwargs): super(PreventiveFileEquipmentServiceForm, self).__init__(*args, **kwargs) price_agreement_id = None q = models.File.objects.filter(pk=self.file_id).values("price_agreement_id") if q.count(): price_agreement_id = q.all()[0]["price_agreement_id"] q = models.EquipmentServiceCost.objects.filter( available=True, parent__isnull=True, price_agreement_id=price_agreement_id, equipment_service_type__generic_equipment_type__txt_idx=self.type_filter, ) self.unities = {} unit_dict = dict(models.ES_UNITS) choices = [("", "-" * 9)] costs = list(q.all()) if ( self.instance and self.instance.equipment_service_cost_id and self.instance.equipment_service_cost not in costs ): costs.append(self.instance.equipment_service_cost) self.flat_rates = [] for cost in costs: choices.append((cost.pk, str(cost))) if cost.unit: self.unities[cost.pk] = unit_dict[cost.unit] if cost.flat_rate: self.flat_rates.append(cost.pk) self.fields["equipment_service_cost"].choices = choices self.fields["quantity_by_day_planned"].initial = 1 self.fields["days_planned"].unit = "..." self.fields["days_worked"].unit = "..." def save(self, commit=True): item = super().save(commit=True) if not item: return for child in item.equipment_service_cost.equipment_service_type.children.all(): if not self._meta.model.objects.filter( file_id=item.file_id, equipment_service_cost=child ).count(): self._meta.model.objects.create( file_id=item.file_id, equipment_service_cost=child, quantity_by_day_planned=0, ) return item class PreventiveFileEquipmentServiceBaseFormSet(FileBaseFormset): model = models.PreventiveFileEquipmentServiceCost def get_base_queryset(self): queryset = super( PreventiveFileEquipmentServiceBaseFormSet, self ).get_base_queryset() queryset = queryset.filter( equipment_service_cost__equipment_service_type__generic_equipment_type__txt_idx=self.type_filter ) return queryset class AdministrativeActFileModifySelect(TableSelect): _model = AdministrativeAct search_vector = forms.CharField( label=_("Full text search"), widget=widgets.SearchWidget( "archaeological-operations", "administrativeact", "administrativeactfile", ), ) year = forms.IntegerField(label=_("Year")) index = forms.IntegerField(label=_("Index")) ref_sra = forms.CharField(label=_("Other reference"), max_length=200) act_type = forms.ChoiceField(label=_("Act type"), choices=[]) act_object = forms.CharField(label=_("Object (full text search)"), max_length=300) operation__towns = get_town_field() if settings.ISHTAR_DPTS: operation__towns__numero_insee__startswith = forms.ChoiceField( label=_("Department"), choices=[] ) def __init__(self, *args, **kwargs): super(AdministrativeActFileModifySelect, self).__init__(*args, **kwargs) if "act_type" in self.fields: self.fields["act_type"].choices = ActType.get_types( dct={"intented_to": "F"} ) self.fields["act_type"].help_text = ActType.get_help( dct={"intented_to": "F"} ) k = "operation__towns__numero_insee__startswith" if settings.ISHTAR_DPTS and k in self.fields: self.fields[k].choices = [("", "--")] + list(settings.ISHTAR_DPTS) class AdministrativeActFileSelect(TableSelect): _model = AdministrativeAct search_vector = forms.CharField( label=_("Full text search"), widget=widgets.SearchWidget( "archaeological-operations", "administrativeact", "administrativeactfile", ), ) year = forms.IntegerField(label=_("Year")) index = forms.IntegerField(label=_("Index")) ref_sra = forms.CharField(label=_("Other reference"), max_length=200) act_type = forms.ChoiceField(label=_("Act type"), choices=[]) indexed = forms.NullBooleanField(label=_("Indexed?")) associated_file__towns = get_town_field() parcel = forms.CharField(label=_("Parcel")) if settings.ISHTAR_DPTS: associated_file__towns__numero_insee__startswith = forms.ChoiceField( label=_("Department"), choices=[] ) act_object = forms.CharField(label=_("Object"), max_length=300) signature_date = DateField(label=_("Signature date")) associated_file__name = forms.CharField(label=_("File name"), max_length=200) associated_file__general_contractor = forms.IntegerField( label=_("General contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person", args=[person_type_pk_lazy("general_contractor")] ), associated_model=Person, ), validators=[valid_id(Person)], ) associated_file__general_contractor__attached_to = forms.IntegerField( label=_("Organization of general contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-organization", args=[organization_type_pks_lazy(["general_contractor"])], ), associated_model=Organization, ), validators=[valid_id(Organization)], ) associated_file__numeric_reference = forms.IntegerField( label=_("File numeric reference") ) associated_file__year = forms.IntegerField(label=_("File year")) associated_file__internal_reference = forms.CharField( max_length=200, label=_("File other reference") ) associated_file__in_charge = forms.IntegerField( label=_("File in charge"), widget=widgets.JQueryAutoComplete( reverse_lazy( "autocomplete-person", args=[person_type_pk_lazy("sra_agent")] ), associated_model=Person, ), validators=[valid_id(Person)], ) associated_file__permit_reference = forms.CharField( max_length=200, label=_("File permit reference") ) history_creator = forms.IntegerField( label=_("Created by"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person", args=["0", "user"]), associated_model=Person, ), validators=[valid_id(Person)], ) history_modifier = forms.IntegerField( label=_("Modified by"), widget=widgets.JQueryAutoComplete( reverse_lazy("autocomplete-person", args=["0", "user"]), associated_model=Person, ), validators=[valid_id(Person)], ) def __init__(self, *args, **kwargs): super(AdministrativeActFileSelect, self).__init__(*args, **kwargs) if "act_type" in self.fields: self.fields["act_type"].choices = ActType.get_types( dct={"intented_to": "F"} ) self.fields["act_type"].help_text = ActType.get_help( dct={"intented_to": "F"} ) k = "associated_file__towns__numero_insee__startswith" if k in self.fields and settings.ISHTAR_DPTS: self.fields[k].choices = [("", "--")] + list(settings.ISHTAR_DPTS) class AdministrativeActFileFormSelection(AdministrativeActOpeFormSelection): SEARCH_AND_SELECT = True pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-administrativeactfile"), AdministrativeActFileSelect, AdministrativeAct, table_cols="TABLE_COLS_FILE", ), validators=[valid_id(AdministrativeAct)], ) class AdministrativeActFileModifyFormSelection(AdministrativeActOpeFormSelection): SEARCH_AND_SELECT = True pk = forms.IntegerField( label="", required=False, widget=widgets.DataTable( reverse_lazy("get-administrativeactfile"), AdministrativeActFileModifySelect, AdministrativeAct, table_cols="TABLE_COLS_FILE", ), validators=[valid_id(AdministrativeAct)], ) class AdministrativeActFileForm(AdministrativeActForm): form_admin_name = _("Archaeological file - Administrative act - General") form_slug = "file-adminact-general" act_type = forms.ChoiceField(label=_("Act type"), choices=[]) TYPES = [ FieldType("act_type", ActType, extra_args={"dct": {"intented_to": "F"}}), ] class AdministrativeActFileModifForm( AdministrativeActModifForm, AdministrativeActFileForm ): pk = forms.IntegerField(required=False, widget=forms.HiddenInput) index = forms.IntegerField(label=_("Index"), required=False)