summaryrefslogtreecommitdiff
path: root/archaeological_finds
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2025-02-21 17:06:53 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2025-02-24 18:09:08 +0100
commitbc6cf94def73926e6f6bb986d61e5861a17584e2 (patch)
treeba4a7438cd6594c02938ad3211d523c6dd28a79f /archaeological_finds
parent1b72554283f5c9e0644262a3f182409376870991 (diff)
downloadIshtar-bc6cf94def73926e6f6bb986d61e5861a17584e2.tar.bz2
Ishtar-bc6cf94def73926e6f6bb986d61e5861a17584e2.zip
✨ treatment state refactoring -> distinct input status and treatment status (refs #6182) - treatments: search criteria
Diffstat (limited to 'archaeological_finds')
-rw-r--r--archaeological_finds/admin.py11
-rw-r--r--archaeological_finds/forms_treatments.py162
-rw-r--r--archaeological_finds/migrations/0102_link_apps.py2
-rw-r--r--archaeological_finds/migrations/0103_auto_20200129_1944.py1
-rw-r--r--archaeological_finds/migrations/0109_auto_20220328_1222.py2
-rw-r--r--archaeological_finds/migrations/0136_treatment_status_refactoring.py83
-rw-r--r--archaeological_finds/migrations/0137_data_migration_treatment_status_inputstatus.py51
-rw-r--r--archaeological_finds/migrations/0137_data_migration_treatmentinputstatus.json24
-rw-r--r--archaeological_finds/migrations/0137_data_migration_treatmentstatus.json62
-rw-r--r--archaeological_finds/models.py8
-rw-r--r--archaeological_finds/models_treatments.py128
-rw-r--r--archaeological_finds/templates/ishtar/forms/exhibition_form.html3
-rw-r--r--archaeological_finds/templates/ishtar/sheet_treatment.html12
-rw-r--r--archaeological_finds/tests.py48
14 files changed, 477 insertions, 120 deletions
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py
index 5536901cf..39a8b16a4 100644
--- a/archaeological_finds/admin.py
+++ b/archaeological_finds/admin.py
@@ -101,7 +101,7 @@ admin_site.register(models.Property, PropertyAdmin)
class TreatmentAdmin(HistorizedObjectAdmin):
list_display = ('year', 'index', 'label', 'treatment_types_lbl', 'location',
'downstream_lbl', 'upstream_lbl', 'container', 'person')
- list_filter = ('treatment_types', 'treatment_state', 'year')
+ list_filter = ('treatment_types', 'input_status', 'treatment_status', 'year')
model = models.Treatment
readonly_fields = HistorizedObjectAdmin.readonly_fields + [
'cached_label', 'downstream_lbl', 'upstream_lbl',
@@ -232,11 +232,16 @@ class TreatmentFileTypeAdmin(GeneralTypeAdmin):
extra_list_display = ["treatment_type"]
-@admin.register(models.TreatmentState, site=admin_site)
-class TreatmentStateAdmin(GeneralTypeAdmin):
+@admin.register(models.TreatmentInputStatus, site=admin_site)
+class TreatmentInputStatusAdmin(GeneralTypeAdmin):
extra_list_display = ["order", "executed"]
+@admin.register(models.TreatmentStatus, site=admin_site)
+class TreatmentStatusAdmin(GeneralTypeAdmin):
+ extra_list_display = ["order"]
+
+
@admin.register(models.Exhibition, site=admin_site)
class ExhibitionAdmin(HistorizedObjectAdmin):
list_display = ('name', 'year', 'reference', 'exhibition_type')
diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py
index 936834267..b4cd973c1 100644
--- a/archaeological_finds/forms_treatments.py
+++ b/archaeological_finds/forms_treatments.py
@@ -64,6 +64,38 @@ class TreatmentSelect(DocumentItemSelect):
associated_model=Person),
label=_("Scientific monitoring manager"))
treatment_types = forms.ChoiceField(label=_("Treatment type"), choices=[])
+ label = forms.CharField(label=_("Label"),
+ max_length=200, required=False)
+ reference = forms.CharField(
+ label=_("Reference"), max_length=200, required=False)
+ treatment_status = forms.ChoiceField(label=_("Status"), choices=[])
+ input_status = forms.ChoiceField(label=_("Input status"), choices=[])
+ location = forms.IntegerField(
+ label=_("Location"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse),
+ validators=[valid_id(Warehouse)])
+ scientific_monitoring_manager = forms.IntegerField(
+ label=_("Scientific monitoring manager"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-person'), associated_model=Person),
+ )
+ person = forms.IntegerField(
+ label=_("Responsible of the treatment"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-person'), associated_model=Person),
+ )
+ organization = forms.IntegerField(
+ label=_("Organization"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-organization'),
+ associated_model=Organization),
+ )
+ TYPES = [
+ FieldType('treatment_status', models.TreatmentStatus),
+ FieldType('input_status', models.TreatmentInputStatus),
+ FieldType('treatment_type', models.TreatmentType),
+ ]
def __init__(self, *args, **kwargs):
super(TreatmentSelect, self).__init__(*args, **kwargs)
@@ -88,36 +120,39 @@ class TreatmentFormSelection(CustomForm, forms.Form):
validators=[valid_id(models.Treatment)])
-class TreatmentStateSelect(forms.Select):
+class TreatmentInputStatusSelect(forms.Select):
def render(self, name, value, attrs=None, renderer=None):
- rendered = super(TreatmentStateSelect, self).render(name, value, attrs,
- renderer)
+ rendered = super().render(name, value, attrs, renderer)
executed_id = [
- str(t.pk) for t in models.TreatmentState.objects.filter(
+ str(t.pk) for t in models.TreatmentInputStatus.objects.filter(
executed=True).all()]
if not executed_id:
return rendered
message = '<i class="fa fa-exclamation-triangle" ' \
'aria-hidden="true"></i> &nbsp;'
- message += str(_("Once validated, this state is not reversible."))
+ message += str(_("Once validated, this input status is not reversible."))
+ message += " " + str(
+ _("Depending on the type of treatment, container change and find "
+ "separation/grouping will be carried out on a database basis.")
+ )
rendered += """
- <div id="%(name)s-msg"class="alert alert-warning d-none">%(message)s</div>
- <script type='text/javascript'>
- var %(id)s_exec_list = ['%(exec_list)s'];
- var %(id)s_check = function(){
- var current_val = $("#id_%(name)s").val();
- if (%(id)s_exec_list.indexOf(current_val) != -1){
- $("#%(name)s-msg").removeClass("d-none");
- } else {
- $("#%(name)s-msg").addClass("d-none");
- }
- };
-
- $("#id_%(name)s").change(%(id)s_check);
- setTimeout(function(){ %(id)s_check(); }, 500);
- </script>""" % {"name": name, "id": name.replace("-", "_"),
- "exec_list": "','".join(executed_id),
- "message": message}
+<div id="%(name)s-msg"class="alert alert-warning d-none">%(message)s</div>
+<script type='text/javascript'>
+var %(id)s_exec_list = ['%(exec_list)s'];
+var %(id)s_check = function(){
+ var current_val = $("#id_%(name)s").val();
+ if (%(id)s_exec_list.indexOf(current_val) != -1){
+ $("#%(name)s-msg").removeClass("d-none");
+ } else {
+ $("#%(name)s-msg").addClass("d-none");
+ }
+};
+
+$("#id_%(name)s").change(%(id)s_check);
+setTimeout(function(){ %(id)s_check(); }, 500);
+</script>""" % {"name": name, "id": name.replace("-", "_"),
+ "exec_list": "','".join(executed_id),
+ "message": message}
return rendered
@@ -128,32 +163,51 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
form_admin_name = _("Treatment - 020 - General")
form_slug = "treatment-020-general"
base_models = ['treatment_type']
- associated_models = {'treatment_type': models.TreatmentType,
- 'person': Person,
- 'scientific_monitoring_manager': Person,
- 'location': Warehouse,
- 'organization': Organization,
- 'container': Container,
- 'treatment_state': models.TreatmentState,
- }
+ associated_models = {
+ 'treatment_type': models.TreatmentType,
+ 'person': Person,
+ 'scientific_monitoring_manager': Person,
+ 'location': Warehouse,
+ 'organization': Organization,
+ 'container': Container,
+ 'treatment_status': models.TreatmentStatus,
+ 'input_status': models.TreatmentInputStatus,
+ }
+ HEADERS = {
+ "treatment_type": FormHeader(_("General")),
+ "location": FormHeader(_("Location/responsability")),
+ "start_date": FormHeader(_("Details")),
+ }
file_upload = True
need_user_for_initialization = True
treatment_type = widgets.Select2MultipleField(
label=_("Treatment type"), choices=[],
widget=widgets.CheckboxSelectMultiple)
- treatment_state = forms.ChoiceField(label=_("State"), choices=[],
- widget=TreatmentStateSelect)
year = forms.IntegerField(label=_("Year"),
initial=lambda: datetime.datetime.now().year,
validators=[validators.MinValueValidator(1000),
validators.MaxValueValidator(2100)])
+ label = forms.CharField(label=_("Label"),
+ max_length=200, required=False)
+ reference = forms.CharField(
+ label=_("Reference"), max_length=200, required=False)
+ treatment_status = forms.ChoiceField(label=_("Status"), choices=[])
+ input_status = forms.ChoiceField(label=_("Input status"), choices=[],
+ widget=TreatmentInputStatusSelect)
location = forms.IntegerField(
label=_("Location"),
widget=widgets.JQueryAutoComplete(
reverse_lazy('autocomplete-warehouse'), associated_model=Warehouse,
new=True),
validators=[valid_id(Warehouse)])
+ container = forms.IntegerField(
+ label=_("Destination container (relevant for treatment that change "
+ "location)"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-container'),
+ associated_model=Container, new=True),
+ validators=[valid_id(Container)], required=False)
scientific_monitoring_manager = forms.IntegerField(
label=_("Scientific monitoring manager"),
widget=widgets.JQueryAutoComplete(
@@ -161,7 +215,7 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
new=True),
validators=[valid_id(Person)], required=False)
person = forms.IntegerField(
- label=_("Responsible"),
+ label=_("Responsible of the treatment"),
widget=widgets.JQueryAutoComplete(
reverse_lazy('autocomplete-person'), associated_model=Person,
new=True),
@@ -172,22 +226,11 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
reverse_lazy('autocomplete-organization'),
associated_model=Organization, new=True),
validators=[valid_id(Organization)], required=False)
- label = forms.CharField(label=_("Label"),
- max_length=200, required=False)
- reference = forms.CharField(
- label=_("Reference"), max_length=200, required=False)
# external_id = forms.CharField(
# label=_("External ref."), max_length=200, required=False)
start_date = DateField(label=_("Start date"), required=False,
initial=datetime.date.today)
- end_date = DateField(label=_("Closing date"), required=False)
- container = forms.IntegerField(
- label=_("Destination container (relevant for treatment that change "
- "location)"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-container'),
- associated_model=Container, new=True),
- validators=[valid_id(Container)], required=False)
+ end_date = DateField(label=_("End date"), required=False)
goal = forms.CharField(label=_("Goal"),
widget=forms.Textarea, required=False)
description = forms.CharField(label=_("Description"),
@@ -206,7 +249,8 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
widget=forms.HiddenInput)
TYPES = [
- FieldType('treatment_state', models.TreatmentState, True),
+ FieldType('treatment_status', models.TreatmentStatus, True),
+ FieldType('input_status', models.TreatmentInputStatus, True),
FieldType(
'treatment_type', models.TreatmentType, is_multiple=True,
extra_args={'dct': {'upstream_is_many': False,
@@ -238,9 +282,9 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
initial = kwargs.get('initial', {})
if initial.get('executed', False):
- self.fields['treatment_state'].choices = \
- models.TreatmentState.get_types(empty_first=False,
- dct={'executed': True})
+ self.fields['input_status'].choices = \
+ models.TreatmentInputStatus.get_types(
+ empty_first=False, dct={'executed': True})
q = Person.objects.filter(ishtaruser__pk=user.pk)
if q.count():
@@ -288,8 +332,8 @@ class BaseTreatmentForm(CustomForm, ManageOldType):
if tp.change_reference_location
]
- if (change_ref_location or change_current_location
- ) and restore_reference_location:
+ if (change_ref_location or change_current_location) and \
+ restore_reference_location:
if change_ref_location:
raise forms.ValidationError(
str(
@@ -332,7 +376,8 @@ class N1TreatmentForm(BaseTreatmentForm):
form_slug = "treatmentn1-020-general"
TYPES = [
- FieldType('treatment_state', models.TreatmentState, True,
+ FieldType('treatment_status', models.TreatmentStatus, True),
+ FieldType('input_status', models.TreatmentInputStatus, True,
extra_args={'dct': {"executed": True}}),
FieldType(
'treatment_type', models.TreatmentType, is_multiple=True,
@@ -347,7 +392,8 @@ class OneNTreatmentForm(BaseTreatmentForm):
form_slug = "treatment1n-020-general"
TYPES = [
- FieldType('treatment_state', models.TreatmentState, True,
+ FieldType('treatment_status', models.TreatmentStatus, True),
+ FieldType('input_status', models.TreatmentInputStatus, True,
extra_args={'dct': {"executed": True}}),
FieldType(
'treatment_type', models.TreatmentType, is_multiple=True,
@@ -534,7 +580,8 @@ class QAFindTreatmentForm(QABasePackagingForm):
if self.cleaned_data['create_treatment']:
treat_type = models.TreatmentType.objects.get(
pk=self.cleaned_data['treatment_type'])
- treat_state = models.TreatmentState.get_completed_state()
+ treat_input_status = models.TreatmentInputStatus.get_validated_state()
+ treat_status = models.TreatmentStatus.get_completed_state()
t = models.Treatment.objects.create(
container=container,
year=self.cleaned_data['year'],
@@ -543,7 +590,8 @@ class QAFindTreatmentForm(QABasePackagingForm):
person_id=self.cleaned_data['person'],
organization_id=self.cleaned_data['organization'],
history_modifier=user,
- treatment_state=treat_state
+ input_status=treat_input_status,
+ treatment_status=treat_status,
)
t.treatment_types.add(treat_type)
t.save(items=items)
@@ -670,7 +718,7 @@ class TreatmentFileSelect(DocumentItemSelect):
associated_model=Organization),
validators=[valid_id(Organization)])
- end_date = DateField(label=_("Closing date"), required=False)
+ end_date = DateField(label=_("End date"), required=False)
exhibition_start = DateField(label=_("Exhibition start date"))
exhibition_end = DateField(label=_("Exhibition end date"))
@@ -762,7 +810,7 @@ class TreatmentFileForm(CustomForm, ManageOldType):
)
creation_date = DateField(label=_("Start date"), required=False,
initial=lambda: datetime.datetime.now())
- end_date = DateField(label=_("Closing date"), required=False)
+ end_date = DateField(label=_("End date"), required=False)
TYPES = [
FieldType('type', models.TreatmentFileType),
diff --git a/archaeological_finds/migrations/0102_link_apps.py b/archaeological_finds/migrations/0102_link_apps.py
index a39fd7c8f..40b6ff882 100644
--- a/archaeological_finds/migrations/0102_link_apps.py
+++ b/archaeological_finds/migrations/0102_link_apps.py
@@ -82,7 +82,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='treatment',
name='treatment_state',
- field=models.ForeignKey(default=archaeological_finds.models_treatments.TreatmentState.get_default, on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentState', verbose_name='State'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='archaeological_finds.TreatmentState', verbose_name='State'),
),
migrations.AddField(
model_name='treatment',
diff --git a/archaeological_finds/migrations/0103_auto_20200129_1944.py b/archaeological_finds/migrations/0103_auto_20200129_1944.py
index f127c71c8..3739a6de6 100644
--- a/archaeological_finds/migrations/0103_auto_20200129_1944.py
+++ b/archaeological_finds/migrations/0103_auto_20200129_1944.py
@@ -308,7 +308,6 @@ class Migration(migrations.Migration):
model_name='historicaltreatment',
name='treatment_state',
field=models.ForeignKey(blank=True, db_constraint=False,
- default=archaeological_finds.models_treatments.TreatmentState.get_default,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name='+',
diff --git a/archaeological_finds/migrations/0109_auto_20220328_1222.py b/archaeological_finds/migrations/0109_auto_20220328_1222.py
index abbae69a4..a451d8142 100644
--- a/archaeological_finds/migrations/0109_auto_20220328_1222.py
+++ b/archaeological_finds/migrations/0109_auto_20220328_1222.py
@@ -157,7 +157,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='treatment',
name='treatment_state',
- field=models.ForeignKey(default=archaeological_finds.models_treatments.TreatmentState.get_default, on_delete=django.db.models.deletion.PROTECT, to='archaeological_finds.TreatmentState', verbose_name='State'),
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='archaeological_finds.TreatmentState', verbose_name='State'),
),
migrations.AlterField(
model_name='treatmentfile',
diff --git a/archaeological_finds/migrations/0136_treatment_status_refactoring.py b/archaeological_finds/migrations/0136_treatment_status_refactoring.py
new file mode 100644
index 000000000..987b995af
--- /dev/null
+++ b/archaeological_finds/migrations/0136_treatment_status_refactoring.py
@@ -0,0 +1,83 @@
+# Generated by Django 2.2.28 on 2025-02-21 14:00
+
+import archaeological_finds.models_treatments
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import ishtar_common.models_common
+import re
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_finds', '0135_exhibition_description'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='TreatmentInputStatus',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('label', models.TextField(verbose_name='Label')),
+ ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')),
+ ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
+ ('available', models.BooleanField(default=True, verbose_name='Available')),
+ ('order', models.IntegerField(default=10, verbose_name='Order')),
+ ('executed', models.BooleanField(default=False, verbose_name='Treatment is executed')),
+ ],
+ options={
+ 'verbose_name': 'Treatment - Input status type',
+ 'verbose_name_plural': 'Treatment - Input status types',
+ 'ordering': ('order', 'label'),
+ },
+ bases=(ishtar_common.models_common.Cached, models.Model),
+ ),
+ migrations.CreateModel(
+ name='TreatmentStatus',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('label', models.TextField(verbose_name='Label')),
+ ('txt_idx', models.TextField(help_text='The slug is the standardized version of the name. It contains only lowercase letters, numbers and hyphens. Each slug must be unique.', unique=True, validators=[django.core.validators.RegexValidator(re.compile('^[-a-zA-Z0-9_]+\\Z'), "Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.", 'invalid')], verbose_name='Textual ID')),
+ ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
+ ('available', models.BooleanField(default=True, verbose_name='Available')),
+ ('order', models.IntegerField(default=10, verbose_name='Order')),
+ ],
+ options={
+ 'verbose_name': 'Treatment - Treatment status type',
+ 'verbose_name_plural': 'Treatment - Treatment status types',
+ 'ordering': ('order', 'label'),
+ },
+ bases=(ishtar_common.models_common.Cached, models.Model),
+ ),
+ migrations.AlterField(
+ model_name='historicaltreatment',
+ name='treatment_state',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.TreatmentState', verbose_name='State - deprecated'),
+ ),
+ migrations.AlterField(
+ model_name='treatment',
+ name='treatment_state',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='archaeological_finds.TreatmentState', verbose_name='State - deprecated'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatment',
+ name='input_status',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.TreatmentInputStatus', verbose_name='Input status'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatment',
+ name='treatment_status',
+ field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='archaeological_finds.TreatmentStatus', verbose_name='Treatment status'),
+ ),
+ migrations.AddField(
+ model_name='treatment',
+ name='input_status',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.TreatmentInputStatus', verbose_name='Input status'),
+ ),
+ migrations.AddField(
+ model_name='treatment',
+ name='treatment_status',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='archaeological_finds.TreatmentStatus', verbose_name='Treatment status'),
+ ),
+ ]
diff --git a/archaeological_finds/migrations/0137_data_migration_treatment_status_inputstatus.py b/archaeological_finds/migrations/0137_data_migration_treatment_status_inputstatus.py
new file mode 100644
index 000000000..b1f2077a3
--- /dev/null
+++ b/archaeological_finds/migrations/0137_data_migration_treatment_status_inputstatus.py
@@ -0,0 +1,51 @@
+import os
+
+from django.db import migrations
+from django.core.management import call_command
+
+
+def load_data(apps, __):
+ TreatmentStatus = apps.get_model("archaeological_finds", "treatmentstatus")
+ if not TreatmentStatus.objects.count():
+ migration = "0137_data_migration_treatmentstatus.json"
+ json_path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1] + [migration])
+ call_command("loaddata", json_path)
+
+ TreatmentInputStatus = apps.get_model("archaeological_finds", "treatmentinputstatus")
+ if not TreatmentInputStatus.objects.count():
+ migration = "0137_data_migration_treatmentinputstatus.json"
+ json_path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1] + [migration])
+ call_command("loaddata", json_path)
+
+ input_status_executed = TreatmentInputStatus.objects.filter(executed=True).all()[0]
+ input_status_draft = TreatmentInputStatus.objects.filter(executed=False).all()[0]
+
+ Treatment = apps.get_model("archaeological_finds", "treatment")
+ try:
+ TreatmentState = apps.get_model("archaeological_finds", "treatmentstate")
+ except LookupError:
+ # treatment state model deleted
+ return
+ for treatment_state in TreatmentState.objects.all():
+ q = TreatmentStatus.objects.filter(txt_idx=treatment_state.txt_idx)
+ if not q.exists():
+ print(f"Equivalence for treatment state: '{treatment_state.txt_idx}' not found")
+ continue
+ equiv = q.all()[0]
+ q = Treatment.objects.filter(treatment_state=treatment_state)
+ q.update(treatment_status=equiv)
+ if treatment_state.executed:
+ q.update(input_status=input_status_executed)
+ else:
+ q.update(input_status=input_status_draft)
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_finds', '0136_treatment_status_refactoring'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_data)
+ ]
diff --git a/archaeological_finds/migrations/0137_data_migration_treatmentinputstatus.json b/archaeological_finds/migrations/0137_data_migration_treatmentinputstatus.json
new file mode 100644
index 000000000..100dee461
--- /dev/null
+++ b/archaeological_finds/migrations/0137_data_migration_treatmentinputstatus.json
@@ -0,0 +1,24 @@
+[
+{
+ "model": "archaeological_finds.treatmentinputstatus",
+ "fields": {
+ "label": "Brouillon",
+ "txt_idx": "draft",
+ "comment": "",
+ "available": true,
+ "order": 10,
+ "executed": false
+ }
+},
+{
+ "model": "archaeological_finds.treatmentinputstatus",
+ "fields": {
+ "label": "Valid\u00e9",
+ "txt_idx": "validated",
+ "comment": "",
+ "available": true,
+ "order": 20,
+ "executed": true
+ }
+}
+]
diff --git a/archaeological_finds/migrations/0137_data_migration_treatmentstatus.json b/archaeological_finds/migrations/0137_data_migration_treatmentstatus.json
new file mode 100644
index 000000000..28f725d8a
--- /dev/null
+++ b/archaeological_finds/migrations/0137_data_migration_treatmentstatus.json
@@ -0,0 +1,62 @@
+[
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "Pr\u00e9vu",
+ "txt_idx": "planned",
+ "comment": "",
+ "available": true,
+ "order": 30
+ }
+},
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "En cours",
+ "txt_idx": "in-progress",
+ "comment": "",
+ "available": true,
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "Achev\u00e9",
+ "txt_idx": "completed",
+ "comment": "",
+ "available": true,
+ "order": 20
+ }
+},
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "Inconnu",
+ "txt_idx": "unknown",
+ "comment": "",
+ "available": true,
+ "order": 60
+ }
+},
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "\u00c0 confirmer",
+ "txt_idx": "to-be-confirmed",
+ "comment": "",
+ "available": true,
+ "order": 40
+ }
+},
+{
+ "model": "archaeological_finds.treatmentstatus",
+ "fields": {
+ "label": "Abandonn\u00e9",
+ "txt_idx": "cancelled",
+ "comment": "",
+ "available": true,
+ "order": 50
+ }
+}
+]
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index 90ca4bffd..c03e17f18 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -44,7 +44,9 @@ from archaeological_finds.models_treatments import (
FindUpstreamTreatments,
TreatmentFile,
TreatmentFileType,
- TreatmentState,
+ TreatmentInputStatus,
+ TreatmentState, # deprecated
+ TreatmentStatus,
)
__all__ = [
@@ -90,6 +92,8 @@ __all__ = [
"TreatmentEmergencyType",
"TreatmentFile",
"TreatmentFileType",
- "TreatmentType",
+ "TreatmentInputStatus",
+ "TreatmentStatus",
"TreatmentState",
+ "TreatmentType",
]
diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py
index 81b1df7df..0c684d98a 100644
--- a/archaeological_finds/models_treatments.py
+++ b/archaeological_finds/models_treatments.py
@@ -41,22 +41,23 @@ from archaeological_context_records.models import Dating
from archaeological_warehouse.models import Warehouse, Container
from ishtar_common.model_managers import ExternalIdManager
from ishtar_common.models import (
+ BaseHistorizedItem,
+ DashboardFormItem,
Document,
+ document_attached_changed,
+ DocumentItem,
GeneralType,
+ HistoryModel,
ImageModel,
- BaseHistorizedItem,
+ MainItem,
+ OrderedType,
+ Organization,
OwnPerms,
Person,
- Organization,
- ValueGetter,
post_save_cache,
- ShortMenuItem,
- DashboardFormItem,
- document_attached_changed,
- MainItem,
- HistoryModel,
SearchVectorConfig,
- DocumentItem,
+ ShortMenuItem,
+ ValueGetter,
)
from ishtar_common.models_common import CompleteIdentifierItem, HistoricalRecords
from ishtar_common.utils import (
@@ -73,8 +74,25 @@ class TreatmentState(GeneralType):
order = models.IntegerField(verbose_name=_("Order"), default=10)
class Meta:
- verbose_name = _("Treatment state type")
- verbose_name_plural = _("Treatment state types")
+ verbose_name = _("Treatment state type - deprecated")
+ verbose_name_plural = _("Treatment state types - deprecated")
+ ordering = (
+ "order",
+ "label",
+ )
+ ADMIN_SECTION = _("Treatments")
+
+
+post_save.connect(post_save_cache, sender=TreatmentState)
+post_delete.connect(post_save_cache, sender=TreatmentState)
+
+
+class TreatmentInputStatus(OrderedType):
+ executed = models.BooleanField(_("Treatment is executed"), default=False)
+
+ class Meta:
+ verbose_name = _("Treatment - Input status type")
+ verbose_name_plural = _("Treatment - Input status types")
ordering = (
"order",
"label",
@@ -83,23 +101,47 @@ class TreatmentState(GeneralType):
@classmethod
def get_default(cls):
- q = cls.objects.filter(executed=True)
+ q = cls.objects.filter(executed=False)
if not q.count():
return None
return q.all()[0].pk
@classmethod
+ def get_validated_state(cls):
+ treat_state, __ = cls.objects.get_or_create(
+ txt_idx='validated',
+ defaults={
+ 'label': _("Validated"), 'executed': True,
+ 'available': True})
+ return treat_state
+
+
+post_save.connect(post_save_cache, sender=TreatmentInputStatus)
+post_delete.connect(post_save_cache, sender=TreatmentInputStatus)
+
+
+class TreatmentStatus(OrderedType):
+ class Meta:
+ verbose_name = _("Treatment - Treatment status type")
+ verbose_name_plural = _("Treatment - Treatment status types")
+ ordering = (
+ "order",
+ "label",
+ )
+ ADMIN_SECTION = _("Treatments")
+
+ @classmethod
def get_completed_state(cls):
treat_state, __ = cls.objects.get_or_create(
txt_idx='completed',
defaults={
- 'label': _("Completed"), 'executed': True,
+ 'label': _("Completed"),
'available': True})
return treat_state
-post_save.connect(post_save_cache, sender=TreatmentState)
-post_delete.connect(post_save_cache, sender=TreatmentState)
+post_save.connect(post_save_cache, sender=TreatmentStatus)
+post_delete.connect(post_save_cache, sender=TreatmentStatus)
class AssociatedFindBasket:
@@ -171,7 +213,7 @@ class Treatment(
"year",
"index",
"treatment_types__label",
- "treatment_state__label",
+ "treatment_status__label",
"label",
"scientific_monitoring_manager__cached_label",
"person__cached_label",
@@ -195,8 +237,8 @@ class Treatment(
"downstream_cached_label": _("Downstream find"),
"upstream_cached_label": _("Upstream find"),
"treatment_types__label": _("Type"),
- "treatment_state__label": _("State"),
- "person__cached_label": _("Responsible"),
+ "treatment_status__label": _("State"),
+ "person__cached_label": _("Responsible of the treatment"),
"scientific_monitoring_manager__cached_label": _(
"Scientific monitoring manager"
),
@@ -232,6 +274,26 @@ class Treatment(
"scientific_monitoring_manager__cached_label__iexact",
related_name="scientific_monitoring_manager"
),
+ "input_status": SearchAltName(
+ pgettext_lazy("key for text search", "input-status"),
+ "input_status__label__iexact",
+ ),
+ "treatment_status": SearchAltName(
+ pgettext_lazy("key for text search", "treatment-status"),
+ "treatment_status__label__iexact",
+ ),
+ "location": SearchAltName(
+ pgettext_lazy("key for text search", "location"),
+ "location__name__iexact",
+ ),
+ "person": SearchAltName(
+ pgettext_lazy("key for text search", "responsible-of-treatment"),
+ "person__cached_label__iexact",
+ ),
+ "organization": SearchAltName(
+ pgettext_lazy("key for text search", "organization"),
+ "organization__name__iexact",
+ ),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
ALT_NAMES.update(DocumentItem.ALT_NAMES)
@@ -242,7 +304,7 @@ class Treatment(
BASE_SEARCH_VECTORS = [
SearchVectorConfig("treatment_types__label"),
- SearchVectorConfig("treatment_state__label"),
+ SearchVectorConfig("treatment_status__label"),
SearchVectorConfig("label"),
SearchVectorConfig("goal", "local"),
SearchVectorConfig("external_id"),
@@ -294,10 +356,26 @@ class Treatment(
)
treatment_state = models.ForeignKey(
TreatmentState,
- verbose_name=_("State"),
- default=TreatmentState.get_default,
+ verbose_name=_("State - deprecated use input_status and treatment_status"),
+ blank=True,
+ null=True,
on_delete=models.PROTECT,
)
+ input_status = models.ForeignKey(
+ TreatmentInputStatus,
+ verbose_name=_("Input status"),
+ default=TreatmentInputStatus.get_default,
+ blank=True,
+ null=True,
+ on_delete=models.SET_NULL,
+ )
+ treatment_status = models.ForeignKey(
+ TreatmentStatus,
+ verbose_name=_("Treatment status"),
+ blank=True,
+ null=True,
+ on_delete=models.SET_NULL,
+ )
executed = models.BooleanField(_("Treatment have been executed"), default=False)
location = models.ForeignKey(
Warehouse,
@@ -311,7 +389,7 @@ class Treatment(
)
person = models.ForeignKey(
Person,
- verbose_name=_("Responsible"),
+ verbose_name=_("Responsible of the treatment"),
blank=True,
null=True,
on_delete=models.SET_NULL,
@@ -340,7 +418,7 @@ class Treatment(
description = models.TextField(_("Description"), blank=True, default="")
goal = models.TextField(_("Goal"), blank=True, default="")
start_date = models.DateField(_("Start date"), blank=True, null=True)
- end_date = models.DateField(_("Closing date"), blank=True, null=True)
+ end_date = models.DateField(_("End date"), blank=True, null=True)
creation_date = models.DateTimeField(default=datetime.datetime.now)
container = models.ForeignKey(
Container,
@@ -718,7 +796,7 @@ class Treatment(
super().save(*args, **kwargs)
# reinit cached values
self.clean_cache()
- to_be_executed = not self.executed and self.treatment_state.executed
+ to_be_executed = not self.executed and self.input_status.executed
updated = []
# baskets
@@ -1313,7 +1391,7 @@ class TreatmentFile(
blank=True,
null=True,
)
- end_date = models.DateField(_("Closing date"), null=True, blank=True)
+ end_date = models.DateField(_("End date"), null=True, blank=True)
creation_date = models.DateField(
_("Creation date"), default=datetime.date.today, blank=True, null=True
)
diff --git a/archaeological_finds/templates/ishtar/forms/exhibition_form.html b/archaeological_finds/templates/ishtar/forms/exhibition_form.html
new file mode 100644
index 000000000..56259b265
--- /dev/null
+++ b/archaeological_finds/templates/ishtar/forms/exhibition_form.html
@@ -0,0 +1,3 @@
+{% extends "ishtar/forms/base_form.html" %}
+{% load i18n inline_formset table_form from_dict %}
+
diff --git a/archaeological_finds/templates/ishtar/sheet_treatment.html b/archaeological_finds/templates/ishtar/sheet_treatment.html
index ac11d9b70..7fa2097f0 100644
--- a/archaeological_finds/templates/ishtar/sheet_treatment.html
+++ b/archaeological_finds/templates/ishtar/sheet_treatment.html
@@ -66,11 +66,6 @@
<p class="window-refs">{{ item.year|unlocalize }} - {{ item.index|unlocalize }}</p>
{% if item.external_id %}
<p class="window-refs">{{ item.external_id }}</p>{% endif %}
- {% if item.end_date %}
- <p class="window-refs">{% trans "Closed" context "Treatment" %} ({{item.end_date}})</p>
- {% else %}
- <p class="window-refs">{% trans "Active" context "Treatment" %}</p>
- {% endif %}
</div>
</div>
</div>
@@ -78,15 +73,15 @@
<div class="row">
{% field_flex_multiple_obj "Treatment type" item 'treatment_types' %}
- {% field_flex "State" item.treatment_state %}
+ {% field_flex _("Status") item.treatment_status %}
{% field_flex_detail "Associated request" item.file %}
{% field_flex_detail "Location" item.location %}
{% field_flex_detail "Container" item.container %}
{% field_flex_detail "Scientific monitoring manager" item.scientific_monitoring_manager %}
- {% field_flex_detail "Responsible" item.person %}
+ {% field_flex_detail _("Responsible of the treatment") item.person %}
{% field_flex_detail "Organization" item.organization %}
{% field_flex "Start date" item.start_date|date:"DATE_FORMAT" %}
- {% field_flex "Closing date" item.end_date|date:"DATE_FORMAT" %}
+ {% field_flex _("End date") item.end_date|date:"DATE_FORMAT" %}
{% field_flex "Estimated cost" item.estimated_cost|intcomma '' " "|add:CURRENCY %}
{% field_flex "Quoted cost" item.quoted_cost|intcomma '' " "|add:CURRENCY %}
{% field_flex "Realized cost" item.realized_cost|intcomma '' " "|add:CURRENCY %}
@@ -102,6 +97,7 @@
{% if item.history_creator or item.last_edition_date or item.created %}
<h3>{% trans "Sheet"%}</h3>
<div class="row">
+ {% field_flex _("Input status") item.input_status %}
{% include "ishtar/blocks/sheet_creation_section.html" %}
</div>
{% endif %}
diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py
index 6b5c1f1b1..2cf184561 100644
--- a/archaeological_finds/tests.py
+++ b/archaeological_finds/tests.py
@@ -573,20 +573,24 @@ class TreatmentWizardCreationTest(WizardTest, FindInit, TestCase):
loan.save()
self.form_datas[2].set("basetreatment", "treatment_type", loan.pk)
- planned, __ = models.TreatmentState.objects.get_or_create(
- txt_idx="planned", defaults={"executed": False, "label": "Planned"}
+ planned, __ = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="draft", defaults={"executed": False, "label": "Draft"}
)
planned.executed = False
planned.save()
- self.form_datas[0].set("basetreatment", "treatment_state", planned.pk)
+ self.form_datas[0].set("basetreatment", "input_status", planned.pk)
- completed, created = models.TreatmentState.objects.get_or_create(
- txt_idx="completed", defaults={"executed": True, "label": "Done"}
+ completed, created = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="validated", defaults={"executed": True, "label": "Validated"}
)
completed.executed = True
completed.save()
- self.form_datas[1].set("basetreatment", "treatment_state", completed.pk)
- self.form_datas[2].set("basetreatment", "treatment_state", completed.pk)
+ self.form_datas[1].set("basetreatment", "input_status", completed.pk)
+ self.form_datas[2].set("basetreatment", "input_status", completed.pk)
+
+ status = models.TreatmentStatus.objects.all()[0]
+ for form_data in self.form_datas:
+ form_data.set("basetreatment", "treatment_status", status.pk)
self.treatment_number = models.Treatment.objects.count()
@@ -2220,10 +2224,10 @@ class FindQATest(FindInit, TestCase):
def test_duplicate(self):
t1, __ = models.Treatment.objects.get_or_create(
- label="Treatment 1", treatment_state=models.TreatmentState.objects.all()[0]
+ label="Treatment 1", input_status=models.TreatmentInputStatus.objects.all()[0]
)
t2, __ = models.Treatment.objects.get_or_create(
- label="Treatment 1", treatment_state=models.TreatmentState.objects.all()[0]
+ label="Treatment 2", input_status=models.TreatmentInputStatus.objects.all()[0]
)
find = self.finds[0]
default_desc = "Description for duplicate"
@@ -2778,13 +2782,13 @@ class TreatmentTest(FindInit, TestCase):
first_find = self.finds[0]
- completed, created = models.TreatmentState.objects.get_or_create(
- txt_idx="completed", defaults={"executed": True, "label": "Done"}
+ completed, created = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="validated", defaults={"executed": True, "label": "Validated"}
)
completed.executed = True
completed.save()
- treatment.treatment_state = completed
+ treatment.input_status = completed
treatment.save(
user=self.get_default_user(),
items=self.basket,
@@ -2833,13 +2837,13 @@ class TreatmentTest(FindInit, TestCase):
treatment = models.Treatment()
initial_find = self.finds[0]
- completed, created = models.TreatmentState.objects.get_or_create(
- txt_idx="completed", defaults={"executed": True, "label": "Done"}
+ completed, created = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="validated", defaults={"executed": True, "label": "Validated"}
)
completed.executed = True
completed.save()
- treatment.treatment_state = completed
+ treatment.input_status = completed
treatment.save(
user=self.get_default_user(),
items=self.basket,
@@ -2869,13 +2873,13 @@ class TreatmentTest(FindInit, TestCase):
treatment = models.Treatment()
initial_find = self.finds[0]
- completed, created = models.TreatmentState.objects.get_or_create(
- txt_idx="completed", defaults={"executed": True, "label": "Done"}
+ completed, created = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="validated", defaults={"executed": True, "label": "Validated"}
)
completed.executed = True
completed.save()
- treatment.treatment_state = completed
+ treatment.input_status = completed
treatment.save(
user=self.get_default_user(),
items=self.basket,
@@ -2909,13 +2913,13 @@ class TreatmentTest(FindInit, TestCase):
treatment = models.Treatment()
initial_find = self.finds[0]
- completed, created = models.TreatmentState.objects.get_or_create(
- txt_idx="completed", defaults={"executed": True, "label": "Done"}
+ completed, created = models.TreatmentInputStatus.objects.get_or_create(
+ txt_idx="validated", defaults={"executed": True, "label": "Validated"}
)
completed.executed = True
completed.save()
- treatment.treatment_state = completed
+ treatment.input_status = completed
treatment.save(
user=self.get_default_user(),
items=self.basket,
@@ -2973,7 +2977,7 @@ class AutocompleteTest(AutocompleteTestBase, TestCase):
def create_treatment(self, base_name):
item, __ = models.Treatment.objects.get_or_create(
- label=base_name, treatment_state=models.TreatmentState.objects.all()[0]
+ label=base_name, input_status=models.TreatmentInputStatus.objects.all()[0]
)
return item, None