diff options
| -rw-r--r-- | archaeological_finds/forms.py | 2 | ||||
| -rw-r--r-- | archaeological_finds/forms_treatments.py | 107 | ||||
| -rw-r--r-- | archaeological_finds/migrations/0157_treatments_statement_condition.py | 27 | ||||
| -rw-r--r-- | archaeological_finds/models_treatments.py | 41 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html | 2 | ||||
| -rw-r--r-- | archaeological_finds/urls.py | 10 | ||||
| -rw-r--r-- | archaeological_finds/views.py | 9 | ||||
| -rw-r--r-- | ishtar_common/static/js/ishtar.js | 5 |
8 files changed, 151 insertions, 52 deletions
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 58869d108..83e3e330a 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -61,6 +61,7 @@ from archaeological_finds.forms_treatments import ( AdministrativeActTreatmentFileModifForm, N1TreatmentForm, QAFindTreatmentForm, + QATreatmentForm, OneNTreatmentForm, ) from archaeological_operations.models import ( @@ -169,6 +170,7 @@ __all__ = [ "ResultingFindForm", "ResultingFindsForm", "SingleUpstreamFindFormSelection", + "QATreatmentForm", ] logger = logging.getLogger(__name__) diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py index f4848446e..53a928fd8 100644 --- a/archaeological_finds/forms_treatments.py +++ b/archaeological_finds/forms_treatments.py @@ -459,6 +459,76 @@ class TreatmentDeletionForm(FinalForm): confirm_end_msg = _("Would you like to delete this treatment?") +class QATreatmentForm(CustomForm, IshtarForm): + treatment_type_id = forms.ChoiceField(label=_("Treatment type"), choices=[]) + label = forms.CharField(label=_("Label"), max_length=200) + year = forms.IntegerField( + label=_("Year"), initial=lambda: datetime.datetime.now().year, + validators=[validators.MinValueValidator(1000), + validators.MaxValueValidator(2100)], required=False) + start_date = DateField(label=_("Precise date"), required=False, + initial=lambda: datetime.date.today()) + person_id = forms.IntegerField( + label=_("Responsible"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-person'), associated_model=Person, + new=True), + validators=[valid_id(Person)], required=False) + organization_id = forms.IntegerField( + label=_("Organization"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-organization'), + associated_model=Organization, new=True), + validators=[valid_id(Organization)], required=False) + + TYPES = [ + FieldType("treatment_type_id", models.TreatmentType, empty_first=False, + extra_args={'dct': {"is_statement_condition": True}}), + ] + + def __init__(self, *args, **kwargs): + self.confirm = False + self.user = None + if "limits" in kwargs: + kwargs.pop("limits") + if 'user' in kwargs: + self.user = kwargs.pop('user') + if hasattr(self.user, 'ishtaruser'): + self.user = self.user.ishtaruser + super().__init__(*args, **kwargs) + if not self.user: + return + + q = Person.objects.filter(ishtaruser__pk=self.user.pk) + if not q.count(): + return + person = q.all()[0] + self.fields['person_id'].initial = person.pk + if person.attached_to_id: + self.fields['organization_id'].initial = person.attached_to_id + + def clean(self): + year = self.cleaned_data['year'] + if not year: + if self.cleaned_data['start_date']: + self.cleaned_data['year'] = self.cleaned_data['start_date'].year + else: + raise forms.ValidationError(_("At least a year is required.")) + if not self.cleaned_data.get('treatment_type_id', None): + raise forms.ValidationError(_("Treatment type is required.")) + + return self.cleaned_data + + def save(self, user): + treatment_type_id = self.cleaned_data.pop("treatment_type_id") + self.cleaned_data["history_creator"] = user + self.cleaned_data["history_modifier"] = user + treatment = models.Treatment.objects.create(**self.cleaned_data) + treatment.treatment_types.add( + models.TreatmentType.objects.get(pk=treatment_type_id)) + return treatment + + class QABasePackagingForm(CustomForm, IshtarForm): create_treatment = forms.BooleanField( label=_("Create a treatment"), required=False, @@ -1181,6 +1251,7 @@ class QANewExhibitionLoanForm(IshtarForm): class QAStatementCondition(ManageOldType, forms.Form): form_label = _("Statement condition") base_models = [ + "qa_treatment", "qa_alterations", "qa_alteration_causes", "qa_recommended_treatments", @@ -1198,11 +1269,9 @@ class QAStatementCondition(ManageOldType, forms.Form): "qa_integrities": models.IntegrityType, "follow_up_action": models.FollowUpActionType, "statement_condition_type_id": models.StatementConditionType, - "treatment_person": Person, "qa_museum_marking_type": models.MarkingType, "qa_museum_inventory_marking_presence": models.InventoryMarkingPresence, } - TREATMENT_FIELDS = ("treatment_type", "treatment_person", "treatment_organization") HEADERS = {} pk = forms.IntegerField(required=False, widget=forms.HiddenInput) HEADERS["date"] = FormHeader(_("Statement of condition")) @@ -1211,6 +1280,13 @@ class QAStatementCondition(ManageOldType, forms.Form): choices=models.StatementCondition.APPLIED_CHOICES) statement_condition_type_id = forms.ChoiceField(label=_("Type"), choices=[], required=True) + treatment_id = forms.IntegerField( + label=_("Associated treatment"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-statement-treatment'), + associated_model=models.Treatment, + new=True), + validators=[valid_id(models.Treatment)], required=False) verification_officer_id = forms.IntegerField( label=_("Verification officer"), widget=widgets.JQueryAutoComplete( @@ -1229,22 +1305,6 @@ class QAStatementCondition(ManageOldType, forms.Form): observations = forms.CharField(label=_("Observations"), widget=forms.Textarea, required=False) - HEADERS["treatment_type"] = FormHeader(_("Treatment"), collapse=True) - treatment_type = forms.ChoiceField(label=_("Treatment type"), choices=[], - required=False) - treatment_person = forms.IntegerField( - label=_("Responsible"), - widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-person'), associated_model=Person, - new=True), - validators=[valid_id(Person)], required=False) - treatment_organization = forms.IntegerField( - label=_("Organization"), - widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-organization'), - associated_model=Organization, new=True), - validators=[valid_id(Organization)], required=False) - HEADERS["qa_description"] = FormHeader(_("Find")) qa_description = forms.CharField( label=_("Description"), widget=forms.Textarea, required=False @@ -1362,8 +1422,6 @@ class QAStatementCondition(ManageOldType, forms.Form): FieldType("statement_condition_type_id", models.StatementConditionType, empty_first=False), FieldType("qa_treatment_emergency_id", models.TreatmentEmergencyType), - FieldType("treatment_type", models.TreatmentType, empty_first=False, - extra_args={'dct': {"is_statement_condition": True}}), ] PROFILE_FILTER = { "museum": ["qa_museum_observed_quantity", "qa_museum_marking_type", @@ -1378,10 +1436,10 @@ class QAStatementCondition(ManageOldType, forms.Form): super().__init__(*args, **kwargs) if not self.user: return + self.fields["treatment_id"].widget.user = self.user q = Person.objects.filter(ishtaruser__pk=self.user.pk) if q.count(): person = q.all()[0] - self.fields['treatment_person'].initial = person.pk self.fields['verification_officer_id'].initial = person.pk def save(self): @@ -1395,11 +1453,6 @@ class QAStatementCondition(ManageOldType, forms.Form): key = f"qa_{m2m_attr}" if key in data: m2m[m2m_attr] = data.pop(key) - # remove treatment fields - treatment = {} - for k in self.TREATMENT_FIELDS: - if k in data.keys(): - treatment[k] = data.pop(k) # remove "qa_" prefix for remaining fields for k in list(data.keys()): if k.startswith("qa_"): @@ -1431,4 +1484,4 @@ class QAStatementCondition(ManageOldType, forms.Form): # draft exit return st.applied = applied - st.apply_validation(treatment) + st.apply_validation() diff --git a/archaeological_finds/migrations/0157_treatments_statement_condition.py b/archaeological_finds/migrations/0157_treatments_statement_condition.py new file mode 100644 index 000000000..88ec7addc --- /dev/null +++ b/archaeological_finds/migrations/0157_treatments_statement_condition.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.19 on 2026-06-15 11:28 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('archaeological_finds', '0156_context_record_com_comparanda_alteration_com_conservation_recomm'), + ] + + operations = [ + migrations.RemoveField( + model_name='historicaltreatment', + name='statement_condition', + ), + migrations.RemoveField( + model_name='treatment', + name='statement_condition', + ), + migrations.AddField( + model_name='statementcondition', + name='treatment', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='statement_conditions', to='archaeological_finds.treatment', verbose_name='Treament'), + ), + ] diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index ab16711d1..052a7b5ee 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -391,13 +391,6 @@ class Treatment( null=True, on_delete=models.SET_NULL, ) - statement_condition = models.ForeignKey( - "StatementCondition", - verbose_name=_("Statement condition"), - blank=True, - null=True, - on_delete=models.SET_NULL, - ) treatment_status = models.ForeignKey( TreatmentStatus, verbose_name=_("Treatment status"), @@ -1735,7 +1728,6 @@ class StatementCondition( APPLIED_CHOICES = ( ("D", _("Draft")), ("V", _("Validated")), - ("T", _("Validated with treatment")), ) date = models.DateField(_("Date")) @@ -1744,11 +1736,15 @@ class StatementCondition( last = models.BooleanField(_("Last"), default=True) find = models.ForeignKey(Find, verbose_name=_("Find"), on_delete=models.CASCADE, related_name="statement_conditions") + treatment = models.ForeignKey( + Treatment, verbose_name=_("Treament"), on_delete=models.SET_NULL, + null=True, blank=True, related_name="statement_conditions") campaign_number = models.TextField(_("Campaign/observation number"), default="", blank=True) report_number = models.TextField(_("Report number"), default="", blank=True) - verification_officer = models.ForeignKey(Person, verbose_name=_("Verification officer"), null=True, - blank=True, on_delete=models.SET_NULL) + verification_officer = models.ForeignKey( + Person, verbose_name=_("Verification officer"), null=True, blank=True, + on_delete=models.SET_NULL) statement_condition_type = models.ForeignKey( StatementConditionType, verbose_name=_("Type"), on_delete=models.PROTECT) follow_up_actions = models.ManyToManyField( @@ -1890,14 +1886,21 @@ class StatementCondition( def get_initial(self, prefix="qa_"): initial = {} - base_attrs = ["pk", "date", "find_id", "statement_condition_type_id", "verification_officer_id", - "campaign_number", "report_number", "observations"] + base_attrs = [ + "pk", "date", "find_id", "statement_condition_type_id", + "verification_officer_id", "campaign_number", "report_number", + "observations", "treatment_id" + ] for attr in base_attrs: initial[attr] = getattr(self, attr) for attr in self.OVERLOADED_FIELDS: initial[f"{prefix}{attr}"] = getattr(self, attr) - m2m_attrs = list(self.OVERLOADED_M2M_FIELDS) + ["follow_up_actions"] + m2m_attrs = ["follow_up_action"] for attr in m2m_attrs: + initial[attr] = list( + getattr(self, f"{attr}s").all().values_list("id", flat=True) + ) + for attr in self.OVERLOADED_M2M_FIELDS: initial[f"{prefix}{attr}"] = list( getattr(self, attr).all().values_list("id", flat=True) ) @@ -1913,9 +1916,6 @@ class StatementCondition( "applied", flat=True) )[0] == "D" - def _create_associated_treatment(self, treatment_fields): - pass - def _create_initial_statementcondition(self): """ Create a reference statement condition in order to get the diff @@ -1950,7 +1950,7 @@ class StatementCondition( getattr(obj, attr).clear() getattr(obj, attr).add(*new_m2m) - def apply_validation(self, treatment_fields=None): + def apply_validation(self): """ Copy statement condition fields to the associated find """ @@ -1958,13 +1958,6 @@ class StatementCondition( if not self.__class__.objects.filter(initial=True, find=self.find).exists(): self._create_initial_statementcondition() - # treatment creation - if self.applied == "T": - find = self._create_associated_treatment(treatment_fields) - if find.pk != self.find_id: # new find is created after treatment - self.find, self.find_id = find, find.pk - self.__class__.objects.filter(pk=self.pk).update(find_id=find.pk) - # update find fields for attr in self.OVERLOADED_FIELDS: setattr(self.find, attr, getattr(self, attr)) diff --git a/archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html b/archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html index 30d9cc0b3..23667852c 100644 --- a/archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html +++ b/archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html @@ -39,6 +39,8 @@ {% endif %} <div class="row"> + {% field_flex _("Date") statement_condition.date|date:"SHORT_DATE_FORMAT" %} + {% field_flex_detail _("Treatment") statement_condition.treatment %} {% field_flex _("Verification officer") statement_condition.verification_officer %} {% field_flex _("Campaign/observation number") statement_condition.campaign_number %} {% field_flex _("Report number") statement_condition.report_number %} diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 40e26ce01..97f8df68f 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -663,6 +663,16 @@ urlpatterns = [ views.autocomplete_statementcondition, name="autocomplete-statementcondition", ), + path( + "autocomplete-statement-treatment/", + views.autocomplete_statement_treatment, + name="autocomplete-statement-treatment", + ), + path( + "new-treatment/<str:parent_name>/", + views.new_treatment, + name="new-treatment", + ), re_path( r"get-find-for-ope/own/(?P<type>.+)?$", views.get_find_for_ope, diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 929d57962..cde528a05 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -59,9 +59,10 @@ from ishtar_common.views_item import ( get_item, show_item, revert_item, + new_qa_item, get_autocomplete_item, get_autocomplete_queries, - get_autocomplete_query + get_autocomplete_query, ) from archaeological_operations.views import get_relation_modify @@ -129,6 +130,12 @@ get_treatment = get_item( display_treatment = display_item(models.Treatment) autocomplete_treatment = get_autocomplete_item(model=models.Treatment) +autocomplete_statement_treatment = get_autocomplete_item( + model=models.Treatment, + extra={"treatment_types__is_statement_condition": True} +) +new_treatment = new_qa_item(models.Treatment, forms.QATreatmentForm, + page_name=_("New treatment")) get_administrativeacttreatment = get_item( AdministrativeAct, diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 519c17158..624d1902b 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -1260,6 +1260,11 @@ var dt_generate_qa_url = function (table, url){ var dt_qa_open = function (url, modal_id){ if (!modal_id) modal_id = "modal-dynamic-form"; + if (!$('#' + modal_id).length){ + let src = '<div class="modal" id="' + modal_id + '" tabindex="-1" role="dialog"'; + src += 'data-backdrop="static" data-keyboard="true" aria-hidden="true"></div>'; + $("#message").after(src); + } short_wait(); $.ajax({ url: url, |
