summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/fixtures/initial_importtypes-tests-fr.json4
-rw-r--r--ishtar_common/migrations/0270_gis_import_key_init.py11
-rw-r--r--ishtar_common/migrations/0272_ishtarsiteprofile_dating_external_id.py18
-rw-r--r--ishtar_common/models.py22
-rw-r--r--ishtar_common/models_common.py22
-rw-r--r--ishtar_common/templates/ishtar/blocks/sheet_dating_list.html6
-rw-r--r--ishtar_common/utils.py27
-rw-r--r--ishtar_common/utils_migrations.py39
8 files changed, 129 insertions, 20 deletions
diff --git a/ishtar_common/fixtures/initial_importtypes-tests-fr.json b/ishtar_common/fixtures/initial_importtypes-tests-fr.json
index e8bdb40f9..244516a25 100644
--- a/ishtar_common/fixtures/initial_importtypes-tests-fr.json
+++ b/ishtar_common/fixtures/initial_importtypes-tests-fr.json
@@ -1349,13 +1349,13 @@
"mcc-ue",
13
],
- "target": "datings__period",
+ "target": "periods",
"formater_type": [
"TypeFormater",
"archaeological_operations.models.Period",
"&"
],
- "force_new": true,
+ "force_new": false,
"concat": false,
"concat_str": null,
"comment": ""
diff --git a/ishtar_common/migrations/0270_gis_import_key_init.py b/ishtar_common/migrations/0270_gis_import_key_init.py
index ed3d8e568..030db3a25 100644
--- a/ishtar_common/migrations/0270_gis_import_key_init.py
+++ b/ishtar_common/migrations/0270_gis_import_key_init.py
@@ -1,16 +1,17 @@
+import sys
from django.db import migrations
-from ishtar_common.utils_migrations import update_import_key
+from ishtar_common.utils_migrations import update_import_key, print_progress
def update_importkey(apps, __):
updated = 0
GeoVectorData = apps.get_model("ishtar_common", "geovectordata")
- for data in GeoVectorData.objects.all():
+ total = GeoVectorData.objects.count()
+ sys.stdout.write("\n")
+ for idx, data in enumerate(GeoVectorData.objects.all()):
+ print_progress(idx, total)
updated += 1 if update_import_key(data) else 0
- if updated:
- print()
- print(f"* {updated} GeoVectorData import_key updated")
class Migration(migrations.Migration):
diff --git a/ishtar_common/migrations/0272_ishtarsiteprofile_dating_external_id.py b/ishtar_common/migrations/0272_ishtarsiteprofile_dating_external_id.py
new file mode 100644
index 000000000..a3c8f278a
--- /dev/null
+++ b/ishtar_common/migrations/0272_ishtarsiteprofile_dating_external_id.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.19 on 2025-10-29 10:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0271_import_import_immediatly'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='ishtarsiteprofile',
+ name='dating_external_id',
+ field=models.TextField(default='{{parent_external_id}}-{% if reference %}{{reference}}{% else %}{{auto_id}}{% endif %}', help_text='Formula to manage dating external ID. Change this with care. With incorrect formula, the application might be unusable and import of external data can be destructive.', verbose_name='Dating external id'),
+ ),
+ ]
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 0ffb24882..aa9224be7 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -423,11 +423,14 @@ class HistoryModel(models.Model):
models = import_module(models)
model = getattr(models, self.__class__.__name__[len("Historical"):])
field = getattr(model, key)
- if hasattr(field, "rel"):
- field = field.rel
+ if not hasattr(field, "reverse"):
+ related_model = field.field.model
else:
- field = field.remote_field
- related_model = field.model
+ if hasattr(field, "rel"):
+ field = field.rel
+ else:
+ field = field.remote_field
+ related_model = field.model
return related_model.history_decompress(self.history_m2m[key], create=create)
@@ -1525,6 +1528,17 @@ class IshtarSiteProfile(models.Model, Cached):
"Formula to manage cached label. If not set a default formula is used."
),
)
+ dating_external_id = models.TextField(
+ _("Dating external id"),
+ default="{{parent_external_id}}-{% if reference %}{{reference}}"
+ "{% else %}{{auto_id}}{% endif %}",
+ help_text=_(
+ "Formula to manage dating external ID. "
+ "Change this with care. With incorrect formula, the "
+ "application might be unusable and import of external "
+ "data can be destructive."
+ ),
+ )
document_external_id = models.TextField(
_("Document external id"),
default="{index}",
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index be3e06848..821a89ac4 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -1891,9 +1891,25 @@ class BaseHistorizedItem(
new_item.history_m2m = saved_m2m
values = new_item.m2m_listing(hist_key, create=True) or []
hist_field = getattr(self, hist_key)
- hist_field.clear()
- for val in values:
- hist_field.add(val)
+ if hasattr(hist_field, "clear"):
+ hist_field.clear()
+ for val in values:
+ hist_field.add(val)
+ continue
+ # manage related field (not real m2m)
+ # # clear removed values
+ for current_value in hist_field.all():
+ current_values = current_value.history_compress()
+ has_value = False
+ # clear non existant
+ for idx, value in enumerate(values[:]):
+ if value.history_compress() == current_values:
+ values.pop(idx) # remove existing to not create them
+ has_value = True
+ break
+ if has_value:
+ continue
+ current_value.delete()
# force label regeneration
self._cached_label_checked = False
self.save()
diff --git a/ishtar_common/templates/ishtar/blocks/sheet_dating_list.html b/ishtar_common/templates/ishtar/blocks/sheet_dating_list.html
index 6135bbf77..e79d9f201 100644
--- a/ishtar_common/templates/ishtar/blocks/sheet_dating_list.html
+++ b/ishtar_common/templates/ishtar/blocks/sheet_dating_list.html
@@ -1,6 +1,7 @@
{% load i18n %}
<table id='{{window_id}}-datings' class="table table-striped">
<tr>
+ <th>{% trans "Reference" %}</th>
<th>{% trans "Chronological period" %}</th>
<th>{% trans "Start date" %}</th>
<th>{% trans "End date" %}</th>
@@ -11,7 +12,10 @@
{% for dating in dating_list %}
<tr>
<td>
- {{dating.period}}
+ {{dating.reference|default:"-"}}
+ </td>
+ <td>
+ {{dating.period|default:"-"}}
</td>
<td>
{{dating.start_date|default_if_none:"-"}}
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index 937b9bb99..bd79814e9 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -2373,11 +2373,7 @@ def get_urls_for_model(
return urls
-def m2m_historization_changed(sender, **kwargs):
- obj = kwargs.get("instance", None)
- if not obj:
- return
- obj._queue = kwargs.get("queue", settings.CELERY_DEFAULT_QUEUE)
+def get_m2m_values(obj):
hist_values = obj.history_m2m or {}
for attr in obj.HISTORICAL_M2M:
values = []
@@ -2387,6 +2383,12 @@ def m2m_historization_changed(sender, **kwargs):
values.append(value.history_compress())
hist_values[attr] = values
obj.history_m2m = hist_values
+ return hist_values
+
+
+def manage_m2m(obj, kwargs):
+ obj._queue = kwargs.get("queue", settings.CELERY_DEFAULT_QUEUE)
+ hist_values = get_m2m_values(obj)
if getattr(obj, "skip_history_when_saving", False):
# assume the last modifier is good...
q = obj.history.filter(
@@ -2403,6 +2405,21 @@ def m2m_historization_changed(sender, **kwargs):
obj.save()
+def related_historization_changed(sender, **kwargs):
+ rel_obj = kwargs.get("instance", None)
+ if not rel_obj or not getattr(rel_obj, "CURRENT_MODEL_ATTR", None):
+ return
+ obj = getattr(rel_obj, rel_obj.CURRENT_MODEL_ATTR)
+ manage_m2m(obj, kwargs)
+
+
+def m2m_historization_changed(sender, **kwargs):
+ obj = kwargs.get("instance", None)
+ if not obj:
+ return
+ manage_m2m(obj, kwargs)
+
+
def max_size_help(help_for_doc=False):
max_size = settings.MAX_UPLOAD_SIZE
if help_for_doc:
diff --git a/ishtar_common/utils_migrations.py b/ishtar_common/utils_migrations.py
index 6d75ff885..04a6d9827 100644
--- a/ishtar_common/utils_migrations.py
+++ b/ishtar_common/utils_migrations.py
@@ -10,6 +10,9 @@ from django.core.management import call_command
from django.db import connection
from django.utils.translation import gettext_lazy
+from ishtar_common.utils import BColors
+
+
HOMEPAGE_TITLE = gettext_lazy("Welcome in Ishtar, open source software for management and inventory of archaeological data")
@@ -233,3 +236,39 @@ def update_import_key(geovectordata): # 0267_gis_import_key
GeoVectorData.objects.filter(pk=geovectordata.id).update(
import_key=import_key)
return True
+
+
+def print_progress(idx, total):
+ sys.stdout.write(f"\r {BColors.OKBLUE}→ Migration {idx+1}/{total}{BColors.ENDC}")
+
+
+def migrate_dating_periods(apps, model_dating, model, dating_attr):
+ if not hasattr(model, "datings_old"): # migration is not relevant anymore
+ return
+ q = model.objects.filter(datings_old__pk__isnull=False)
+ if not q.count():
+ return
+ period_attr = ["start_date", "end_date", "dating_type", "quality", "precise_dating"]
+ full_period_attr = period_attr + ["period"]
+ sys.stdout.write("\n")
+ total = q.count()
+ for idx, item in enumerate(q.all()):
+ print_progress(idx, total)
+ for idx_dating, dating in enumerate(item.datings_old.all()):
+ if not dating.period:
+ # should not occur as for old dating period was required
+ continue
+ item.periods.add(dating.period)
+ has_more = False
+ for attr in period_attr:
+ if hasattr(dating, attr) and getattr(dating, attr):
+ has_more = True
+ break
+ if not has_more:
+ # do not recreate a new dating, it is not relevant anymore
+ continue
+ new_attrs = dict((k, getattr(dating, k)) for k in full_period_attr)
+ new_attrs[dating_attr] = item
+ new_attrs["external_id"] = f"{item.external_id}-{idx_dating + 1}"
+ model_dating.objects.create(**new_attrs)
+