summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2011-01-14 01:17:05 +0100
committerÉtienne Loks <etienne.loks@peacefrogs.net>2011-01-14 01:17:05 +0100
commitdc3dd6ffd4be05b613a4bbba56e907b7ca2dea02 (patch)
treeb7fe8f621f6165f8b7a5cdb28fa2e1052d9e5e6b
parentf6d282bd88ef69501b0a01791e7a1eee22cb1a5b (diff)
downloadIshtar-dc3dd6ffd4be05b613a4bbba56e907b7ca2dea02.tar.bz2
Ishtar-dc3dd6ffd4be05b613a4bbba56e907b7ca2dea02.zip
Implementation of operation creation (refs #16)
-rw-r--r--ishtar/furnitures/admin.py6
-rw-r--r--ishtar/furnitures/forms.py195
-rw-r--r--ishtar/furnitures/menus.py9
-rw-r--r--ishtar/furnitures/models.py34
-rw-r--r--ishtar/furnitures/urls.py5
-rw-r--r--ishtar/furnitures/views.py6
6 files changed, 228 insertions, 27 deletions
diff --git a/ishtar/furnitures/admin.py b/ishtar/furnitures/admin.py
index b7821fb43..980349520 100644
--- a/ishtar/furnitures/admin.py
+++ b/ishtar/furnitures/admin.py
@@ -69,9 +69,9 @@ class FileAdmin(HistorizedObjectAdmin):
admin.site.register(models.File, FileAdmin)
class OperationAdmin(HistorizedObjectAdmin):
- list_display = ['name', 'operation_code', 'start_date', 'end_date',
+ list_display = ['year', 'operation_code', 'start_date', 'end_date',
'operation_type']
- list_filter = ("operation_type",)
+ list_filter = ("year", "operation_type",)
search_fields = ['towns__name', 'operation_code']
if settings.COUNTRY == 'fr':
list_display += ['code_patriarche']
@@ -197,7 +197,7 @@ basic_models = [models.PersonType, models.IshtarUser, models.FileType,
models.OperationType, models.DatingType, models.DatingQuality,
models.SourceType, models.MaterialType, models.ParcelOwner,
models.WarehouseType, models.ActType, models.AuthorType,
- models.OrganizationType, models.TreatmentType]
+ models.OrganizationType, models.TreatmentType, models.RemainType]
if settings.COUNTRY == 'fr':
basic_models += [models.Arrondissement, models.Canton, models.SaisineType]
diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py
index 8d5ee6c91..5abfe90f9 100644
--- a/ishtar/furnitures/forms.py
+++ b/ishtar/furnitures/forms.py
@@ -133,11 +133,11 @@ class Wizard(NamedUrlSessionFormWizard):
if not lbl:
continue
value = cleaned_data[key]
+ if not value:
+ continue
if key in associated_models:
value = unicode(associated_models[key].objects.get(
pk=value))
- if not value:
- continue
form_datas.append((lbl, value, ''))
if form_datas:
datas.append((form.form_label, form_datas))
@@ -167,10 +167,14 @@ class Wizard(NamedUrlSessionFormWizard):
# datas not managed
continue
value = frm.cleaned_data[key]
+ if not value:
+ continue
value = associated_models[key].objects.get(pk=value)
m2m.append((key, value))
elif type(form.cleaned_data) == dict:
for key in form.cleaned_data:
+ if key.startswith('hidden_'):
+ continue
value = form.cleaned_data[key]
if key in associated_models:
value = associated_models[key].objects.get(pk=value)
@@ -292,12 +296,12 @@ class Wizard(NamedUrlSessionFormWizard):
def get_form_initial(self, request, storage, step):
current_obj = self.get_current_object(request, storage)
+ current_step = storage.get_current_step() or self.get_first_step(
+ request, storage)
if step.startswith('selec-') and step in self.form_list \
and 'pk' in self.form_list[step].associated_models:
model_name = self.form_list[step].associated_models['pk'
].__name__.lower()
- current_step = storage.get_current_step() or self.get_first_step(
- request, storage)
if step == current_step:
self.reset_wizard(request, storage)
val = model_name in request.session and request.session[model_name]
@@ -306,6 +310,17 @@ class Wizard(NamedUrlSessionFormWizard):
elif current_obj:
return self.get_instanced_init(current_obj, request, storage,
step)
+ current_form = self.form_list[current_step]
+ if hasattr(current_form, 'currents'):
+ initial = {}
+ for key in current_form.currents:
+ model_name = current_form.currents[key].__name__.lower()
+ val = model_name in request.session and \
+ request.session[model_name]
+ if val:
+ initial[key] = val
+ if initial:
+ return initial
return super(Wizard, self).get_form_initial(request, storage, step)
def get_instanced_init(self, obj, request, storage, step):
@@ -353,7 +368,7 @@ class FileWizard(Wizard):
def get_form(self, request, storage, step=None, data=None, files=None):
"""
- Manage formset
+ Manage towns
"""
if data:
data = data.copy()
@@ -385,7 +400,6 @@ class FileWizard(Wizard):
def get_extra_model(self, dct, request, storage, form_list):
dct = super(FileWizard, self).get_extra_model(dct, request, storage,
form_list)
- models.File.objects.filter(year=dct['year'])
current_ref = models.File.objects.filter(year=dct['year']
).aggregate(Max('numeric_reference'))["numeric_reference__max"]
dct['numeric_reference'] = current_ref and current_ref + 1 or 1
@@ -432,6 +446,7 @@ def get_now():
class FileFormSelection(forms.Form):
form_label = _("Archaelogical file")
associated_models = {'pk':models.File}
+ currents = {'pk':models.File}
pk = forms.IntegerField(label=_("References/location"),
widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'),
associated_model=models.File),
@@ -497,6 +512,8 @@ class TownFormSet(FormSet):
towns = []
for i in range(0, self.total_form_count()):
form = self.forms[i]
+ if not form.is_valid():
+ continue
if 'town' not in form.cleaned_data:
continue
town = form.cleaned_data['town']
@@ -618,3 +635,169 @@ file_modification_wizard = FileWizard([
'preventive-file_modification':is_preventive('general-file_modification')
},
url_name='file_modification',)
+
+class OperationWizard(Wizard):
+ model = models.Operation
+
+ def get_form(self, request, storage, step=None, data=None, files=None):
+ """
+ Manage towns
+ """
+ if data:
+ data = data.copy()
+ else:
+ data = {}
+ # manage the dynamic choice of towns
+ if not step:
+ step = self.determine_step(request, storage)
+ form = self.get_form_list(request, storage)[step]
+
+ # put hidden year field
+ general_form_key = 'general-' + self.url_name
+ if not data and step.startswith('refs-') \
+ and storage.prefix in request.session \
+ and 'step_data' in request.session[storage.prefix] \
+ and general_form_key in request.session[storage.prefix]['step_data']:
+ prefix = 'refs-' + self.url_name
+ year = int(request.session[storage.prefix]['step_data']\
+ [general_form_key][general_form_key+"-year"])
+ data[prefix+'-hidden_year'] = year
+ max_val = models.Operation.objects.filter(year=year).aggregate(
+ Max('operation_code'))["operation_code__max"]
+ data[prefix+'-operation_code'] = max_val and (max_val + 1) or 1
+ if step.startswith('towns-') and hasattr(form, 'management_form') \
+ and storage.prefix in request.session \
+ and 'step_data' in request.session[storage.prefix] \
+ and general_form_key in request.session[storage.prefix]['step_data']:
+ towns = []
+ try:
+ file_id = int(request.session[storage.prefix]['step_data']\
+ [general_form_key][general_form_key+"-associated_file"])
+ for town in models.File.objects.get(pk=file_id).towns.all():
+ towns.append((town.pk, unicode(town)))
+ except (ValueError, ObjectDoesNotExist):
+ pass
+ if not data:
+ # by default fill with all towns
+ data['towns'] = towns
+ data['TOWNS'] = sorted(towns, key=lambda x:x[1])
+ data = data or None
+ form = super(OperationWizard, self).get_form(request, storage, step,
+ data, files)
+ return form
+
+
+
+class OperationFormGeneral(forms.Form):
+ form_label = _("General")
+ associated_models = {'in_charge':models.Person,
+ 'associated_file':models.File,
+ 'operation_type':models.OperationType}
+ currents = {'associated_file':models.File}
+ in_charge = forms.IntegerField(label=_("Person in charge of the operation"),
+ widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person',
+ args=[models.PersonType.objects.get(txt_idx='head_scientist').pk]),
+ associated_model=models.Person),
+ validators=[models.valid_id(models.Person)])
+ associated_file = forms.IntegerField(label=_("Archaelogical file"),
+ widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'),
+ associated_model=models.File),
+ validators=[models.valid_id(models.File)])
+ operation_type = forms.ChoiceField(label=_("Operation type"),
+ choices=models.OperationType.get_types())
+ start_date = forms.DateField(label=_(u"Start date"), required=False,
+ initial=get_now, widget=widgets.JQueryDate)
+ end_date = forms.DateField(label=_(u"End date"), required=False,
+ widget=widgets.JQueryDate)
+ year = forms.IntegerField(label=_("Year"),
+ initial=lambda:datetime.datetime.now().year,
+ validators=[validators.MinValueValidator(1900),
+ validators.MaxValueValidator(2100)])
+ comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea,
+ required=False)
+
+class OperationFormReference(forms.Form):
+ form_label = _("References")
+ associated_models = {'in_charge':models.Person,
+ 'associated_file':models.File,
+ 'operation_type':models.OperationType}
+ currents = {'associated_file':models.File}
+ hidden_year = forms.IntegerField(widget=forms.HiddenInput)
+ operation_code = forms.IntegerField(label=u"Operation code")
+ if settings.COUNTRY == 'fr':
+ code_patriarche = forms.IntegerField(label=u"Code PATRIARCHE",
+ required=False)
+ code_dracar = forms.CharField(label=_(u"Code DRACAR"), required=False,
+ validators=[validators.MaxLengthValidator(10)])
+ def clean(self):
+ cleaned_data = self.cleaned_data
+ year = cleaned_data.get("hidden_year")
+ operation_code = cleaned_data.get("operation_code")
+ ops = models.Operation.objects.filter(year=year,
+ operation_code=operation_code).count()
+ if ops:
+ max_val = models.Operation.objects.filter(year=year).aggregate(
+ Max('operation_code'))["operation_code__max"]
+ raise forms.ValidationError(_(u"Operation code already exist for "
+ "year: %d - use a value bigger than %d") % (year, max_val))
+ return cleaned_data
+
+class SelectedTownForm(forms.Form):
+ form_label = _("Towns")
+ associated_models = {'town':models.Town}
+ town = forms.ChoiceField(label=_("Town"), choices=(),
+ validators=[models.valid_id(models.Town)])
+ def __init__(self, *args, **kwargs):
+ towns = None
+ if 'data' in kwargs and 'TOWNS' in kwargs['data']:
+ towns = kwargs['data']['TOWNS']
+ # clean data if not "real" data
+ prefix_value = kwargs['prefix'] + '-town'
+ if not [k for k in kwargs['data'].keys()
+ if k.startswith(prefix_value) and kwargs['data'][k]]:
+ kwargs['data'] = None
+ if 'files' in kwargs:
+ kwargs.pop('files')
+ super(SelectedTownForm, self).__init__(*args, **kwargs)
+ if towns:
+ self.fields['town'].choices = [('', '--')] + towns
+
+SelectedTownFormSet = formset_factory(SelectedTownForm, can_delete=True,
+ formset=TownFormSet)
+SelectedTownFormSet.form_label = _("Towns")
+
+class RemainForm(forms.Form):
+ form_label = _("Remain types")
+ associated_models = {'remain':models.RemainType}
+ remain = forms.ChoiceField(label=_("Remain type"), required=False,
+ choices=models.RemainType.get_types())
+
+class RemainFormSet(FormSet):
+ def clean(self):
+ """Checks that no remain types are duplicated."""
+ if any(self.errors):
+ return
+ remains = []
+ for i in range(0, self.total_form_count()):
+ form = self.forms[i]
+ if not form.is_valid():
+ continue
+ if 'remain_type' not in form.cleaned_data:
+ continue
+ remain = form.cleaned_data['remain_type']
+ if remain in remains:
+ raise forms.ValidationError, \
+ _("There are identical remain types.")
+ remains.append(remain)
+
+RemainFormSet = formset_factory(RemainForm, can_delete=True,
+ formset=RemainFormSet)
+RemainFormSet.form_label = _("Remain types")
+
+operation_creation_wizard = OperationWizard([
+ ('general-operation_creation', OperationFormGeneral),
+ ('refs-operation_creation', OperationFormReference),
+ ('towns-operation_creation', SelectedTownFormSet),
+ ('remains-operation_creation', RemainFormSet),
+ ('final-file_creation', FinalForm)],
+ url_name='operation_creation',)
diff --git a/ishtar/furnitures/menus.py b/ishtar/furnitures/menus.py
index f96ff9280..fb15745f3 100644
--- a/ishtar/furnitures/menus.py
+++ b/ishtar/furnitures/menus.py
@@ -66,8 +66,13 @@ class Menu:
access_controls=['change_file', 'change_own_file']),
MenuItem('file_deletion', _(u"File deletion"),
access_controls=['delete_file', 'delete_own_file']),
- ]),
-]
+ ]),
+ SectionItem('operation_management', _(u"Operation management"),
+ childs=[
+ MenuItem('operation_creation', _(u"Operation creation"),
+ access_controls=['add_operation', 'add_own_operation']),
+ ]),
+ ]
self.items = {}
def init(self):
diff --git a/ishtar/furnitures/models.py b/ishtar/furnitures/models.py
index f77fe6caf..e3c434f7a 100644
--- a/ishtar/furnitures/models.py
+++ b/ishtar/furnitures/models.py
@@ -79,6 +79,7 @@ class GeneralType(models.Model):
@classmethod
def get_types(cls):
+ yield ('', '--')
for item in cls.objects.filter(available=True).all():
yield (item.id, _(item.label))
@@ -288,28 +289,29 @@ class OperationType(GeneralType):
verbose_name = _(u"Operation type")
verbose_name_plural = _(u"Operation types")
-class VestigeType(GeneralType):
+class RemainType(GeneralType):
class Meta:
- verbose_name = _(u"Vestige type")
- verbose_name_plural = _(u"Vestige types")
+ verbose_name = _(u"Remain type")
+ verbose_name_plural = _(u"Remain types")
class Operation(BaseHistorizedItem, OwnPerms):
- name = models.CharField(_(u"Name"), max_length=120)
- start_date = models.DateField(_(u"Start date"))
- end_date = models.DateField(_(u"End date"))
+ start_date = models.DateField(_(u"Start date"), null=True, blank=True)
+ end_date = models.DateField(_(u"End date"), null=True, blank=True)
in_charge = models.ForeignKey('Person', related_name='+',
verbose_name=_(u"In charge"))
- operation_code = models.CharField(_(u"Operation code"), max_length=20)
+ year = models.IntegerField(_(u"Year"))
+ operation_code = models.IntegerField(_(u"Operation code"))
associated_file = models.ForeignKey(File, related_name='+',
verbose_name=_(u"File"))
operation_type = models.ForeignKey(OperationType, related_name='+',
verbose_name=_(u"Operation type"))
- vestiges = models.ManyToManyField("VestigeType")
+ remains = models.ManyToManyField("RemainType")
towns = models.ManyToManyField("Town")
if settings.COUNTRY == 'fr':
- code_patriarche = models.IntegerField(u"Code PATRIARCHE")
- code_pat = models.CharField(u"Code PAT", max_length=10)
- code_dracar = models.CharField(u"Code DRACAR", max_length=10)
+ code_patriarche = models.IntegerField(u"Code PATRIARCHE", null=True,
+ blank=True)
+ code_dracar = models.CharField(u"Code DRACAR", max_length=10, null=True,
+ blank=True)
comment = models.TextField(_(u"Comment"), null=True, blank=True)
history = HistoricalRecords()
@@ -324,10 +326,16 @@ class Operation(BaseHistorizedItem, OwnPerms):
)
def __unicode__(self):
- return self.name
+ items = [unicode(_('Intercommunal'))]
+ if self.towns.count() == 1:
+ items[0] = unicode(self.towns.all()[0])
+ items += [unicode(getattr(self, k))[:12] for k in ['year',
+ 'operation_code',]
+ if getattr(self, k)]
+ return u" - ".join(items)
-class Parcel(LightHistorizedItem) :
+class Parcel(LightHistorizedItem):
associated_file = models.ForeignKey(File, related_name='parcels',
blank=True, null=True, verbose_name=_(u"File"))
operation = models.ForeignKey(Operation, related_name='parcel', blank=True,
diff --git a/ishtar/furnitures/urls.py b/ishtar/furnitures/urls.py
index b7ff515af..85071a141 100644
--- a/ishtar/furnitures/urls.py
+++ b/ishtar/furnitures/urls.py
@@ -21,7 +21,8 @@ from django.conf.urls.defaults import *
from ishtar.urls import BASE_URL
from menus import menu
-from forms import file_creation_wizard, file_modification_wizard
+from forms import file_creation_wizard, file_modification_wizard,\
+ operation_creation_wizard
urlpatterns, actions = [], []
@@ -30,6 +31,8 @@ urlpatterns = patterns('',
name='file_creation'),
url(BASE_URL + r'file_modification/(?P<step>.+)$',
file_modification_wizard, name='file_modification'),
+ url(BASE_URL + r'operation_creation/(?P<step>.+)$',
+ operation_creation_wizard, name='operation_creation'),
)
for section in menu.childs:
for menu_item in section.childs:
diff --git a/ishtar/furnitures/views.py b/ishtar/furnitures/views.py
index 530984092..ab0a64560 100644
--- a/ishtar/furnitures/views.py
+++ b/ishtar/furnitures/views.py
@@ -32,7 +32,8 @@ from django.core import serializers
from ishtar import settings
from menus import menu
-from forms import file_creation_wizard, file_modification_wizard
+from forms import file_creation_wizard, file_modification_wizard,\
+ operation_creation_wizard
import models
def index(request):
@@ -46,7 +47,6 @@ def index(request):
def update_current_item(request):
if not request.is_ajax() and not request.method == 'POST':
return Http404()
- print request.POST
if 'value' in request.POST and 'item' in request.POST:
request.session[request.POST['item']] = request.POST['value']
return HttpResponse('ok')
@@ -159,3 +159,5 @@ def file_creation(request, dct, obj_id, *args, **kwargs):
def file_modification(request, dct, obj_id, *args, **kwargs):
return file_modification_wizard(request, *args, **kwargs)
+def operation_creation(request, dct, obj_id, *args, **kwargs):
+ return operation_creation_wizard(request, *args, **kwargs)