diff options
| -rw-r--r-- | archaeological_context_records/models.py | 43 | ||||
| -rw-r--r-- | archaeological_finds/models_finds.py | 16 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 10 | ||||
| -rw-r--r-- | archaeological_finds/tests.py | 39 | ||||
| -rw-r--r-- | ishtar_common/models.py | 38 | ||||
| -rw-r--r-- | ishtar_common/templatetags/window_field.py | 5 | ||||
| -rw-r--r-- | ishtar_common/utils.py | 14 | 
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()  | 
