diff options
Diffstat (limited to 'archaeological_finds')
| -rw-r--r-- | archaeological_finds/forms.py | 6 | ||||
| -rw-r--r-- | archaeological_finds/models.py | 91 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 153 | ||||
| -rw-r--r-- | archaeological_finds/tests.py | 81 |
4 files changed, 260 insertions, 71 deletions
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 99907781b..f5387febe 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -432,8 +432,12 @@ class SelectFindBasketForm(forms.Form): basket = forms.ChoiceField(label=_(u"Basket"), required=True, choices=[]) def __init__(self, *args, **kwargs): - self.user = kwargs.pop('user') + self.user = None + if 'user' in kwargs: + self.user = kwargs.pop('user') super(SelectFindBasketForm, self).__init__(*args, **kwargs) + if not self.user: + return self.fields['basket'].choices = [('', '--')] + [ (b.pk, unicode(b)) for b in models.FindBasket.objects.filter(user=self.user)] diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index 417dd3929..b84b7614f 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -32,6 +32,7 @@ from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \ from archaeological_operations.models import AdministrativeAct from archaeological_context_records.models import ContextRecord, Dating +from ishtar_common.models import PRIVATE_FIELDS from archaeological_warehouse.models import Warehouse, Container @@ -303,10 +304,10 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): find_number = models.IntegerField(_("Find number"), blank=True, null=True) upstream_treatment = models.ForeignKey( "Treatment", blank=True, null=True, - related_name='downstream_treatment', + related_name='downstream', verbose_name=_("Upstream treatment")) downstream_treatment = models.ForeignKey( - "Treatment", blank=True, null=True, related_name='upstream_treatment', + "Treatment", blank=True, null=True, related_name='upstream', verbose_name=_("Downstream treatment")) datings = models.ManyToManyField(Dating, verbose_name=_(u"Dating"), related_name='find') @@ -412,6 +413,42 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): bf.context_record.operation.get_reference(), self.index) + def upstream_treatments(self): + treatments = [] + base_finds = [bf.pk for bf in self.base_finds.all()] + if self.upstream_treatment and \ + self.upstream_treatment.pk not in treatments: + treatments.append((self.upstream_treatment.upstream.distinct( + ).order_by('label').all(), self.upstream_treatment)) + for upstream in self.upstream_treatment.upstream.all(): + if upstream.pk != self.pk and not [ + bf.pk for bf in upstream.base_finds.all() + if bf.pk in base_finds]: + continue + for items, treatment in upstream.upstream_treatments(): + if treatment.pk not in treatments: + treatments.append((treatment.upstream.order_by( + 'label').all(), treatment)) + return treatments + + def downstream_treatments(self): + treatments = [] + base_finds = [bf.pk for bf in self.base_finds.all()] + if self.downstream_treatment and \ + self.downstream_treatment.pk not in treatments: + treatments.append((self.downstream_treatment.downstream.distinct( + ).order_by('label').all(), self.downstream_treatment)) + for downstream in self.downstream_treatment.downstream.all(): + if downstream.pk != self.pk and not [ + bf.pk for bf in downstream.base_finds.all() + if bf.pk in base_finds]: + continue + for items, treatment in downstream.downstream_treatments(): + if treatment.pk not in treatments: + treatments.append((treatment.downstream.order_by( + 'label').all(), treatment)) + return treatments + def get_department(self): bf = self.get_first_base_find() if not bf: @@ -478,19 +515,24 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem): return q.filter(downstream_treatment__isnull=True).count() def duplicate(self, user): - # TODO - raise + model = self.__class__ + # base fields + table_cols = [field.name for field in model._meta.fields + if field.name not in PRIVATE_FIELDS or + field.name == 'order'] dct = dict([(attr, getattr(self, attr)) for attr in - ('order', 'label', 'description', - 'volume', 'weight', 'find_number', 'dating', - 'conservatory_state', 'preservation_to_consider', - 'weight_unit', )]) + table_cols]) dct['order'] += 1 dct['history_modifier'] = user new = self.__class__(**dct) new.save() - for base_find in self.base_finds.all(): - new.base_finds.add(base_find) + + # m2m fields + m2m = [field.name for field in model._meta.many_to_many + if field.name not in PRIVATE_FIELDS] + for field in m2m: + for val in getattr(self, field).all(): + getattr(new, field).add(val) return new @classmethod @@ -606,6 +648,35 @@ class Treatment(BaseHistorizedItem, OwnPerms): lbl += u" %s %s" % (_(u"by"), unicode(self.person)) return lbl + def save(self, *args, **kwargs): + items, user, extra_args_for_new = [], None, [] + if "items" in kwargs: + items = kwargs.pop('items') + if "user" in kwargs: + user = kwargs.pop('user') + if "extra_args_for_new" in kwargs: + extra_args_for_new = kwargs.pop('extra_args_for_new') + is_new = self.pk is None + super(Treatment, self).save(*args, **kwargs) + if not is_new or not items: + return + basket = None + if hasattr(items, "items"): + basket = items + items = basket.items.all() + for item in items: + new = item.duplicate(user) + item.downstream_treatment = self + item.save() + new.upstream_treatment = self + for k in extra_args_for_new: + setattr(new, k, extra_args_for_new[k]) + new.save() + # update baskets + for basket in FindBasket.objects.filter(items__pk=item.pk).all(): + basket.items.remove(item) + basket.items.add(new) + class TreatmentSource(Source): class Meta: diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html index c5d3eb638..d21c85856 100644 --- a/archaeological_finds/templates/ishtar/sheet_find.html +++ b/archaeological_finds/templates/ishtar/sheet_find.html @@ -1,5 +1,5 @@ {% extends "ishtar/sheet.html" %} -{% load i18n window_field from_dict %} +{% load i18n window_field from_dict link_to_window %} {% block head_sheet %} {{block.super}} @@ -10,7 +10,7 @@ {% if previous or next %} <div class='tool'> -{%if previous%} +{% if previous %} <a href="#" onclick='load_window("{% url show-historized-find item.pk previous|date:"c"%}");$("#{{window_id}}").hide();return false;'>{%trans "Previous version"%} ({{previous}})</a> {% endif %} {% if previous and next %} - {% endif %} @@ -25,84 +25,116 @@ <div class='tool modify'><a href='{% url find_modify item.pk %}'>{% trans "Modify" %}</a></div> {% if item.image %} -<a href='{{item.image.url}}' rel="prettyPhoto" title="{{item.label}}"><img src='{{item.thumbnail.url}}'/></a> +<a href='{{item.image.url}}' rel="prettyPhoto" title="{{item.label}}" class='photo'><img src='{{item.thumbnail.url}}'/></a> {% endif%} -{% field "Free-ID" item.label %} -{% field "Previous ID" item.previous_id %} -{% field "Description" item.description %} -{% field "Created by" item.history_creator.ishtaruser.full_label %} -{% field "Administrative index" item.administrative_index %} -{% field_multiple "Material types" item.material_types %} -{% field "Dating" item.dating %} -{% field "Length (cm)" item.length %} -{% field "Width (cm)" item.width %} -{% field "Height (cm)" item.height %} -{% field "Diameter (cm)" item.diameter %} -{% field "Volume (l)" item.volume %} +<ul class='form-flex'> +{% field_li "Free-ID" item.label %} +{% field_li "Previous ID" item.previous_id %} +{% field_li "Description" item.description %} +{% field_li "Created by" item.history_creator.ishtaruser.full_label %} +{% field_li "Administrative index" item.administrative_index %} +{% field_li_multiple "Material types" item.material_types %} +{% field_li "Dating" item.dating %} +{% field_li "Length (cm)" item.length %} +{% field_li "Width (cm)" item.width %} +{% field_li "Height (cm)" item.height %} +{% field_li "Diameter (cm)" item.diameter %} +{% field_li "Volume (l)" item.volume %} {% if item.weight %}{% with item.weight|add:' '|add:item.weight_unit as weight %} -{% field "Weight" weight %} +{% field_li "Weight" weight %} {% endwith %}{% endif %} -{% field "Weight" item.weight %} +{% field_li "Weight" item.weight %} -{% field "Find number" item.find_number %} -{% field "Conservatory state" item.conservatory_state %} -{% field_multiple "Type of preservation to consider" item.preservation_to_considers %} -{% field_multiple "Object types" item.object_types %} -{% field_multiple "Integrity" item.integrities %} +{% field_li "Find number" item.find_number %} +{% field_li "Conservatory state" item.conservatory_state %} +{% field_li_multiple "Type of preservation to consider" item.preservation_to_considers %} +{% field_li_multiple "Object types" item.object_types %} +{% field_li_multiple "Integrity" item.integrities %} {% if item.CHECK_DICT %} -{% field "Checked" item.checked|from_dict:item.CHECK_DICT %} +{% field_li "Checked" item.checked|from_dict:item.CHECK_DICT %} {% endif%} {% if item.history_object and item.history_object.CHECK_DICT %} -{% field "Checked" item.checked|from_dict:item.history_object.CHECK_DICT %} +{% field_li "Checked" item.checked|from_dict:item.history_object.CHECK_DICT %} {% endif%} +{% field_li "Container" item.container %} +</ul> -{% if item.upstream_treatment %}<p><label>{%trans "Upstream treatment"%}{% trans ":"%}</label> -<span class='value'>{{item.upstream_treatment}} ({% for up in item.upstream_treatment.upstream_treatment.all %}{% if forloop.counter0 %}, {%endif %}{{up}}{% endfor %})</span></p>{% endif%} -{% if item.downstream_treatment %}<p><label>{%trans "Downstream treatment"%}{% trans ":"%}</label> -<span class='value'>{{item.downstream_treatment}} ({% for dt in item.downstream_treatment.downstream_treatment.all %}{% if forloop.counter0 %}, {%endif %}{{dt}}{% endfor %})</span></p>{% endif%} -{% if item.container %}<p><label>{%trans "Container"%}{% trans ":"%}</label> -<span class='value'>{{item.container}}</span></p>{% endif%} +{% if item.upstream_treatment %} +<table class='simple' id='{{window_id}}-upstream'> + <caption>{% trans "Upstream treatment" %}</caption> + <tr> + <th>{% trans "Type" %}</th> + <th>{% trans "Related find" %}</th> + <th>{% trans "Person" %}</th> + <th>{% trans "Container" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + </tr> + {% for items, treatment in item.upstream_treatments %} + <tr> + <td class='string'>{{ treatment.treatment_type }}</td> + <td class='item-list'>{% for item in items %}<span>{{item}} {{ item|link_to_window}}</span>{% endfor %}</td> + <td class='string'>{{ treatment.person|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.container|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.start_date|default_if_none:"-" }}</td> + <td class='string'>{{ treatment.end_date|default_if_none:"-" }}</td> + </tr> + {% endfor %} +</table> +{% endif %} + +{% if item.downstream_treatment %} +<table class='simple' id='{{window_id}}-downstream'> + <caption>{% trans "Downstream treatment" %}</caption> + <tr> + <th>{% trans "Type" %}</th> + <th>{% trans "Related find" %}</th> + <th>{% trans "Person" %}</th> + <th>{% trans "Start date" %}</th> + <th>{% trans "End date" %}</th> + </tr> + {% for items, treatment in item.downstream_treatments %} + <tr> + <td class='string'>{{ treatment.treatment_type }}</td> + <td class='item-list'>{% for item in items %}<span>{{item}} {{ item|link_to_window}}</span>{% endfor %}</td> + <td class='string'>{{ treatment.person|default_if_none:"" }}</td> + <td class='string'>{{ treatment.start_date|default_if_none:"" }}</td> + <td class='string'>{{ treatment.end_date|default_if_none:"" }}</td> + </tr> + {% endfor %} +</table> +{% endif %} <h3>{% trans "Associated base finds"%}</h3> {% for base_find in item.base_finds.all %} -<p><label>{%trans "Complete ID"%}{% trans ":"%}</label> -<span class='value'>{{base_find.complete_id}}</span></p> - -{% field "Short ID" base_find.short_id %} +<ul class='form-flex'> +{% field_li "Complete ID" base_find.complete_id %} +{% field_li "Short ID" base_find.short_id %} {% if base_find.IS_ISOLATED_DICT %} -{% field "Batch/object" base_find.batch|from_dict:base_find.IS_ISOLATED_DICT %} +{% field_li "Batch/object" base_find.batch|from_dict:base_find.IS_ISOLATED_DICT %} {% endif %} {% if base_find.history_object and base_find.history_object.IS_ISOLATED_DICT %} -{% field "Batch/object" base_find.batch|from_dict:base_find.history_object.IS_ISOLATED_DICT %} +{% field_li "Batch/object" base_find.batch|from_dict:base_find.history_object.IS_ISOLATED_DICT %} {% endif %} -{% if base_find.discovery_date %} -<p><label>{%trans "Discovery date"%}{% trans ":"%}</label> -<span class='value'>{{base_find.discovery_date}}</span></p> -{% endif%} -{% if base_find.description %} -<p><label>{%trans "Description"%}{% trans ":"%}</label> -<span class='value'>{{base_find.description}}</span></p> -{% endif%} -{% field "Comment" base_find.comment "<pre>" "</pre>" %} -{% if base_find.special_interest %} -<p><label>{%trans "Special interest"%}{% trans ":"%}</label> -<span class='value'>{{base_find.special_interest}}</span></p> -{% endif%} +{% field_li "Discovery date" base_find.discovery_date %} +{% field_li "Special interest" base_find.special_interest %} +{% field_li_detail "Context record" base_find.context_record %} +{% if base_find.context_record %}{% field_li "Parcel" base_find.context_record.parcel %} +{% field_li_detail "Operation" base_find.context_record.operation %}{% endif %} +</ul> -<p><label>{%trans "Related context record"%}{% trans ":"%}</label> -<span class='value'><a href="#" onclick='load_window("{% url show-contextrecord base_find.context_record.pk ''%}");'>{{ base_find.context_record }}</a></span></p> -<p><label>{%trans "Related parcel"%}{% trans ":"%}</label> -<span class='value'>{{base_find.context_record.parcel}}</span></p> -<p><label>{%trans "Related operation"%}{% trans ":"%}</label> -<span class='value'><a href="#" onclick='load_window("{% url show-operation base_find.context_record.operation.pk ''%}");'>{{ base_find.context_record.operation }}</a></span></p> +{% field "Description" base_find.description "<pre>" "</pre>" %} +{% field "Comment" base_find.comment "<pre>" "</pre>" %} {% if forloop.counter0 %}<hr/>{% endif %} {% endfor %} -<table class='simple'> +{% if item.source.count %} +<h3>{% trans "Documents"%}</h3> +<table id='{{window_id}}-docs'> <caption>{%trans "Documents"%}</caption> <tr> <th>{% trans "Title" %}</th> @@ -115,11 +147,16 @@ <td class='string'>{{ doc.title }}</td> <td class='string'>{{doc.source_type}}</td> <td class='string'>{{ doc.authors.all|join:", " }}</td> - <td class='string'>{% if doc.associated_url %}<a href='{{doc.associated_url}}'>{% trans "Link"%}</a>{% endif %}</td> + <td class='string'>{% if doc.associated_url %}<a href='{{doc.associated_url}}' target="_blank">{% trans "Link"%}</a>{% endif %}</td> </tr> {% empty %} - <tr><td colspan="4" class='no_items'>{% trans "No document associated to this find" %}</td></tr> {% endfor %} </table> +<script type='text/javascript'> +tableToGrid('#{{window_id}}-docs', { + width: null, shrinkToFit: false}); +</script> +{% endif %} + {% endblock %} diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index ccf821757..f75e9cfa3 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -19,11 +19,13 @@ from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile -from ishtar_common.models import ImporterType +from django.test import TestCase +from ishtar_common.models import ImporterType, IshtarUser from archaeological_finds import models -from archaeological_context_records.tests import ImportContextRecordTest +from archaeological_context_records.tests import ImportContextRecordTest, \ + ContextRecordInit from ishtar_common import forms_common @@ -67,3 +69,78 @@ class ImportFindTest(ImportContextRecordTest): self.assertTrue(current_nb == (old_nb + 4)) self.assertEqual( models.Find.objects.filter(material_types__pk=ceram).count(), 4) + + +class FindInit(ContextRecordInit): + test_context_records = False + + def create_finds(self, user=None, data_base={}, data={}): + if not getattr(self, 'finds', None): + self.finds = [] + if not getattr(self, 'base_finds', None): + self.base_finds = [] + + default = {'label': "Base find"} + if not data_base.get('history_modifier'): + data_base['history_modifier'] = self.get_default_user() + if not data_base.get('context_record'): + data_base['context_record'] = self.get_default_context_record() + + default.update(data_base) + base_find = models.BaseFind.objects.create(**default) + self.base_finds.append(base_find) + + data["history_modifier"] = data_base["history_modifier"] + find = models.Find.objects.create(**data) + find.base_finds.add(base_find) + self.finds.append(find) + return self.finds, self.base_finds + + def get_default_find(self): + return self.create_finds()[0] + + +class PackagingTest(TestCase, FindInit): + fixtures = [settings.ROOT_PATH + + '../fixtures/initial_data.json', + settings.ROOT_PATH + + '../ishtar_common/fixtures/initial_data.json', + settings.ROOT_PATH + + '../archaeological_files/fixtures/initial_data.json', + settings.ROOT_PATH + + '../archaeological_operations/fixtures/initial_data-fr.json', + settings.ROOT_PATH + + '../archaeological_finds/fixtures/initial_data-fr.json', + ] + model = models.Find + + def setUp(self): + self.create_finds({"label": u"Find 1"}) + self.create_finds({"label": u"Find 2"}) + self.basket = models.FindBasket.objects.create( + label="My basket", user=IshtarUser.objects.get( + pk=self.get_default_user().pk)) + self.other_basket = models.FindBasket.objects.create( + label="My other basket", user=IshtarUser.objects.get( + pk=self.get_default_user().pk)) + for find in self.finds: + self.basket.items.add(find) + self.other_basket.items.add(find) + + def testPackaging(self): + treatment_type = models.TreatmentType.objects.get(txt_idx='packaging') + treatment = models.Treatment(treatment_type=treatment_type) + items_nb = models.Find.objects.count() + treatment.save(user=self.get_default_user(), items=self.basket) + self.assertEqual(items_nb + self.basket.items.count(), + models.Find.objects.count(), + msg="Packaging doesn't generate enough new finds") + # new version of the find is in the basket + for item in self.basket.items.all(): + self.assertNotIn( + item, self.finds, + msg="Original basket have not been upgraded after packaging") + for item in self.other_basket.items.all(): + self.assertNotIn( + item, self.finds, + msg="Other basket have not been upgraded after packaging") |
