summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/models.py43
-rw-r--r--archaeological_finds/models_finds.py16
-rw-r--r--archaeological_finds/templates/ishtar/sheet_find.html10
-rw-r--r--archaeological_finds/tests.py39
-rw-r--r--ishtar_common/models.py38
-rw-r--r--ishtar_common/templatetags/window_field.py5
-rw-r--r--ishtar_common/utils.py14
7 files changed, 102 insertions, 63 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index 5ba631dba..030f817d9 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -29,7 +29,7 @@ from django.utils.translation import ugettext_lazy as _, pgettext, \
activate, pgettext_lazy, deactivate
from django.utils.text import slugify
-from ishtar_common.utils import cached_label_changed
+from ishtar_common.utils import cached_label_changed, HISTORY_M2M_SPLIT
from ishtar_common.models import Document, GeneralType, \
BaseHistorizedItem, HistoricalRecords, OwnPerms, ShortMenuItem, \
@@ -104,25 +104,30 @@ class Dating(models.Model):
return self.SEP.join(values)
@classmethod
- def history_decompress(cls, value):
- if not value:
- value = ""
- res = {}
- for idx, val in enumerate(value.split(cls.SEP)):
- key = cls.HISTORY_ATTR[idx]
- if val == '':
- val = None
- elif key in ("period", "dating_type", "quality"):
- field = cls._meta.get_field(key)
- q = field.related_model.objects.filter(txt_idx=val)
- if q.count():
- val = q.all()[0]
- else: # do not exist anymore in db
+ def history_decompress(cls, full_value, create=False):
+ if not full_value:
+ return []
+ full_res = []
+ for value in full_value.split(HISTORY_M2M_SPLIT):
+ res = {}
+ for idx, val in enumerate(value.split(cls.SEP)):
+ key = cls.HISTORY_ATTR[idx]
+ if val == '':
val = None
- elif key in ("start_date", "end_date"):
- val = int(val)
- res[key] = val
- return res
+ elif key in ("period", "dating_type", "quality"):
+ field = cls._meta.get_field(key)
+ q = field.related_model.objects.filter(txt_idx=val)
+ if q.count():
+ val = q.all()[0]
+ else: # do not exist anymore in db
+ val = None
+ elif key in ("start_date", "end_date"):
+ val = int(val)
+ res[key] = val
+ if create:
+ res = cls.objects.create(**res)
+ full_res.append(res)
+ return full_res
@classmethod
def is_identical(cls, dating_1, dating_2):
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index f8cc34e61..9e377d1f6 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -32,7 +32,7 @@ from django.utils.translation import ugettext_lazy as _, pgettext_lazy, \
from ishtar_common.data_importer import post_importer_action, ImporterError
from ishtar_common.utils import cached_label_changed, post_save_point, \
- m2m_historization_changed, HISTORY_M2M_SPLIT
+ m2m_historization_changed
from ishtar_common.alternative_configs import ALTERNATE_CONFIGS
@@ -41,7 +41,7 @@ from ishtar_common.models import Document, GeneralType, \
HistoricalRecords, OwnPerms, Person, Basket, post_save_cache, \
ValueGetter, get_current_profile, IshtarSiteProfile, PRIVATE_FIELDS, \
SpatialReferenceSystem, BulkUpdatedItem, ExternalIdManager, QuickAction, \
- MainItem, document_attached_changed
+ MainItem, document_attached_changed, HistoryModel
from archaeological_operations.models import AdministrativeAct, Operation
from archaeological_context_records.models import ContextRecord, Dating
@@ -1199,7 +1199,7 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms,
help_text=_(u"Related treatments when no new find is created"))
cached_label = models.TextField(_(u"Cached name"), null=True, blank=True,
db_index=True)
- history = HistoricalRecords()
+ history = HistoricalRecords(bases=[HistoryModel])
BASKET_MODEL = FindBasket
class Meta:
@@ -1233,16 +1233,6 @@ class Find(BulkUpdatedItem, ValueGetter, BaseHistorizedItem, OwnPerms,
return u" ; ".join([unicode(dating) for dating in self.datings.all()])
@property
- def dating_list(self):
- if self.historical_datings:
- return [
- Dating.history_decompress(v)
- for v in self.historical_datings.split(HISTORY_M2M_SPLIT)
- ]
- else:
- return self.datings.all()
-
- @property
def excavation_ids(self):
return u" - ".join(
[base_find['excavation_id']
diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html
index 2d234b2d9..ac2df607d 100644
--- a/archaeological_finds/templates/ishtar/sheet_find.html
+++ b/archaeological_finds/templates/ishtar/sheet_find.html
@@ -19,7 +19,7 @@
{% with permission_view_document=permission_view_document %}
{% with permission_view_own_document=permission_view_own_document %}
-{% with display_identification=item.integrities.count|or_:item.remarkabilities.count|or_:item.conservatory_state|or_:item.conservatory_comment|or_:item.alterations.count|or_:item.alteration_causes.count|or_:item.preservation_to_considers.count|or_:item.appraisal_date|or_:item.treatment_emergency|or_:item.insurance_value|or_:item.estimated_value|or_:item.datings.count|or_:item.dating_comment %}
+{% with display_datings=item.integrities.count|or_:item.remarkabilities.count|or_:item.conservatory_state|or_:item.conservatory_comment|or_:item.alterations.count|or_:item.alteration_causes.count|or_:item.preservation_to_considers.count|or_:item.appraisal_date|or_:item.treatment_emergency|or_:item.insurance_value|or_:item.estimated_value|or_:item.historical_datings|or_:item.datings.count|or_:item.dating_comment %}
{% with display_warehouse_treatments=item.container|or_:item.container_ref|or_:item.upstream_treatment|or_:item.downstream_treatment|or_:item.treatments.count %}
{% with can_view_documents=permission_view_own_document|or_:permission_view_document %}
{% with display_documents=can_view_documents|and_:item.documents.count %}
@@ -39,7 +39,7 @@
{% trans "Identification / Description / Dimensions" %}
</a>
</li>
- {% if display_identification %}
+ {% if display_datings %}
<li class="nav-item">
<a class="nav-link" id="{{window_id}}-preservation-tab"
data-toggle="tab" href="#{{window_id}}-preservation" role="tab"
@@ -180,7 +180,7 @@
{% include "ishtar/blocks/sheet_creation_section.html" %}
</div>
</div>
- {% if display_identification %}
+ {% if display_datings %}
<div class="tab-pane fade" id="{{window_id}}-preservation"
role="tabpanel" aria-labelledby="{{window_id}}-preservation-tab">
{% if item.integrities.count or item.remarkabilities.count or item.conservatory_state or item.conservatory_comment or item.alterations.count or item.alteration_causes.count or item.preservation_to_considers.count or item.appraisal_date or item.treatment_emergency or item.insurance_value or item.estimated_value %}
@@ -202,7 +202,6 @@
{% if item.historical_datings or item.datings.count or item.dating_comment %}
<h3>{% trans "Dating" %}</h3>
- {% if item.datings.count %}
<table id='{{window_id}}-datings' class="table table-striped">
<tr>
<th>{% trans "Period" %}</th>
@@ -212,7 +211,7 @@
<th>{% trans "Quality" %}</th>
<th>{% trans "Precise dating" %}</th>
</tr>
- {% for dating in item.dating_list %}
+ {% for dating in item|m2m_listing:'datings' %}
<tr>
<td>
{{dating.period}}
@@ -235,7 +234,6 @@
</tr>
{% endfor %}
</table>
- {% endif %}
{% field_flex_full "Comment on dating" item.dating_comment "<pre>" "</pre>" %}
{% endif %}
</div>
diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py
index cefeb1649..231ac30ad 100644
--- a/archaeological_finds/tests.py
+++ b/archaeological_finds/tests.py
@@ -861,15 +861,19 @@ class FindHistoryTest(FindInit, TestCase):
def test_m2m_history_save(self):
find = self.finds[0]
user = self.get_default_user()
- nb_hist = find.history.count()
ceram = models.MaterialType.objects.get(txt_idx='ceramic').pk
glass = models.MaterialType.objects.get(txt_idx='glass').pk
+
+ find = models.Find.objects.get(pk=find.pk)
+ nb_hist = find.history.count()
+ find.label = "hop hop hop1"
+ find.history_modifier = user
+ find._force_history = True
+ find.save()
find.material_types.add(ceram)
find.material_types.add(glass)
d1_txt, d2_txt = self._add_datings(find)
-
- find = models.Find.objects.get(pk=find.pk)
self.assertIn(
find.historical_material_types,
[HISTORY_M2M_SPLIT.join(['ceramic', 'glass']), # order do not
@@ -880,20 +884,16 @@ class FindHistoryTest(FindInit, TestCase):
HISTORY_M2M_SPLIT.join([d2_txt, d1_txt])]) # matter
historical_material_types = find.historical_material_types
- find.label = "hop hop hop1"
- find.history_modifier = user
- find._force_history = True
- find.save()
find = models.Find.objects.get(pk=find.pk)
- find.material_types.remove(ceram)
- find.datings.clear()
find.label = "hop hop hop2"
find.history_modifier = user
if hasattr(find, 'skip_history_when_saving'):
delattr(find, 'skip_history_when_saving')
find._force_history = True
find.save()
+ find.material_types.remove(ceram)
+ find.datings.clear()
find = models.Find.objects.get(pk=find.pk)
self.assertEqual(find.historical_material_types, 'glass')
@@ -908,33 +908,33 @@ class FindHistoryTest(FindInit, TestCase):
c = Client()
user = self.get_default_user()
find = self.finds[0]
-
- find = models.Find.objects.get(pk=find.pk)
ceram = models.MaterialType.objects.get(txt_idx='ceramic').pk
glass = models.MaterialType.objects.get(txt_idx='glass').pk
- find.material_types.add(ceram)
- find.material_types.add(glass)
- self._add_datings(find)
+
+ find = models.Find.objects.get(pk=find.pk)
find.history_modifier = user
find.label = "hop hop hop1"
find._force_history = True
if hasattr(find, 'skip_history_when_saving'):
delattr(find, 'skip_history_when_saving')
find.save()
+ find.material_types.add(ceram)
+ find.material_types.add(glass)
+ self._add_datings(find)
find = models.Find.objects.get(pk=find.pk)
- find.material_types.remove(ceram)
find.history_modifier = user
find.label = "hop hop hop2"
- find.datings.clear()
find._force_history = True
if hasattr(find, 'skip_history_when_saving'):
delattr(find, 'skip_history_when_saving')
find.save()
+ find.datings.clear()
+ find.material_types.remove(ceram)
find = models.Find.objects.get(pk=find.pk)
- history_date = find.history.all()[1].history_date.strftime(
- '%Y-%m-%dT%H:%M:%S.%f')
+ history_date = find.history.order_by('-history_date').all()[
+ 1].history_date.strftime('%Y-%m-%dT%H:%M:%S.%f')
c.login(username=self.username, password=self.password)
response = c.get(reverse('show-find',
@@ -957,7 +957,8 @@ class FindHistoryTest(FindInit, TestCase):
content = response.content.decode('utf-8')
self.assertIn(
models.MaterialType.objects.get(txt_idx='ceramic').label, content)
- self.assertIn("5001", content)
+ self.assertIn("5001", content, msg=u"5001 not found in historical "
+ u"sheet")
self.assertIn(
Period.objects.get(txt_idx='neolithic').label, content)
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index c7223c898..e5e173654 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -148,6 +148,18 @@ class ValueGetter(object):
return values
+class HistoryModel(models.Model):
+ class Meta:
+ abstract = True
+
+ def m2m_listing(self, key):
+ hist_value = getattr(self, "historical_" + key, None)
+ if not hist_value:
+ return
+ related_model = getattr(self, key).model
+ return related_model.history_decompress(hist_value)
+
+
class HistoricalRecords(BaseHistoricalRecords):
def create_historical_record(self, instance, type):
try:
@@ -523,9 +535,9 @@ class GeneralType(Cached, models.Model):
return self.txt_idx
@classmethod
- def history_decompress(cls, value=""):
+ def history_decompress(cls, value, create=False):
if not value:
- value = ""
+ return []
res = []
for txt_idx in value.split(HISTORY_M2M_SPLIT):
try:
@@ -1571,12 +1583,27 @@ class BaseHistorizedItem(DocumentItem, FullSearch, Imported, JsonData,
if not new_item:
raise HistoryError(u"The date to rollback to doesn't exist.")
try:
- for f in self._meta.fields:
- k = f.name
+ field_keys = [f.name for f in self._meta.fields]
+ for k in field_keys:
if k != 'id' and hasattr(self, k):
if not hasattr(new_item, k):
k = k + "_id"
setattr(self, k, getattr(new_item, k))
+
+ # M2M history
+ if k.startwith('historical_') \
+ and k[len('historical_'):] in field_keys:
+ value = getattr(new_item, k)
+ if not value:
+ continue
+ base_k = k[len('historical_'):]
+ base_field = self._meta.get_field(base_k)
+ base_field.clear()
+ new_values = base_field.related_model.history_decompress(
+ value, create=True
+ )
+ for val in new_values:
+ base_field.add(val)
try:
self.history_modifier = User.objects.get(
pk=new_item.history_modifier_id)
@@ -1591,6 +1618,9 @@ class BaseHistorizedItem(DocumentItem, FullSearch, Imported, JsonData,
for historized_item in to_del:
historized_item.delete()
+ def m2m_listing(self, key):
+ return getattr(self, key).all()
+
def values(self):
values = {}
for f in self._meta.fields:
diff --git a/ishtar_common/templatetags/window_field.py b/ishtar_common/templatetags/window_field.py
index 3af9ed634..df72690c4 100644
--- a/ishtar_common/templatetags/window_field.py
+++ b/ishtar_common/templatetags/window_field.py
@@ -166,3 +166,8 @@ def field_flex_detail(context, caption, item, small=False):
if small:
size = 2
return field_detail(context, caption, item, size=size)
+
+
+@register.filter
+def m2m_listing(item, key):
+ return item.m2m_listing(key)
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index 94e71c655..56c6f669f 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -938,12 +938,22 @@ def m2m_historization_changed(sender, **kwargs):
obj = kwargs.get('instance', None)
if not obj:
return
+ hist_values = {}
for attr in obj.HISTORICAL_M2M:
values = []
for value in getattr(obj, attr).all():
if not hasattr(value, "history_compress"):
continue
values.append(value.history_compress())
- setattr(obj, 'historical_' + attr, HISTORY_M2M_SPLIT.join(values))
- obj.skip_history_when_saving = True
+ hist_values['historical_' + attr] = HISTORY_M2M_SPLIT.join(values)
+ for key in hist_values:
+ setattr(obj, key, hist_values[key])
+ # force resave of last history record
+ if hasattr(obj, 'skip_history_when_saving'):
+ delattr(obj, 'skip_history_when_saving')
+ obj._force_history = True
+ q = obj.history.order_by("-history_date")
+ if q.count():
+ last = q.all()[0]
+ last.delete()
obj.save()