summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/migrations/0102_link_apps.py4
-rw-r--r--archaeological_context_records/migrations/0113_auto_20231113_1610.py38
-rw-r--r--archaeological_context_records/models.py20
-rw-r--r--archaeological_context_records/tests.py12
-rw-r--r--archaeological_files/migrations/0112_auto_20231113_1610.py33
-rw-r--r--archaeological_finds/migrations/0113_auto_20231113_1610.py103
-rw-r--r--archaeological_operations/migrations/0113_auto_20231114_1058.py103
-rw-r--r--archaeological_operations/models.py45
-rw-r--r--archaeological_operations/tests.py9
-rw-r--r--archaeological_warehouse/migrations/0119_auto_20231113_1611.py53
-rw-r--r--ishtar_common/data_importer.py11
-rw-r--r--ishtar_common/migrations/0230_auto_20231114_1334.py128
-rw-r--r--ishtar_common/models.py24
-rw-r--r--ishtar_common/models_common.py11
-rw-r--r--ishtar_common/utils.py27
-rw-r--r--locale/fr/LC_MESSAGES/django.po3
16 files changed, 561 insertions, 63 deletions
diff --git a/archaeological_context_records/migrations/0102_link_apps.py b/archaeological_context_records/migrations/0102_link_apps.py
index d885acf32..47904b860 100644
--- a/archaeological_context_records/migrations/0102_link_apps.py
+++ b/archaeological_context_records/migrations/0102_link_apps.py
@@ -191,8 +191,4 @@ class Migration(migrations.Migration):
model_name='contextrecord',
index=django.contrib.postgres.indexes.GinIndex(fields=['data'], name='archaeologi_data_1c3119_gin'),
),
- migrations.RunSQL(
- archaeological_context_records.models.CRBulkView.DELETE_SQL),
- migrations.RunSQL(
- archaeological_context_records.models.CRBulkView.CREATE_SQL),
]
diff --git a/archaeological_context_records/migrations/0113_auto_20231113_1610.py b/archaeological_context_records/migrations/0113_auto_20231113_1610.py
new file mode 100644
index 000000000..2d42f2c21
--- /dev/null
+++ b/archaeological_context_records/migrations/0113_auto_20231113_1610.py
@@ -0,0 +1,38 @@
+# Generated by Django 2.2.24 on 2023-11-13 16:10
+
+from django.db import migrations, models
+
+DELETE_SQL = """
+ DROP VIEW IF EXISTS context_records_cached_label_bulk_update;
+"""
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_context_records', '0112_migrate_created'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='contextrecord',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='contextrecord',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontextrecord',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.RunSQL(DELETE_SQL)
+ ]
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index 985390861..2f9737c14 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -378,26 +378,6 @@ post_save.connect(post_save_cache, sender=DocumentationType)
post_delete.connect(post_save_cache, sender=DocumentationType)
-class CRBulkView(object):
- CREATE_SQL = """
- CREATE VIEW context_records_cached_label_bulk_update
- AS (
- SELECT cr.id AS id, ope.code_patriarche AS main_code,
- ope.year AS year,
- ope.operation_code AS ope_code,
- parcel.section AS section,
- parcel.parcel_number AS number, cr.label AS label
- FROM archaeological_context_records_contextrecord AS cr
- INNER JOIN archaeological_operations_operation ope
- ON ope.id = cr.operation_id
- INNER JOIN archaeological_operations_parcel parcel
- ON cr.parcel_id = parcel.id
- );"""
- DELETE_SQL = """
- DROP VIEW IF EXISTS context_records_cached_label_bulk_update;
- """
-
-
class GeographicSubTownItem(GeoItem):
UPPER_GEO = []
diff --git a/archaeological_context_records/tests.py b/archaeological_context_records/tests.py
index 7a0b41f50..0d838f3ea 100644
--- a/archaeological_context_records/tests.py
+++ b/archaeological_context_records/tests.py
@@ -467,11 +467,10 @@ class ContextRecordTest(ContextRecordInit, TestCase):
cr = self.create_context_record()[0]
cr_pk = cr.pk
self.assertIsNotNone(cr.cached_label)
- # OA1 | A | 1 | CR 1
- ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ")
+ # OA1 | 12345 | A1 | CR 1
+ ope_id, town_num, parcel_sec_nb, cr_label = cr.cached_label.split(" | ")
self.assertEqual(ope_id, "OA1")
- self.assertEqual(parcel_sec, cr.parcel.section)
- self.assertEqual(parcel_nb, cr.parcel.parcel_number)
+ self.assertEqual(parcel_sec_nb, cr.parcel.section + cr.parcel.parcel_number)
self.assertEqual(cr_label, cr.label)
new_lbl = "UE 2"
@@ -489,9 +488,8 @@ class ContextRecordTest(ContextRecordInit, TestCase):
parcel.save()
cr = models.ContextRecord.objects.get(pk=cr_pk)
self.assertIsNotNone(cr.cached_label)
- ope_id, parcel_sec, parcel_nb, cr_label = cr.cached_label.split(" | ")
- self.assertEqual(parcel_sec, new_sec)
- self.assertEqual(parcel_nb, new_nb)
+ ope_id, town_num, parcel_sec_nb, cr_label = cr.cached_label.split(" | ")
+ self.assertEqual(parcel_sec_nb, new_sec + new_nb)
cr.operation.year = 2017
cr.operation.save()
diff --git a/archaeological_files/migrations/0112_auto_20231113_1610.py b/archaeological_files/migrations/0112_auto_20231113_1610.py
new file mode 100644
index 000000000..c3582edcd
--- /dev/null
+++ b/archaeological_files/migrations/0112_auto_20231113_1610.py
@@ -0,0 +1,33 @@
+# Generated by Django 2.2.24 on 2023-11-13 16:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_files', '0111_migrate_created'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='file',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='file',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalfile',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalfile',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ ]
diff --git a/archaeological_finds/migrations/0113_auto_20231113_1610.py b/archaeological_finds/migrations/0113_auto_20231113_1610.py
new file mode 100644
index 000000000..437b5f2bd
--- /dev/null
+++ b/archaeological_finds/migrations/0113_auto_20231113_1610.py
@@ -0,0 +1,103 @@
+# Generated by Django 2.2.24 on 2023-11-13 16:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_finds', '0112_migrate_created'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='basefind',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='basefind',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='find',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='find',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalbasefind',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalbasefind',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalfind',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalfind',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatment',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatment',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatmentfile',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicaltreatmentfile',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='property',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='property',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='treatment',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='treatment',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='treatmentfile',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='treatmentfile',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ ]
diff --git a/archaeological_operations/migrations/0113_auto_20231114_1058.py b/archaeological_operations/migrations/0113_auto_20231114_1058.py
new file mode 100644
index 000000000..3b1bb0c55
--- /dev/null
+++ b/archaeological_operations/migrations/0113_auto_20231114_1058.py
@@ -0,0 +1,103 @@
+# Generated by Django 2.2.24 on 2023-11-14 10:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_operations', '0112_migrate_created'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='administrativeact',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='administrativeact',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='archaeologicalsite',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicaladministrativeact',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicaladministrativeact',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalarchaeologicalsite',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicaloperation',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='parcel',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='parcel',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='parcelowner',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='parcelowner',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AlterField(
+ model_name='historicaloperation',
+ name='cached_label',
+ field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached label'),
+ ),
+ migrations.AlterField(
+ model_name='operation',
+ name='cached_label',
+ field=models.TextField(blank=True, default='', help_text='Generated automatically - do not edit', verbose_name='Cached label'),
+ ),
+ ]
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 4f0112710..3ebf98349 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -1113,10 +1113,10 @@ class Operation(
"scientist": {("person_types", PersonType): ("head_scientist", "sra_agent")},
}
CACHED_LABELS = [
- "cached_label",
"cached_towns_label",
"cached_periods",
"cached_remains",
+ "cached_label",
]
objects = UUIDModelManager()
@@ -1296,7 +1296,7 @@ class Operation(
"towns__numero_insee__startswith": "_get_department_code",
}
- DOWN_MODEL_UPDATE = ["context_record"]
+ DOWN_MODEL_UPDATE = ["parcels", "context_record"]
HISTORICAL_M2M = [
"remains",
@@ -1532,6 +1532,12 @@ class Operation(
related_name="minutes_writer",
on_delete=models.SET_NULL,
)
+ cached_label = models.TextField(
+ _("Cached label"),
+ blank=True,
+ default="",
+ help_text=_("Generated automatically - do not edit"),
+ )
cached_towns_label = models.TextField(
_("Cached town label"),
blank=True,
@@ -1676,6 +1682,10 @@ class Operation(
return self.code_patriarche
@property
+ def auto_external_id(self):
+ return False
+
+ @property
def short_label(self):
if settings.COUNTRY == "fr":
return self.reference
@@ -1697,7 +1707,7 @@ class Operation(
return [town.label_with_areas for town in self.towns.all()]
def towns_label(self):
- return " ; ".join(self.towns_codes())
+ return " ; ".join([town.name for town in self.towns.all()])
def has_finds(self):
from archaeological_finds.models import BaseFind
@@ -1762,7 +1772,7 @@ class Operation(
return cached_label
def _generate_cached_towns_label(self):
- return self.towns_label() or "-"
+ return self.towns_label() or _("No associated town")
def _generate_cached_remains(self):
return " & ".join([str(remain) for remain in self.remains.all()]) or "-"
@@ -1773,10 +1783,6 @@ class Operation(
def _get_associated_cached_labels(self):
return list(self.context_record.all())
- def _cached_labels_bulk_update(self):
- self.context_record.model.cached_label_bulk_update(operation_id=self.pk)
- return True
-
def _get_base_image_path(self):
return "{}/{}/{}".format(self.SLUG, self.year, self.reference)
@@ -3304,8 +3310,27 @@ def parcel_post_save(sender, **kwargs):
parcel.save()
return
- if parcel.context_record.count():
- parcel.context_record.model.cached_label_bulk_update(parcel_id=parcel.id)
+ cr_external_id_formula = get_current_profile().context_record_external_id
+ has_ext_id = "{parcel__external_id}" in cr_external_id_formula
+ has_nb = "{parcel__parcel_number}" in cr_external_id_formula
+ has_section = "{parcel__section}" in cr_external_id_formula
+
+ q = parcel.context_record
+ if q.count():
+ # check if first context record is affected
+ cr = q.all()[0]
+ need_update = not has_nb and not has_section and not has_ext_id # cannot check easily
+ if has_ext_id:
+ need_update += parcel.external_id not in cr.external_id
+ if has_section and parcel.section:
+ need_update += parcel.section not in cr.external_id
+ if has_nb and parcel.parcel_number:
+ need_update += parcel.parcel_number not in cr.external_id
+ if need_update:
+ for cr in q.all():
+ cr.no_post_process()
+ cr._cached_label_checked = False
+ cr.save()
if (
parcel.operation
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py
index 1c2623389..331c24659 100644
--- a/archaeological_operations/tests.py
+++ b/archaeological_operations/tests.py
@@ -2153,16 +2153,17 @@ class OperationTest(TestCase, OperationInitTest):
operation = self.operations[0]
self.assertIsNotNone(operation.cached_label)
town, ope_id = operation.cached_label.split(" | ")
- self.assertIn(town, ("Intercommunal", "Multi-town"))
- self.assertEqual(ope_id, "OA1 - OP2010-1")
+ self.assertIn(town, ("Pas de commune associée", "No associated town"))
+ self.assertEqual(ope_id, "OA1")
operation = models.Operation.objects.get(pk=operation.pk)
operation.year = 2011
+ operation.code_patriarche = ""
operation.save()
operation.towns.add(self.towns[0])
operation = models.Operation.objects.get(pk=operation.pk)
self.assertIsNotNone(operation.cached_label)
town, ope_id = operation.cached_label.split(" | ")
- self.assertEqual(ope_id, "OA1 - OP2011-1")
+ self.assertEqual(ope_id, "OP2011-1")
self.assertEqual(town, self.towns[0].name)
def test_search_vector_update(self):
@@ -3834,7 +3835,7 @@ class OperationWizardModifTest(WizardTest, OperationInitTest, TestCase):
operation = models.Operation.objects.get(pk=test_object.operations[0].pk)
town_str = town_2.name
test_object.assertEqual(
- operation.complete_identifier[:len(town_str)], town_str
+ operation.cached_label[:len(town_str)], town_str
)
self.form_datas[0].extra_tests = [post_first_wizard]
diff --git a/archaeological_warehouse/migrations/0119_auto_20231113_1611.py b/archaeological_warehouse/migrations/0119_auto_20231113_1611.py
new file mode 100644
index 000000000..b21b4e823
--- /dev/null
+++ b/archaeological_warehouse/migrations/0119_auto_20231113_1611.py
@@ -0,0 +1,53 @@
+# Generated by Django 2.2.24 on 2023-11-13 16:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_warehouse', '0118_auto_20230807_1106'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='container',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='container',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontainer',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalcontainer',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalwarehouse',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalwarehouse',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='warehouse',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='warehouse',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ ]
diff --git a/ishtar_common/data_importer.py b/ishtar_common/data_importer.py
index 8c46cadb6..0f447f957 100644
--- a/ishtar_common/data_importer.py
+++ b/ishtar_common/data_importer.py
@@ -873,12 +873,14 @@ class Importer(object):
self.import_instance.state = "PP"
self.import_instance.imported_line_numbers = ""
self.import_instance.save()
+ self.timestamp = int(datetime.datetime.now().timestamp())
for cls_pk, idx_line in self.post_save_items.items():
if self.import_instance and not self.line_to_process:
self.import_instance.add_imported_line(idx_line)
cls, pk = cls_pk
# force django based post-processing for the item
item = cls.objects.get(pk=pk)
+ item._timestamp = self.timestamp
item.save()
if hasattr(item, "RELATED_POST_PROCESS"):
for related_key in item.RELATED_POST_PROCESS:
@@ -892,6 +894,7 @@ class Importer(object):
for cls, pk in related_list.keys():
try:
item = cls.objects.get(pk=pk)
+ item._timestamp = self.timestamp
item.save()
if hasattr(item, "fix"):
# post save/m2m specific fix
@@ -1105,6 +1108,7 @@ class Importer(object):
return obj
def _line_processing(self, idx_line, line):
+ self.timestamp = int(datetime.datetime.now().timestamp())
for item in self.to_be_close:
item.close()
self.to_be_close = []
@@ -1212,6 +1216,7 @@ class Importer(object):
for k in data["defaults"]:
setattr(obj, k, data["defaults"][k])
obj._no_post_save = True
+ obj._timestamp = self.timestamp
obj.save()
self._add_to_post_save(obj.__class__, obj.pk, idx_line)
@@ -1250,6 +1255,7 @@ class Importer(object):
if item:
for k in geodata:
setattr(item, k, geodata[k])
+ item._timestamp = self.timestamp
item.save()
else:
item = GeoVectorData.objects.create(**geodata)
@@ -1260,6 +1266,7 @@ class Importer(object):
if self.import_instance and created:
item.imports.add(self.import_instance)
if self.MAIN_GEO:
+ obj._timestamp = self.timestamp
obj.main_geodata = item
obj._post_saved_geo = True
obj._no_move = True
@@ -1335,6 +1342,7 @@ class Importer(object):
for k in data["defaults"]:
setattr(t_obj, k, data["defaults"][k])
t_obj._no_post_save = True
+ t_obj._timestamp = self.timestamp
t_obj.save()
self._add_to_post_save(t_obj.__class__, t_obj.pk, idx_line)
if self.import_instance and hasattr(t_obj, "imports") and created:
@@ -1674,6 +1682,7 @@ class Importer(object):
changed = True
setattr(v, k, extra_fields[k])
if changed:
+ v._timestamp = self.timestamp
v.save()
for att, objs in m2m_m2ms:
if type(objs) not in (list, tuple):
@@ -2022,6 +2031,7 @@ class Importer(object):
else:
for k in updated_dct:
setattr(obj, k, updated_dct[k])
+ obj._timestamp = self.timestamp
obj.save()
if (
not self.simulate
@@ -2090,6 +2100,7 @@ class Importer(object):
self._add_to_post_save(v.__class__, v.pk, idx_line)
v._no_post_save = True
try:
+ v._timestamp = self.timestamp
v.save()
except DatabaseError as e:
raise IntegrityError(e.message)
diff --git a/ishtar_common/migrations/0230_auto_20231114_1334.py b/ishtar_common/migrations/0230_auto_20231114_1334.py
new file mode 100644
index 000000000..15da327d4
--- /dev/null
+++ b/ishtar_common/migrations/0230_auto_20231114_1334.py
@@ -0,0 +1,128 @@
+# Generated by Django 2.2.24 on 2023-11-14 13:34
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0229_auto_20230608_1303'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='document',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='document',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='geovectordata',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='geovectordata',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicaldocument',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicaldocument',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalorganization',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalorganization',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='historicalperson',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='historicalperson',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='organization',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='organization',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='person',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='person',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AddField(
+ model_name='town',
+ name='timestamp_geo',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp geo'),
+ ),
+ migrations.AddField(
+ model_name='town',
+ name='timestamp_label',
+ field=models.IntegerField(blank=True, null=True, verbose_name='Timestamp label'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='account_naming_style',
+ field=models.CharField(choices=[('NF', 'name.firstname'), ('FN', 'firstname.name')], default='FN', max_length=2, verbose_name='Naming style for accounts'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='basefind_cached_label',
+ field=models.TextField(blank=True, default='{context_record__cached_label} | {label}', help_text='Formula to manage cached label. If not set a default formula is used.', verbose_name='Base find cached label'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='contextrecord_cached_label',
+ field=models.TextField(default='{parcel__cached_label} | {label}', help_text='Formula to manage cached label. If not set a default formula is used.', verbose_name='Context record cached label'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='find_cached_label',
+ field=models.TextField(default='{get_first_base_find__context_record__operation__complete_identifier}-{index:0>5} | {label}', help_text='Formula to manage cached label. If not set a default formula is used.', verbose_name='Find cached label'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='operation_cached_label',
+ field=models.TextField(default='{{cached_towns_label}} | {% if code_patriarche %}OA{{code_patriarche}}{% else %}{% if operation_code and year %}OP{{year}}-{{operation_code}}{% endif %}{% endif %}', help_text='Formula to manage cached label. If not set a default formula is used.', verbose_name='Operation cached label'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='operation_complete_identifier',
+ field=models.TextField(default='{% if code_patriarche %}OA{{code_patriarche}}{% else %}{% if operation_code and year %}{{year}}-{{operation_code}}{% else %}-{% endif %}{% endif %}', help_text='Formula to manage operation complete identifier.', verbose_name='Operation complete identifier'),
+ ),
+ migrations.AlterField(
+ model_name='ishtarsiteprofile',
+ name='parcel_cached_label',
+ field=models.TextField(default='{associated_file__external_id}{operation__complete_identifier} | {town__numero_insee} | {section}{parcel_number}', help_text='Formula to manage cached label. If not set a default formula is used.', verbose_name='Parcel cached label'),
+ ),
+ ]
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 75e07d7cb..a1fd5e714 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -560,6 +560,7 @@ class BulkUpdatedItem(object):
:param extra_args: arguments dealing with
:return: (transaction ID, is a recursion)
"""
+ # TODO: no more bulk update - should be removed
if not transaction_id:
transaction_id = str(time.time())
args = ["cached_label_bulk_update", transaction_id] + extra_args
@@ -1169,8 +1170,9 @@ class IshtarSiteProfile(models.Model, Cached):
)
operation_complete_identifier = models.TextField(
_("Operation complete identifier"),
- default="",
- blank=True,
+ default="{% if code_patriarche %}OA{{code_patriarche}}{% else %}"
+ "{% if operation_code and year %}{{year}}-{{operation_code}}"
+ "{% else %}-{% endif %}{% endif %}",
help_text=_("Formula to manage operation complete identifier."),
)
operation_custom_index = models.TextField(
@@ -1184,8 +1186,8 @@ class IshtarSiteProfile(models.Model, Cached):
)
operation_cached_label = models.TextField(
_("Operation cached label"),
- default="",
- blank=True,
+ default="{{cached_towns_label}} | {% if code_patriarche %}OA{{code_patriarche}}{% else %}"
+ "{% if operation_code and year %}OP{{year}}-{{operation_code}}{% endif %}{% endif %}",
help_text=_(
"Formula to manage cached label. If not set a default formula is used."
),
@@ -1227,7 +1229,7 @@ class IshtarSiteProfile(models.Model, Cached):
_("Archaeological file complete identifier"),
default="",
blank=True,
- help_text=_("Formula to manage archaeological file complete " "identifier."),
+ help_text=_("Formula to manage archaeological file complete identifier."),
)
file_custom_index = models.TextField(
_("Archaeological file custom index key"),
@@ -1259,8 +1261,8 @@ class IshtarSiteProfile(models.Model, Cached):
)
parcel_cached_label = models.TextField(
_("Parcel cached label"),
- default="",
- blank=True,
+ default="{associated_file__external_id}{operation__complete_identifier} | "
+ "{town__numero_insee} | {section}{parcel_number}",
help_text=_(
"Formula to manage cached label. If not set a default formula is used."
),
@@ -1292,8 +1294,7 @@ class IshtarSiteProfile(models.Model, Cached):
)
contextrecord_cached_label = models.TextField(
_("Context record cached label"),
- default="",
- blank=True,
+ default="{parcel__cached_label} | {label}",
help_text=_(
"Formula to manage cached label. If not set a default formula is used."
),
@@ -1325,7 +1326,7 @@ class IshtarSiteProfile(models.Model, Cached):
)
basefind_cached_label = models.TextField(
_("Base find cached label"),
- default="",
+ default="{context_record__cached_label} | {label}",
blank=True,
help_text=_(
"Formula to manage cached label. If not set a default formula is used."
@@ -1358,8 +1359,7 @@ class IshtarSiteProfile(models.Model, Cached):
)
find_cached_label = models.TextField(
_("Find cached label"),
- default="",
- blank=True,
+ default="{get_first_base_find__context_record__operation__complete_identifier}-{index:0>5} | {label}",
help_text=_(
"Formula to manage cached label. If not set a default formula is used."
),
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index 2074aa523..0345eada2 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -1080,6 +1080,8 @@ class Imported(models.Model):
imports = models.ManyToManyField(
Import, blank=True, related_name="imported_%(app_label)s_%(class)s"
)
+ timestamp_geo = models.IntegerField(_("Timestamp geo"), null=True, blank=True)
+ timestamp_label = models.IntegerField(_("Timestamp label"), null=True, blank=True)
class Meta:
abstract = True
@@ -3329,6 +3331,8 @@ class MainItem(ShortMenuItem, SerializeItem):
rel.update(need_update=True)
continue
for item in getattr(self, down_model).all():
+ if hasattr(self, "_timestamp"):
+ item._timestamp = self._timestamp
if hasattr(item, "cached_label_changed"):
item.cached_label_changed()
if hasattr(item, "main_geodata"):
@@ -3417,10 +3421,13 @@ class MainItem(ShortMenuItem, SerializeItem):
def regenerate_external_id(self):
if not hasattr(self, "external_id"):
return
+ try:
+ self.external_id = ""
+ self.auto_external_id = True
+ except AttributeError:
+ return
self.skip_history_when_saving = True
self._no_move = True
- self.external_id = ""
- self.auto_external_id = True
self.save()
def cached_label_changed(self):
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index bbefd085e..d5ace858d 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -487,6 +487,7 @@ EXTRA_KWARGS_TRIGGER = [
"_post_saved_geo",
"_search_updated",
"_cached_label_checked",
+ "_timestamp",
]
@@ -549,6 +550,9 @@ def cached_label_changed(sender, **kwargs):
instance = kwargs["instance"]
if not instance:
return
+ if hasattr(instance, "_timestamp") and hasattr(instance, "timestamp_label") and (
+ instance.timestamp_label or 0) >= (instance._timestamp or 0):
+ return
if hasattr(instance, "external_id") and hasattr(instance, "auto_external_id") \
and hasattr(instance, "SLUG") and not getattr(instance, "_external_id_checked", None):
changed = load_task(_external_id_changed, "external_id_changed", None, sender, **kwargs)
@@ -581,6 +585,11 @@ def _cached_label_changed(sender, **kwargs):
if not force_update and getattr(instance, "_cached_label_checked", False):
return
+ if hasattr(instance, "_timestamp") and hasattr(instance, "timestamp_label"):
+ if (instance.timestamp_label or 0) >= (instance._timestamp or 0):
+ return
+ instance.__class__.objects.filter(pk=instance.pk).update(timestamp_label=instance._timestamp)
+
logger.debug(f"[ishtar] ishtar_common.utils._cached_label_changed - {instance.__class__.__name__} - {instance.pk} - {instance}")
if hasattr(instance, "refresh_cache"):
instance.refresh_cache()
@@ -625,6 +634,8 @@ def _cached_label_changed(sender, **kwargs):
item._cascade_change = True
if hasattr(instance, "test_obj"):
item.test_obj = instance.test_obj
+ if instance.timestamp_label:
+ item._timestamp = instance.timestamp_label
cached_label_changed(item.__class__, instance=item)
cache_key, __ = get_cache(sender, ["cached_label_changed", instance.pk])
@@ -672,9 +683,12 @@ def _external_id_changed(sender, **kwargs):
if not instance.external_id or instance.auto_external_id:
external_id = get_generated_id(instance.SLUG + "_external_id", instance)
if external_id != instance.external_id:
- updated = True
- instance.auto_external_id = True
- instance.external_id = external_id
+ try:
+ instance.auto_external_id = True
+ instance.external_id = external_id
+ updated = True
+ except AttributeError:
+ pass
if hasattr(instance, "regenerate_all_ids"):
updated |= instance.regenerate_all_ids(save=False) or False
instance._external_id_checked = True
@@ -909,6 +923,11 @@ def _post_save_geo(sender, **kwargs):
if getattr(instance, "_post_saved_geo", False):
return
+ if hasattr(instance, "_timestamp") and hasattr(instance, "timestamp_geo"):
+ if (instance.timestamp_label or 0) >= (instance._timestamp or 0):
+ return
+ instance.__class__.objects.filter(pk=instance.pk).update(timestamp_geo=instance._timestamp)
+
logger.debug(f"[ishtar] ishtar_common.utils._post_save_geo - {instance.__class__.__name__} - {instance.pk} - {instance}")
instance._post_saved_geo = True
@@ -1964,7 +1983,7 @@ def get_current_profile(force=False):
return IshtarSiteProfile.get_current_profile(force=force)
-PARSE_FORMULA = re.compile(r"{([^}^\:]*)(?::.*)?}")
+PARSE_FORMULA = re.compile(r"{([^}^\\:]*)(?::[^}]*)?}")
PARSE_JINJA = re.compile("{{([^}]*)}")
PARSE_JINJA_IF = re.compile("{% if ([^}]*)}")
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 8f970f424..97f108744 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -14184,6 +14184,9 @@ msgstr "Surcharge de traduction"
msgid "Translations overload"
msgstr "Surcharges de traductions"
+msgid "No associated town"
+msgstr "Pas de commune associée"
+
#~ msgid "Center"
#~ msgstr "Centre"