summaryrefslogtreecommitdiff
path: root/archaeological_finds
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_finds')
-rw-r--r--archaeological_finds/forms.py6
-rw-r--r--archaeological_finds/models.py91
-rw-r--r--archaeological_finds/templates/ishtar/sheet_find.html153
-rw-r--r--archaeological_finds/tests.py81
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")