summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_finds/forms.py2
-rw-r--r--archaeological_finds/forms_treatments.py107
-rw-r--r--archaeological_finds/migrations/0157_treatments_statement_condition.py27
-rw-r--r--archaeological_finds/models_treatments.py41
-rw-r--r--archaeological_finds/templates/ishtar/blocks/sheet_statement_condition.html2
-rw-r--r--archaeological_finds/urls.py10
-rw-r--r--archaeological_finds/views.py9
-rw-r--r--ishtar_common/static/js/ishtar.js5
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,