summaryrefslogtreecommitdiff
path: root/archaeological_operations
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_operations')
-rw-r--r--archaeological_operations/forms.py70
-rw-r--r--archaeological_operations/models.py22
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation.html183
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation_pdf.html18
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation_window.html3
-rw-r--r--archaeological_operations/urls.py6
-rw-r--r--archaeological_operations/views.py39
-rw-r--r--archaeological_operations/widgets.py43
-rw-r--r--archaeological_operations/wizards.py41
9 files changed, 403 insertions, 22 deletions
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index f5f0fea99..72834d8f0 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -35,26 +35,37 @@ from django.utils.translation import ugettext_lazy as _
from ishtar_common.models import valid_id, PersonType, Person, Town
from archaeological_files.models import File
import models
+from widgets import ParcelWidget
from ishtar_common import widgets
-from ishtar_common.forms import FinalForm, FormSet, ClosingDateFormSelection, \
- formset_factory, get_now, reverse_lazy, get_form_selection
+from ishtar_common.forms import BaseFormSet, FinalForm, FormSet, \
+ ClosingDateFormSelection, formset_factory, get_now, reverse_lazy, \
+ get_form_selection, TableSelect
from ishtar_common.forms_common import TownForm, TownFormSet, TownFormset, \
AuthorFormset, SourceForm, SourceSelect, \
SourceDeletionForm, get_town_field
+class ParcelField(forms.MultiValueField):
+ def __init__(self, *args, **kwargs):
+ if 'widget' not in kwargs:
+ self.widget = ParcelWidget()
+ return super(ParcelField, self).__init__(*args, **kwargs)
+
+ def compress(data_list):
+ return u"-".join(data_list)
+
class ParcelForm(forms.Form):
form_label = _("Parcels")
base_model = 'parcel'
associated_models = {'parcel':models.Parcel, 'town':models.Town}
town = forms.ChoiceField(label=_("Town"), choices=(), required=False,
validators=[valid_id(models.Town)])
+ year = forms.IntegerField(label=_("Year"), required=False,
+ validators=[validators.MinValueValidator(1900),
+ validators.MaxValueValidator(2100)])
section = forms.CharField(label=_(u"Section"), required=False,
validators=[validators.MaxLengthValidator(4)])
parcel_number = forms.CharField(label=_(u"Parcel number"), required=False,
validators=[validators.MaxLengthValidator(6)])
- year = forms.IntegerField(label=_("Year"), required=False,
- validators=[validators.MinValueValidator(1900),
- validators.MaxValueValidator(2100)])
def __init__(self, *args, **kwargs):
towns = None
if 'data' in kwargs and 'TOWNS' in kwargs['data']:
@@ -74,9 +85,11 @@ class ParcelForm(forms.Form):
"""Check required fields"""
if any(self.errors):
return
- if not self.cleaned_data or DELETION_FIELD_NAME in self.cleaned_data \
- and self.cleaned_data[DELETION_FIELD_NAME]:
+ if not self.cleaned_data or (DELETION_FIELD_NAME in self.cleaned_data \
+ and self.cleaned_data[DELETION_FIELD_NAME]):
return
+ if not self.cleaned_data.get('parcel_number'):
+ return {}
for key in ('town', 'parcel_number', 'section'):
if not key in self.cleaned_data or not self.cleaned_data[key]:
raise forms.ValidationError(_(u"Town section and parcel number "
@@ -84,23 +97,49 @@ class ParcelForm(forms.Form):
return self.cleaned_data
class ParcelFormSet(FormSet):
+ def add_fields(self, form, index):
+ super(FormSet, self).add_fields(form, index)
+
def clean(self):
"""Checks that no parcels are duplicated."""
- return self.check_duplicate(('town', 'parcel_number', 'year'),
- _(u"There are identical parcels."))
+ return self.check_duplicate(('town', 'section',
+ 'parcel_number', 'year'),
+ _(u"There are identical parcels."))
ParcelFormSet = formset_factory(ParcelForm, can_delete=True,
formset=ParcelFormSet)
ParcelFormSet.form_label = _(u"Parcels")
-class OperationSelect(forms.Form):
+class OperationSelect(TableSelect):
common_name = forms.CharField(label=_(u"Name"), max_length=30)
+ if settings.COUNTRY == 'fr':
+ code_patriarche = forms.IntegerField(
+ widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
+ 'autocomplete-patriarche/'),
+ label="Code PATRIARCHE")
towns = get_town_field()
operation_type = forms.ChoiceField(label=_(u"Operation type"),
choices=[])
+ in_charge = forms.IntegerField(
+ widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person',
+ args=["_".join(
+ [unicode(PersonType.objects.get(txt_idx='head_scientist').pk),
+ unicode(PersonType.objects.get(txt_idx='sra_agent').pk)])]),
+ associated_model=Person, new=True), label=_(u"In charge"))
remains = forms.ChoiceField(label=_(u"Remains"),
choices=models.RemainType.get_types())
+ periods = forms.ChoiceField(label=_(u"Periods"),
+ choices=models.Period.get_types())
year = forms.IntegerField(label=_("Year"))
+ start_before = forms.DateField(label=_(u"Started before"),
+ widget=widgets.JQueryDate)
+ start_after = forms.DateField(label=_(u"Started after"),
+ widget=widgets.JQueryDate)
+ end_before = forms.DateField(label=_(u"Ended before"),
+ widget=widgets.JQueryDate)
+ end_after = forms.DateField(label=_(u"Ended after"),
+ widget=widgets.JQueryDate)
+ parcel = ParcelField(label=_("Parcel (section/number)"))
end_date = forms.NullBooleanField(label=_(u"Is open?"))
def __init__(self, *args, **kwargs):
@@ -108,6 +147,13 @@ class OperationSelect(forms.Form):
self.fields['operation_type'].choices = models.OperationType.get_types()
self.fields['operation_type'].help_text = models.OperationType.get_help()
+ def get_input_ids(self):
+ ids = super(OperationSelect, self).get_input_ids()
+ ids.pop(ids.index('parcel'))
+ ids.append('parcel_0')
+ ids.append('parcel_1')
+ return ids
+
class OperationFormSelection(forms.Form):
form_label = _(u"Operation search")
associated_models = {'pk':models.Operation}
@@ -406,7 +452,7 @@ OperationSourceFormSelection = get_form_selection(
# Administrative act management for operations #
################################################
-class AdministrativeActOpeSelect(forms.Form):
+class AdministrativeActOpeSelect(TableSelect):
operation__towns = get_town_field()
act_type = forms.ChoiceField(label=_("Act type"), choices=[])
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 399b536e2..02ec1a912 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2012-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -18,6 +18,7 @@
# See the file COPYING for details.
import datetime
+from itertools import groupby
from django.conf import settings
from django.contrib.gis.db import models
@@ -137,6 +138,9 @@ class Operation(BaseHistorizedItem, OwnPerms):
unicode(self.operation_code))))
return settings.JOINT.join(items)
+ def grouped_parcels(self):
+ return Parcel.grouped_parcels(list(self.parcels.all()))
+
@classmethod
def get_available_operation_code(cls, year=None):
if not year:
@@ -163,6 +167,7 @@ class Operation(BaseHistorizedItem, OwnPerms):
def year_index(self):
if not self.operation_code:
return ""
+ lbl = unicode(self.operation_code)
lbl = u"%d-%s%s" % (self.year, (3-len(lbl))*"0", lbl)
return lbl
@@ -327,6 +332,21 @@ class Parcel(LightHistorizedItem):
def __unicode__(self):
return self.short_label()
+ @staticmethod
+ def grouped_parcels(parcels):
+ sortkeyfn = lambda s:(getattr(s, 'year'), getattr(s, 'town'),
+ getattr(s, 'section'))
+ parcels.sort(key=sortkeyfn)
+ grouped = []
+ for keys, parcel_grp in groupby(parcels, key=sortkeyfn):
+ for idx, parcel in enumerate(parcel_grp):
+ if not idx:
+ grouped.append(parcel)
+ grouped[-1].parcel_numbers = []
+ grouped[-1].parcel_numbers.append(parcel.parcel_number)
+ grouped[-1].parcel_numbers.sort()
+ return grouped
+
def long_label(self):
items = [unicode(self.operation or self.associated_file)]
items += [unicode(item) for item in [self.section, self.parcel_number]
diff --git a/archaeological_operations/templates/ishtar/sheet_operation.html b/archaeological_operations/templates/ishtar/sheet_operation.html
new file mode 100644
index 000000000..491304125
--- /dev/null
+++ b/archaeological_operations/templates/ishtar/sheet_operation.html
@@ -0,0 +1,183 @@
+{% extends "ishtar/sheet.html" %}
+{% load i18n %}
+{% block content %}
+<div class='tool'>{%trans "Export as:"%} <a href='{% url show-operation item.pk "odt" %}'>{%trans "OpenOffice.org file"%}</a>, <a href='{% url show-operation item.pk "pdf" %}'>{%trans "PDF file"%}</a></div>
+<h3>{% trans "General"%}</h3>
+<p><label>{%trans "Year:"%}</label> <span class='value'>{{ item.year }}</span></p>
+{% if item.operation.operation_code %}<p><label>{%trans "Numerical reference:"%}</label> <span class='value'>{{ item.operation_code }}</span></p>{% endif %}
+
+{% if item.code_patriarche %}<p><label>{%trans "Patriarche OA code:"%}</label> <span class='value'>{{ item.code_patriarche }}</span></p>{%else%}
+<p class='alert'>{%trans "Patriarche OA code not yet recorded!"%}</p>{%endif%}
+
+{#<p><label>{%trans "Operation's name:"%}</label> <span class='value'>{{ item.internal_reference }}</span></p>#}
+
+<p><label>{%trans "Edition date:"%}</label> <span class='value'>{{ item.history.all.0.history_date }}</span></p> <!-- date = now -->
+
+{% if item.start_date %}<p><label>{%trans "Begining date:"%}</label> <span class='value'>{{ item.start_date }}</span></p>
+<p><label>{%trans "Excavation end date:"%}</label> <span class='value'>{{ item.excavation_end_date|default:"-" }}</span></p>
+{%endif%}
+{% if item.in_charge %}<p><label>{%trans "Head scientist:"%}</label> <span class='value'>{{ item.in_charge.full_label }}</span></p>{%endif%}
+<p><label>{%trans "State:"%}</label> <span class='value'>{% if item.is_active %}{%trans "Active file"%}</span></p>
+{% else %}{%trans "Closed operation"%}</span></p>
+<p><label>{%trans "Closing date:"%}</label> <span class='value'>{{ item.closing.date }} <strong>{%trans "by" %}</strong> {{ item.closing.user }}</span></p>
+{% endif %}
+<p><label>{%trans "Type:"%}</label> <span class='value'>{{ item.operation_type }}</span></p>
+{% if item.surface %}<p><label>{%trans "Surface:"%}</label> <span class='value'>{{ item.surface }} m<sup>2</sup> ({{ item.surface_ha }} ha)</span></p>{% endif %}
+{% if item.cost %}<p><label>{%trans "Cost:"%}</label> <span class='value'>{{ item.cost }} &euro;{% if item.cost_by_m2 %}, ({{ item.cost_by_m2 }} &euro;/m<sup>2</sup>){%endif%}</span></p>{%endif%}
+{% if item.duration %}<p><label>{%trans "Duration:"%}</label> <span class='value'>{{ item.duration }} {%trans "Day"%}s</span></p>{%endif%}
+
+<p><label>{%trans "Remains:"%}</label> <span class='value'>{{ item.remains.all|join:", " }}</span></p>
+<p><label>{%trans "Periods:"%}</label> <span class='value'>{{ item.periods.all|join:", " }}</span></p>
+
+{% if item.associated_file %}
+<p><label>{%trans "Associated file:"%}</label> <span class='value'><a href='#' onclick='load_window("{% url show-file item.associated_file.pk ''%}")'>{{ item.associated_file }}</a></span></p><!-- Displayed as Year/index/Commune/Common_name This should be a link to the file sheet of the related file -->
+{% if item.associated_file.is_preventive %}
+{#{% if item.operator_reference_code %}<p><label>{%trans "Operator's reference code:"%}</label> <span class='value'>{{ item.operator_reference_code }}</span></p>{% endif %}#}
+{% if item.associated_file.town_planning_service %}<p><label>{%trans "Town planning service:"%}</label> <span class='value'>{{ item.associated_file.town_planning_service }}</span></p>{% endif %}
+{% if item.associated_file.permit_type %}<p><label>{%trans "Permit type:"%}</label> <span class='value'>{{ item.associated_file.permit_type }}</span></p>{% endif %}
+{% if item.associated_file.permit_reference %}<p><label>{%trans "Permit reference:"%}</label> <span class='value'>{{ item.associated_file.permit_reference }}</span></p>{% endif %}
+{% if item.associated_file.general_contractor.attached_to %}<p><label>{%trans "General contractor organisation:"%}</label> <span class='value'>{{ item.associated_file.general_contractor.attached_to }}</span></p>{% endif %} <!-- Contractor's organisation displayed as concat of Name/Adress/postal_code/city -->
+{% if item.associated_file.general_contractor %}<p><label>{%trans "General contractor:"%}</label> <span class='value'>{{ item.associated_file.general_contractor.full_label }}</span></p>{% endif %}
+{% endif %}
+{% endif %}
+
+{% if item.comment %}<p><label>{%trans "Comment:"%}</label> <span class='value'>{{ item.comment }}</span></p>{%endif%}
+
+<h3>{% trans "Localisation"%}</h3>
+<p><label>{%trans "Towns:"%}</label> <span class='value'>{{ item.towns.all|join:", " }}</span></p>
+
+<p><label>{%trans "Main address:"%}</label> <span class='value'>{{ item.associated_file.address }}</span></p>
+{% if item.associated_file.address_complement %}<p><label>{%trans "Complement:"%}</label> <span class='value'>{{ item.associated_file.address_complement }}</span></p>{%endif%}
+{% if item.associated_file.postal_code %}<p><label>{%trans "Postal code:"%}</label> <span class='value'>{{ item.associated_file.postal_code }}</span></p>{%endif%}
+
+{% comment %}
+<p><label>{%trans "Lambert X:"%}</label> <span class='value'>{{ item.lambert_x }}</span></p>
+<p><label>{%trans "Lambert Y:"%}</label> <span class='value'>{{ item.lambert_y }}</span></p>
+<p><label>{%trans "Altitude (m NGF):"%}</label> <span class='value'>{{ item.altitude }}</span></p>
+{% endcomment %}
+<table>
+ <caption>{%trans "Associated parcels"%}</caption>
+ <tr>
+ <th>{% trans "Commune" %}</th>
+ <th>{% trans "Year" %}</th>
+ <th>{% trans "Section" %}</th>
+ <th>{% trans "Parcels" %}</th>
+ {#<th>{% trans "Owner" %}</th>#}
+ </tr>
+ {% for parcel in item.grouped_parcels %}
+ <tr>
+ <td class='string'>{{parcel.town}}</td>
+ <td>{{parcel.year}}</td>
+ <td>{{parcel.section}}</td>
+ <td>{{parcel.parcel_numbers|join:", "}}</td>
+ {#<td class='string'>{{operation.parcel.owner}}</td>#}
+ </tr>
+ {% empty %}
+ <tr><td colspan="4" class='no_items'>{% trans "No parcel associated to this operation" %}</td></tr>
+ {% endfor %}
+</table>
+
+<table>
+ <caption>{%trans "Administrative acts"%}</caption>
+ <tr>
+ <th>{% trans "Year" %}</th>
+ <th>{% trans "Reference" %}</th>
+ <th>{% trans "Type" %}</th>
+ <th>{% trans "Date" %}</th>
+ </tr>
+ {% for act in item.administrative_act.all %}
+ <tr>
+ <td>{{act.signature_date.year}}</td>
+ <td>{{act.ref_sra}}</td>
+ <td class='string'>{{act.act_type}}</td>
+ <td class="string">{{act.signature_date}}</td>
+ </tr>
+ {% empty %}
+ <tr><td colspan="4" class='no_items'>{% trans "No acts associated to this operation" %}</td></tr>
+ {% endfor %}
+</table>
+
+<h3>{% trans "Scientific documentation"%}</h3>
+<table>
+ <caption>{%trans "Documents"%}</caption>
+ <tr>
+ <th>{% trans "Title" %}</th>
+ <th>{% trans "Type" %}</th>
+ <th>{% trans "Authors" %}</th>
+ {#<th>{% trans "Localisation" %}</th>#}
+ </tr>
+ {% for doc in item.source.all %}
+ <tr>
+ <td class='string'>{{ doc.title }}</td>
+ <td class='string'>{{doc.source_type}}</td>
+ <td class='string'>{{ doc.authors.all|join:", " }}</td>
+ {#<td>{{ doc.localisation }}</td>#}
+ </tr>
+ {% empty %}
+ <tr><td colspan="4" class='no_items'>{% trans "No scientific document associated to this operation" %}</td></tr>
+ {% endfor %}
+</table>
+
+<table>
+ <caption>{%trans "Context records"%}</caption>
+ <tr>
+ <th>{% trans "ID" %}</th>
+ <th>{% trans "Type" %}</th>
+ <th>{% trans "Chronology" %}</th>
+ <th>{% trans "Description" %}</th>
+ <th>{% trans "Parcel" %}</th>
+ <th class='link'>&nbsp;</th>
+ </tr>
+ {% for context_record in item.context_record.all %}
+ <tr>
+ <td class='string'>{{ context_record.label }}</td>
+ <td class='string'>{{context_record.unit|default:""}}</td>
+ <td class='string'>{{ context_record.datings.all|join:", " }}</td>{# periods ?#}
+ <td class='string'>{{ context_record.description }}</td>
+ <td class='string'>{{ context_record.parcel.section }} - {{context_record.parcel.parcel_number}}</td>
+ <td class='link'><a href="#" onclick='load_window("{%url show-contextrecord context_record.pk ''%}")'>{% trans "Details" %}</a></td>
+ </tr>
+ {% empty %}
+ <tr><td colspan="6" class='no_items'>{% trans "No context record associated to this operation" %}</td></tr>
+ {% endfor %}
+</table>
+<div class='table'>
+<table>
+ <caption>{%trans "Finds"%}</caption>
+ <tr>
+ <th>{% trans "Find" %}</th>
+ <th>{% trans "Material type" %}</th>
+ <th>{% trans "Context record" %}</th>
+ <th>{% trans "Periods" %}</th>
+ <th>{% trans "Description" %}</th>
+ <th>{% trans "Weight" %}</th>
+ <th>{% trans "Numbers" %}</th>
+ <th>{% trans "Parcel" %}</th>
+ <th class='link'>&nbsp;</th>
+ </tr>
+ {% for context_record in item.context_record.all %}
+ {% for find in context_record.base_finds.all %}
+ <tr>
+ <td class="ref">{{ find.full_label }}</td>
+{# Displayed as (Patriarche operation code)-(Record unit label)-(Finds label). #}
+{# or displayed as (Year)-(index)-(Record unit label)-(Finds label). #}
+ <td class="ref">{{ find.material_type_label }}</td>
+ <td>{{find.context_record.label}}</td>
+ <td class='string'>{{ find.get_last_find.dating}}</td>{# TODO .all|join:", " ? #}
+ <td class='string'>{{ find.get_last_find.description }}</td>
+ <td>{{ find.get_last_find.weight }}</td>
+ <td>{{ find.get_last_find.item_number }}</td>
+ <td class="ref">{{ context_record.parcel.short_label }}</td>
+ <td class='link'><a href="#">{% trans "Details" %}</a></td>
+ {#<a href="#" onclick='load_window("{% url show-find find.pk%}");'>{%trans "Details"%}</a></td>#}
+ </tr>
+ {% empty %}
+ <tr><td colspan="9" class='no_items'>{% trans "No find associated to context record" %} {{context_record.short_label}}</td></tr>
+ {% endfor %}
+ {% empty %}
+ <tr><td colspan="9" class='no_items'>{% trans "No find associated to parcel" %} {{parcel.short_label}} {% trans "(no context record)" %}</td></tr>
+ {% endfor %}
+</table>
+</div>
+
+{% endblock %}
diff --git a/archaeological_operations/templates/ishtar/sheet_operation_pdf.html b/archaeological_operations/templates/ishtar/sheet_operation_pdf.html
new file mode 100644
index 000000000..9ef0edbf7
--- /dev/null
+++ b/archaeological_operations/templates/ishtar/sheet_operation_pdf.html
@@ -0,0 +1,18 @@
+{% extends "ishtar/sheet_operation.html" %}
+{% block css_head %}
+<link rel="stylesheet" href="{{MEDIA_URL}}/media/style_basic.css" />
+{% endblock %}
+{% block main_head %}
+{{ block.super }}
+<div id="pdfheader">
+Ishtar &ndash; {{APP_NAME}} &ndash; {{item}}
+</div>
+{% endblock %}
+{%block head_sheet%}{%endblock%}
+{%block main_foot%}
+<div id="pdffooter">
+&ndash; <pdf:pagenumber/> &ndash;
+</div>
+</body>
+</html>
+{%endblock%}
diff --git a/archaeological_operations/templates/ishtar/sheet_operation_window.html b/archaeological_operations/templates/ishtar/sheet_operation_window.html
new file mode 100644
index 000000000..3accaff42
--- /dev/null
+++ b/archaeological_operations/templates/ishtar/sheet_operation_window.html
@@ -0,0 +1,3 @@
+{% extends "ishtar/sheet_operation.html" %}
+{% block main_head %}{%endblock%}
+{% block main_foot %}{%endblock%}
diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py
index 23632f1cf..0da649d2d 100644
--- a/archaeological_operations/urls.py
+++ b/archaeological_operations/urls.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -72,5 +72,7 @@ urlpatterns += patterns('archaeological_operations.views',
url(r'get-operationsource/(?P<type>.+)?$',
'get_operationsource', name='get-operationsource'),
url(r'dashboard_operation/$', 'dashboard_operation',
- name='dashboard-operation')
+ name='dashboard-operation'),
+ url(r'autocomplete-patriarche/$', 'autocomplete_patriarche',
+ name='autocomplete-patriarche'),
)
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index 9aa2222ba..1ce4c4622 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -30,6 +30,30 @@ from wizards import *
from forms import *
import models
+def autocomplete_patriarche(request, non_closed=True):
+ person_types = request.user.ishtaruser.person.person_type
+ if (not request.user.has_perm('ishtar_common.view_operation',
+ models.Operation)
+ and not request.user.has_perm('ishtar_common.view_own_operation',
+ models.Operation)
+ and not person_types.rights.filter(
+ wizard__url_name='operation_search').count()):
+ return HttpResponse(mimetype='text/plain')
+ if not request.GET.get('term'):
+ return HttpResponse(mimetype='text/plain')
+ q = request.GET.get('term')
+ query = Q()
+ for q in q.split(' '):
+ query = query & Q(code_patriarche__startswith=q)
+ if non_closed:
+ query = query & Q(end_date__isnull=True)
+ limit = 15
+ operations = models.Operation.objects.filter(query)[:limit]
+ data = json.dumps([{'id':operation.code_patriarche,
+ 'value':operation.code_patriarche}
+ for operation in operations])
+ return HttpResponse(data, mimetype='text/plain')
+
def autocomplete_operation(request, non_closed=True):
person_types = request.user.ishtaruser.person.person_type
if (not request.user.has_perm('ishtar_common.view_operation',
@@ -70,9 +94,19 @@ def get_available_operation_code(request, year=None):
get_operation = get_item(models.Operation, 'get_operation', 'operation',
bool_fields = ['end_date__isnull'],
+ dated_fields = ['start_date__lte', 'start_date__gte',
+ 'excavation_end_date__lte', 'excavation_end_date__gte'],
extra_request_keys={'common_name':'common_name__icontains',
'end_date':'end_date__isnull',
- 'year_index':('year', 'operation_code')})
+ 'year_index':('year', 'operation_code'),
+ 'start_before':'start_date__lte',
+ 'start_after':'start_date__gte',
+ 'end_before':'excavation_end_date__lte',
+ 'end_after':'excavation_end_date__gte',
+ 'parcel_0':'parcels__section',
+ 'parcel_1':'parcels__parcel_number',
+ },
+ )
show_operation = show_item(models.Operation, 'operation')
revert_operation = revert_item(models.Operation)
@@ -88,7 +122,6 @@ get_administrativeactop = get_item(models.AdministrativeAct,
'operation__towns':'operation__towns__pk',
'act_type__intented_to':'act_type__intented_to'})
-
def dashboard_operation(request, *args, **kwargs):
"""
Operation dashboard
diff --git a/archaeological_operations/widgets.py b/archaeological_operations/widgets.py
new file mode 100644
index 000000000..0e84b2047
--- /dev/null
+++ b/archaeological_operations/widgets.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django import forms
+from django.forms import widgets
+
+class ParcelWidget(widgets.MultiWidget):
+ def __init__(self, attrs=None):
+ if not attrs:
+ attrs = {'class':'widget-parcel'}
+ elif 'class' not in attrs:
+ attrs['class'] = 'widget-parcel'
+ else:
+ attrs['class'] += ' widget-parcel'
+ _widgets = (
+ widgets.TextInput(attrs=attrs),
+ widgets.TextInput(attrs=attrs),
+ )
+ super(ParcelWidget, self).__init__(_widgets, attrs)
+
+ def decompress(self, value):
+ if value:
+ return value
+ return [None, None]
+
+ def format_output(self, rendered_widgets):
+ return u' / '.join(rendered_widgets)
diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py
index 3281a5723..4205144e6 100644
--- a/archaeological_operations/wizards.py
+++ b/archaeological_operations/wizards.py
@@ -27,16 +27,22 @@ from django.utils.translation import ugettext_lazy as _
from ishtar_common.wizards import Wizard, ClosingWizard, DeletionWizard, \
SourceWizard
import models
+from forms import ParcelForm
class OperationWizard(Wizard):
model = models.Operation
object_parcel_type = 'operation'
+ parcel_step_key = 'parcelsgeneral-'
def get_template_names(self):
templates = super(OperationWizard, self).get_template_names()
- current_step = self.steps. current
+ current_step = self.steps.current
if current_step.startswith('towns-'):
- templates = ['ishtar/wizard/towns_wizard.html'] + templates
+ #templates = ['ishtar/wizard/towns_wizard.html'] + templates
+ pass
+ if current_step.startswith('parcels-') or \
+ current_step.startswith('parcelsgeneral-') :
+ templates = ['ishtar/wizard/parcels_wizard.html'] + templates
return templates
def get_context_data(self, form, **kwargs):
@@ -121,7 +127,7 @@ class OperationWizard(Wizard):
Show a specific warning if no archaelogical file is provided
"""
datas = super(OperationWizard, self).get_formated_datas(forms)
- # if the general town form is used the advertissement is pertinent
+ # if the general town form is used the advertissement is relevant
has_no_af = [form.prefix for form in forms
if form.prefix == 'townsgeneral-operation'] and True
if has_no_af:
@@ -130,6 +136,33 @@ class OperationWizard(Wizard):
+ datas
return datas
+ def get_form_initial(self, step, data=None):
+ initial = super(OperationWizard, self).get_form_initial(step)
+ self.form_initialized = False
+ if not step.startswith(self.parcel_step_key):
+ return initial
+ if initial:
+ default = initial[-1].copy()
+ if 'parcel_number' in default:
+ default.pop('parcel_number')
+ initial.append(default)
+ # necessary to get the appropriate form number
+ self.form_initialized = True
+ elif data:
+ numbers, keys = set(), set()
+ for k in data:
+ items = k.split('-')
+ try:
+ numbers.add(int(items[-2]))
+ except (ValueError, IndexError):
+ continue
+ keys.add(items[-1])
+ if max(numbers) - 1:
+ initial = [dict([(k, data[step+'-'+unicode(max(numbers)-1)+'-'+k])
+ for k in keys if k != 'parcel_number'])]
+ self.form_initialized = True
+ return initial
+
class OperationModificationWizard(OperationWizard):
modification = True
@@ -145,7 +178,7 @@ class OperationDeletionWizard(DeletionWizard):
class OperationSourceWizard(SourceWizard):
model = models.OperationSource
- def get_form_initial(self, step):
+ def get_form_initial(self, step, data=None):
initial = super(OperationSourceWizard, self).get_form_initial(step)
# put default index and operation_id field in the main source form
general_form_key = 'selec-' + self.url_name