summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_warehouse/forms.py79
-rw-r--r--archaeological_warehouse/migrations/0102_auto_20200408_1823.py9
-rw-r--r--archaeological_warehouse/models.py14
-rw-r--r--archaeological_warehouse/templates/ishtar/sheet_container.html24
-rw-r--r--archaeological_warehouse/templates/ishtar/wizard/wizard_container.html39
-rw-r--r--archaeological_warehouse/tests.py6
-rw-r--r--archaeological_warehouse/urls.py2
-rw-r--r--archaeological_warehouse/views.py16
-rw-r--r--archaeological_warehouse/wizards.py18
-rw-r--r--ishtar_common/templates/blocks/JQueryAutocomplete.js2
-rw-r--r--ishtar_common/templates/ishtar/wizard/default_wizard.html2
-rw-r--r--ishtar_common/widgets.py10
12 files changed, 116 insertions, 105 deletions
diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py
index 83289819e..3e754b84a 100644
--- a/archaeological_warehouse/forms.py
+++ b/archaeological_warehouse/forms.py
@@ -61,17 +61,17 @@ def get_warehouse_field(label=_("Warehouse"), required=True):
class SelectedDivisionForm(ManageOldType, forms.Form):
form_label = _("Division")
base_model = 'associated_division'
- associated_models = {'division': models.WarehouseDivision,
+ associated_models = {'division': models.ContainerType,
'associated_division': models.WarehouseDivisionLink}
division = forms.ChoiceField(
- label=_("Division"), choices=(),
- validators=[valid_id(models.WarehouseDivision)])
+ label=_("Container type"), choices=(),
+ validators=[valid_id(models.ContainerType)])
order = forms.IntegerField(label=_("Order"), min_value=0, required=False)
def __init__(self, *args, **kwargs):
super(SelectedDivisionForm, self).__init__(*args, **kwargs)
self.fields['division'].choices = \
- models.WarehouseDivision.get_types(
+ models.ContainerType.get_types(
initial=self.init_data.get('division')
)
@@ -263,32 +263,27 @@ class ContainerForm(CustomForm, ManageOldType, forms.Form):
extra_form_modals = ["warehouse", "organization", "person", "container"]
associated_models = {'container_type': models.ContainerType,
'location': models.Warehouse,
- 'parent': models.Container,
- 'responsible': models.Warehouse}
+ 'parent': models.Container}
reference = forms.CharField(label=_("Ref."), max_length=200)
old_reference = forms.CharField(label=_("Old reference"), required=False,
max_length=200)
container_type = forms.ChoiceField(label=_("Container type"), choices=[])
+ location = forms.IntegerField(
+ label=_("Current location (warehouse)"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-warehouse'),
+ associated_model=models.Warehouse, new=True),
+ validators=[valid_id(models.Warehouse)])
parent = forms.IntegerField(
label=_("Parent container"),
widget=widgets.JQueryAutoComplete(
reverse_lazy('autocomplete-container'),
- associated_model=models.Container, new=True),
+ associated_model=models.Container, new=True,
+ tips="-"
+ ),
validators=[valid_id(models.Container)],
required=False
)
- responsible = forms.IntegerField(
- label=_("Responsible warehouse"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-warehouse'),
- associated_model=models.Warehouse, new=True),
- validators=[valid_id(models.Warehouse)])
- location = forms.IntegerField(
- label=_("Current location (warehouse)"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-warehouse'),
- associated_model=models.Warehouse, new=True),
- validators=[valid_id(models.Warehouse)])
comment = forms.CharField(label=_("Comment"),
widget=forms.Textarea, required=False)
TYPES = [
@@ -303,6 +298,18 @@ class ContainerForm(CustomForm, ManageOldType, forms.Form):
kwargs.pop('limits')
super(ContainerForm, self).__init__(*args, **kwargs)
+ def _clean_parent(self):
+ if not self.cleaned_data.get("parent", None):
+ return
+ warehouse_id = self.cleaned_data.get("location")
+ q = models.Container.objects.filter(
+ pk=self.cleaned_data["parent"],
+ location_id=warehouse_id)
+ if not q.count():
+ raise forms.ValidationError(
+ _("The parent container is not attached to the same "
+ "warehouse."))
+
def clean(self):
cleaned_data = self.cleaned_data
warehouse = cleaned_data.get("location")
@@ -324,7 +331,6 @@ class ContainerForm(CustomForm, ManageOldType, forms.Form):
dct['container_type'] = models.ContainerType.objects.get(
pk=dct['container_type'])
dct['location'] = models.Warehouse.objects.get(pk=dct['location'])
- dct['responsible'] = models.Warehouse.objects.get(pk=dct['responsible'])
new_item = models.Container(**dct)
new_item.save()
return new_item
@@ -340,7 +346,7 @@ class ContainerModifyForm(ContainerForm):
idx = self.fields.pop('index')
for key, value in self.fields.items():
fields[key] = value
- if key == 'location':
+ if key == 'container_type':
fields['index'] = idx
self.fields = fields
@@ -348,9 +354,9 @@ class ContainerModifyForm(ContainerForm):
# manage unique ID
cleaned_data = super(ContainerModifyForm, self).clean()
index = cleaned_data.get("index", None)
- warehouse = cleaned_data.get("responsible")
+ warehouse = cleaned_data.get("location")
if not index:
- q = models.Container.objects.filter(responsible__pk=warehouse)
+ q = models.Container.objects.filter(location__pk=warehouse)
if not q.count():
cleaned_data["index"] = 1
else:
@@ -539,33 +545,6 @@ class FindPackagingFormSelection(FindMultipleFormSelection):
form_label = _("Packaged finds")
-class LocalisationForm(CustomForm, forms.Form):
- form_admin_name = _("Container - 020 - Localisation")
- form_slug = "container-020-localisation"
- form_label = _("Localisation")
-
- def __init__(self, *args, **kwargs):
- self.container, self.warehouse = None, None
- if 'warehouse' in kwargs:
- self.warehouse = kwargs.pop('warehouse')
- if 'container' in kwargs:
- self.container = kwargs.pop('container')
- super(LocalisationForm, self).__init__(*args, **kwargs)
- if not self.warehouse:
- return
- for divlink in self.warehouse.divisions.order_by('order').all():
- initial = "-"
- if self.container:
- q = models.ContainerLocalisation.objects.filter(
- division__division=divlink.division,
- container=self.container)
- if q.count():
- initial = q.all()[0].reference
- self.fields['division_{}'.format(divlink.pk)] = forms.CharField(
- label=str(divlink.division), max_length=200, initial=initial,
- )
-
-
class ContainerDeletionForm(FinalForm):
confirm_msg = _("Would you like to delete this container?")
confirm_end_msg = _("Would you like to delete this container?")
diff --git a/archaeological_warehouse/migrations/0102_auto_20200408_1823.py b/archaeological_warehouse/migrations/0102_auto_20200408_1823.py
index 6bc7f8f88..6550636dc 100644
--- a/archaeological_warehouse/migrations/0102_auto_20200408_1823.py
+++ b/archaeological_warehouse/migrations/0102_auto_20200408_1823.py
@@ -142,6 +142,15 @@ class Migration(migrations.Migration):
name='stationary',
field=models.BooleanField(default=False, help_text='Container that usually will not be moved. Ex: building, room.', verbose_name='Stationary'),
),
+ migrations.AlterModelOptions(
+ name='containertype',
+ options={'ordering': ('order', 'label'), 'verbose_name': 'Container type', 'verbose_name_plural': 'Container types'},
+ ),
+ migrations.AddField(
+ model_name='containertype',
+ name='order',
+ field=models.IntegerField(default=10, verbose_name='Order'),
+ ),
migrations.AddField(
model_name='warehousedivisionlink',
name='container_type',
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index 8d2a3fb71..6de87ee36 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -370,9 +370,9 @@ post_delete.connect(post_save_cache, sender=WarehouseDivision)
class WarehouseDivisionLinkManager(models.Manager):
- def get_by_natural_key(self, warehouse, division):
+ def get_by_natural_key(self, warehouse, container_type):
return self.get(warehouse__uuid=warehouse,
- division__txt_idx=division)
+ container_type__txt_idx=container_type)
class ContainerType(GeneralType):
@@ -386,11 +386,12 @@ class ContainerType(GeneralType):
volume = models.FloatField(_("Volume (l)"), blank=True, null=True)
reference = models.CharField(_("Ref."), max_length=300, blank=True,
null=True)
+ order = models.IntegerField(_("Order"), default=10)
class Meta:
verbose_name = _("Container type")
verbose_name_plural = _("Container types")
- ordering = ('label',)
+ ordering = ('order', 'label',)
post_save.connect(post_save_cache, sender=ContainerType)
@@ -414,10 +415,10 @@ class WarehouseDivisionLink(models.Model):
unique_together = ('warehouse', 'division')
def __str__(self):
- return "{} - {}".format(self.warehouse, self.division)
+ return "{} - {}".format(self.warehouse, self.container_type)
def natural_key(self):
- return self.warehouse.uuid, self.division.txt_idx
+ return self.warehouse.uuid, self.container_type.txt_idx
class ContainerTree:
@@ -1123,6 +1124,7 @@ def container_post_save(sender, **kwargs):
if not kwargs.get('instance'):
return
instance = kwargs.get('instance')
+ #TODO: to be deleted???
for loca in ContainerLocalisation.objects.filter(
container=instance).exclude(
division__warehouse=instance.location).all():
@@ -1142,6 +1144,7 @@ m2m_changed.connect(document_attached_changed,
class ContainerLocalisationManager(models.Manager):
+ #TODO: to be deleted....
def get_by_natural_key(self, container, warehouse, division):
return self.get(container__uuid=container,
division__warehouse__uuid=warehouse,
@@ -1149,6 +1152,7 @@ class ContainerLocalisationManager(models.Manager):
class ContainerLocalisation(models.Model):
+ #TODO: to be deleted....
container = models.ForeignKey(Container, verbose_name=_("Container"),
related_name='division')
division = models.ForeignKey(WarehouseDivisionLink,
diff --git a/archaeological_warehouse/templates/ishtar/sheet_container.html b/archaeological_warehouse/templates/ishtar/sheet_container.html
index 1bb004071..60f49b7ae 100644
--- a/archaeological_warehouse/templates/ishtar/sheet_container.html
+++ b/archaeological_warehouse/templates/ishtar/sheet_container.html
@@ -2,8 +2,11 @@
{% load i18n window_header window_field window_tables link_to_window %}
{% block head_title %}<strong>{% trans "Container" %}</strong> -
-{{ item.container_type|default:"" }} {{ item.reference|default:"" }} -
-{{ item.location.name|default:"" }}
+{% if item.cached_division %}
+{{item.cached_division}}
+{% else %}
+{{ item.container_type|default:"" }} {{ item.reference|default:"" }} {% endif %}
+- {{ item.location.name|default:"" }}
{% endblock %}
{% block toolbar %}
@@ -34,7 +37,7 @@
{% endif %}
{% field_flex_detail "Warehouse" item.location %}
{% if item.parent %}
- <dl class="col-12 col-md-6 flex-wrap">
+ <dl class="col-12 col-md-9 flex-wrap">
<dt>{% trans "Location" %}</dt>
<dd>
<nav aria-label="breadcrumb">
@@ -55,6 +58,21 @@
</div>
</div>
+
+{% with item.container_type as container_type %}
+{% if container_type.length or container_type.width or container_type.height or container_type.volume or container_type.reference %}
+<h4>{% trans "Container type" %}</h4>
+<div class='row'>
+ {% field_flex "Length (mm)" container_type.length %}
+ {% field_flex "Width (mm)" container_type.width %}
+ {% field_flex "Height (mm)" container_type.height %}
+ {% field_flex "Volume (l)" container_type.volume %}
+ {% field_flex "Reference" container_type.reference %}
+</div>
+{% endif %}
+{% endwith %}
+
+
{% if item.container_content.count or item.children.count %}
<h4>{% trans "Content" %}</h4>
diff --git a/archaeological_warehouse/templates/ishtar/wizard/wizard_container.html b/archaeological_warehouse/templates/ishtar/wizard/wizard_container.html
index 4d0a63c17..cf9d4122e 100644
--- a/archaeological_warehouse/templates/ishtar/wizard/wizard_container.html
+++ b/archaeological_warehouse/templates/ishtar/wizard/wizard_container.html
@@ -1,17 +1,26 @@
{% extends "ishtar/wizard/default_wizard.html" %}
-{% load i18n %}
-{% block form_head %}
-{% if not wizard.form.fields %}
-<p class="alert">
- <i class="fa fa-exclamation-triangle"></i>
- {% trans "No division set for this warehouse. Define at least one division to localise containers in this warehouse." %}<br/>
- {{wizard.form.warehouse}}
- <a href="{% url 'warehouse_modify' wizard.form.warehouse.pk %}">
- <span class="fa-stack fa-lg">
- <i class="fa fa-circle fa-stack-2x"></i>
- <i class="fa fa-pencil fa-stack-1x fa-inverse"></i>
- </span>
- </a>
-</p>
-{% endif %}
+{% load i18n replace_underscore %}
+
+{% block "js_extra_generic" %}
+var constraint_on_parent = function(){
+ var warehouse_location_id = $("#id_{{wizard.steps.current}}-location").val();
+ if (!warehouse_location_id) return;
+
+ var parent_search_url = source_{{wizard.steps.current|replace_underscore}}_parent;
+ parent_search_url += warehouse_location_id;
+ $("#id_select_{{wizard.steps.current}}-parent").autocomplete(
+ "option", "source", parent_search_url);
+ var ctips;
+ if (current_label_{{wizard.steps.current|replace_underscore}}_location){
+ ctips = current_label_{{wizard.steps.current|replace_underscore}}_location;
+ } else {
+ ctips = $("#id_{{wizard.steps.current}}-location_previous_label").val();
+ }
+ $("#id_{{wizard.steps.current}}-parent-tips").html(ctips);
+}
+{% endblock %}
+{% block "js_extra_ready" %}
+
+constraint_on_parent();
+$("#id_{{wizard.steps.current}}-location").change(constraint_on_parent);
{% endblock %}
diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py
index 37babf1b2..2fc492caa 100644
--- a/archaeological_warehouse/tests.py
+++ b/archaeological_warehouse/tests.py
@@ -439,9 +439,7 @@ class ContainerWizardCreationTest(WizardTest, FindInit, TestCase):
'reference': 'hop-ref',
'container_type': None,
'location': None,
- 'responsible': None,
},
- 'localisation-container_creation': []
},
),
FormData(
@@ -451,9 +449,7 @@ class ContainerWizardCreationTest(WizardTest, FindInit, TestCase):
'reference': 'hop-ref2',
'container_type': None,
'location': None,
- 'responsible': None,
},
- 'localisation-container_creation': []
},
),
FormData(
@@ -463,9 +459,7 @@ class ContainerWizardCreationTest(WizardTest, FindInit, TestCase):
'reference': 'hop-ref3',
'container_type': None,
'location': None,
- 'responsible': None,
},
- 'localisation-container_creation': []
},
),
]
diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py
index 5c08af2ad..56f554edf 100644
--- a/archaeological_warehouse/urls.py
+++ b/archaeological_warehouse/urls.py
@@ -47,7 +47,7 @@ urlpatterns = [
url(r'get-warehouse-shortcut/(?P<type>.+)?$',
views.get_warehouse, name='get-warehouse-shortcut',
kwargs={'full': 'shortcut'}),
- url(r'autocomplete-container/?$',
+ url(r'autocomplete-container/(?P<warehouse_id>\d+)?$',
views.autocomplete_container, name='autocomplete-container'),
url(r'^show-container(?:/(?P<pk>.+))?/(?P<type>.+)?$', views.show_container,
name=models.Container.SHOW_URL),
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py
index cb74b49f9..801c2255c 100644
--- a/archaeological_warehouse/views.py
+++ b/archaeological_warehouse/views.py
@@ -76,7 +76,7 @@ def autocomplete_warehouse(request):
return HttpResponse(data, content_type='text/plain')
-def autocomplete_container(request):
+def autocomplete_container(request, warehouse_id=None):
if not request.user.has_perm('ishtar_common.view_warehouse',
models.Warehouse)\
and not request.user.has_perm(
@@ -86,7 +86,10 @@ def autocomplete_container(request):
return HttpResponse(content_type='text/plain')
term = request.GET.get('term')
limit = 15
- query = Q()
+ base_query = Q()
+ if warehouse_id:
+ base_query = Q(location_id=warehouse_id)
+ query = base_query
for q in term.split(' '):
extra = Q(reference__iexact=q)
query = query & extra
@@ -94,20 +97,21 @@ def autocomplete_container(request):
query).values('id', 'cached_label')[:limit])
limit = 15 - len(containers)
if limit > 0:
- query = Q()
+ query = base_query
for q in term.split(' '):
extra = Q(container_type__label__icontains=q) | \
Q(container_type__reference__icontains=q) | \
Q(reference__icontains=q) | \
+ Q(cached_division__icontains=q) | \
Q(location__name=q) | \
Q(location__town=q)
query = query & extra
containers += list(
models.Container.objects.filter(query).exclude(
pk__in=[c['id'] for c in containers]
- ).values('id', 'cached_label')[:limit])
+ ).values('id', 'cached_division')[:limit])
data = json.dumps(
- [{'id': container['id'], 'value': container['cached_label']}
+ [{'id': container['id'], 'value': container['cached_division']}
for container in containers])
return HttpResponse(data, content_type='text/plain')
@@ -188,7 +192,6 @@ container_search_wizard = ContainerSearch.as_view([
container_creation_steps = [
('container-container_creation', forms.ContainerForm),
- ('localisation-container_creation', forms.LocalisationForm),
('final-container_creation', FinalForm)]
container_creation_wizard = ContainerWizard.as_view(
@@ -200,7 +203,6 @@ container_creation_wizard = ContainerWizard.as_view(
container_modification_wizard = ContainerModificationWizard.as_view([
('selec-container_modification', forms.MainContainerFormSelection),
('container-container_modification', forms.ContainerModifyForm),
- ('localisation-container_modification', forms.LocalisationForm),
('final-container_modification', FinalForm)],
label=_("Container modification"),
url_name='container_modification',
diff --git a/archaeological_warehouse/wizards.py b/archaeological_warehouse/wizards.py
index 302045e2f..9bce9381b 100644
--- a/archaeological_warehouse/wizards.py
+++ b/archaeological_warehouse/wizards.py
@@ -102,16 +102,6 @@ class WarehouseModificationWizard(Wizard):
}
redirect_url = "warehouse_modification"
- def get_form_kwargs(self, step=None):
- kwargs = super(WarehouseModificationWizard, self).get_form_kwargs(step)
- if step == "divisions-warehouse_modification":
- current_warehouse = self.get_current_object()
- q = models.ContainerLocalisation.objects.filter(
- division__warehouse=current_warehouse)
- if q.count():
- kwargs['readonly'] = True
- return kwargs
-
class WarehouseDeletionWizard(MultipleDeletionWizard):
model = models.Warehouse
@@ -121,10 +111,10 @@ class WarehouseDeletionWizard(MultipleDeletionWizard):
class ContainerWizard(Wizard):
model = models.Container
wizard_templates = {
- 'localisation-container_creation':
- 'ishtar/wizard/wizard_containerlocalisation.html',
- 'localisation-container_modification':
- 'ishtar/wizard/wizard_containerlocalisation.html',
+ 'container-container_creation':
+ 'ishtar/wizard/wizard_container.html',
+ 'container-container_modification':
+ 'ishtar/wizard/wizard_container.html',
}
ignore_init_steps = ['localisation']
wizard_done_window = reverse_lazy('show-container')
diff --git a/ishtar_common/templates/blocks/JQueryAutocomplete.js b/ishtar_common/templates/blocks/JQueryAutocomplete.js
index aaf493db9..54b0cb645 100644
--- a/ishtar_common/templates/blocks/JQueryAutocomplete.js
+++ b/ishtar_common/templates/blocks/JQueryAutocomplete.js
@@ -1,6 +1,7 @@
{% load replace_underscore %}
var base_source_{{field_id|replace_underscore}} = {{source}};
var source_{{field_id|replace_underscore}} = base_source_{{field_id|replace_underscore}};
+var current_label_{{field_id|replace_underscore}};
$(function() {
$("#id_select_{{field_id}}").autocomplete({
@@ -8,6 +9,7 @@ $(function() {
select: function( event, ui ) {
if(ui.item){
$('#id_{{field_id}}').val(ui.item.id);
+ current_label_{{field_id|replace_underscore}} = ui.item.label;
$('#id_{{field_id}}').change();
} else {
$('#id_{{field_id}}').val(null);
diff --git a/ishtar_common/templates/ishtar/wizard/default_wizard.html b/ishtar_common/templates/ishtar/wizard/default_wizard.html
index cfd17e58f..c279a37e0 100644
--- a/ishtar_common/templates/ishtar/wizard/default_wizard.html
+++ b/ishtar_common/templates/ishtar/wizard/default_wizard.html
@@ -52,6 +52,8 @@
{% endblock %}
<script language="javascript" type="text/javascript">
var form_changed = false;
+{% block "js_extra_generic" %}
+{% endblock %}
$(document).ready(function(){
$('form :input').change(function(){form_changed=true;});
$('.change_step').click(function(){
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index 28bd9bdd9..df0d09764 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -729,8 +729,10 @@ class JQueryAutoComplete(forms.TextInput):
model_name = self.associated_model._meta.object_name.lower()
if self.tips:
new += """<span class="input-group-append">
- <span class="add-button input-group-text"><em>{}</em></span></span>
- """.format(self.tips)
+ <span class="add-button input-group-text">
+ <em id="{}-tips">{}</em>
+ </span></span>
+ """.format(attrs_hidden['id'], self.tips)
if self.modify:
new += """
<span class="input-group-append">
@@ -786,8 +788,8 @@ class JQueryAutoComplete(forms.TextInput):
_("Restore previous")
)
attrs_hidden_previous = attrs_hidden.copy()
- attrs_hidden_previous['name'] += u"_previous"
- attrs_hidden_previous['id'] += u"_previous"
+ attrs_hidden_previous['name'] += "_previous"
+ attrs_hidden_previous['id'] += "_previous"
old_value += u"<input type='hidden'{}>".format(
flatatt(attrs_hidden_previous))
pk = None