diff options
-rw-r--r-- | ishtar/furnitures/forms.py | 233 | ||||
-rw-r--r-- | ishtar/furnitures/menus.py | 17 | ||||
-rw-r--r-- | ishtar/furnitures/models.py | 19 | ||||
-rw-r--r-- | ishtar/furnitures/urls.py | 2 | ||||
-rw-r--r-- | static/media/style.css | 4 |
5 files changed, 245 insertions, 30 deletions
diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py index 1f2640e5c..642da9b4b 100644 --- a/ishtar/furnitures/forms.py +++ b/ishtar/furnitures/forms.py @@ -22,6 +22,7 @@ Forms definition """ import datetime import re +from itertools import groupby from django.core.urlresolvers import reverse from django.core import validators @@ -155,7 +156,9 @@ class Wizard(NamedUrlSessionFormWizard): continue if form_datas: form_datas.append(("", "", "spacer")) - for key in cleaned_data: + items = hasattr(base_form, 'fields') and \ + base_form.fields.keyOrder or cleaned_data.keys() + for key in items: lbl = None if key.startswith('hidden_'): continue @@ -172,8 +175,11 @@ class Wizard(NamedUrlSessionFormWizard): elif value == False: value = _("No") elif key in associated_models: - value = unicode(associated_models[key].objects.get( - pk=value)) + item = associated_models[key].objects.get(pk=value) + if hasattr(item, 'short_label'): + value = item.short_label() + else: + value = unicode(item) form_datas.append((lbl, value, '')) if form_datas: datas.append((form.form_label, form_datas)) @@ -218,15 +224,31 @@ class Wizard(NamedUrlSessionFormWizard): else: value = None dct[key] = value + return self.save_model(dct, m2m, request, storage, form_list, + return_object) + + def get_saved_model(self): + """ + Permit a distinguo when saved model is not the base selected model + """ + return self.model + + def get_current_saved_object(self, request, storage): + """ + Permit a distinguo when saved model is not the base selected model + """ + return self.get_current_object(request, storage) + + def save_model(self, dct, m2m, request, storage, form_list, return_object): dct = self.get_extra_model(dct, request, storage, form_list) - obj = self.get_current_object(request, storage) + obj = self.get_current_saved_object(request, storage) if obj: for k in dct: if k.startswith('pk'): continue setattr(obj, k, dct[k]) else: - obj = self.model(**dct) + obj = self.get_saved_model()(**dct) obj.save() for key, value in m2m: if value not in getattr(obj, key+'s').all(): @@ -1020,35 +1042,21 @@ file_closing_wizard = FileWizard([ class FileAdministrativeActWizard(FileWizard): edit = False + def get_associated_item(self, request, storage, dct): return self.get_current_object(request, storage) - def done(self, request, storage, form_list, **kwargs): - ''' - Save the administrative act - ''' - dct = {} - for form in form_list: - if not form.is_valid(): - return self.render(request, storage, form) - associated_models = hasattr(form, 'associated_models') and \ - form.associated_models or {} - if type(form.cleaned_data) == dict: - for key in form.cleaned_data: - if key == 'pk': - continue - value = form.cleaned_data[key] - if key in associated_models and value: - value = associated_models[key].objects.get(pk=value) - dct[key] = value + def save(self, dct, m2m, request, storage, form_list, return_object): associated_item = self.get_associated_item(request, storage, dct) if not associated_item: - return self.render(request, storage, form) + return self.render(request, storage, form_list[-1]) if isinstance(associated_item, models.File): dct['associated_file'] = associated_item elif isinstance(associated_item, models.Operation): dct['operation'] = associated_item dct['history_modifier'] = request.user + if 'pk' in dct: + dct.pop('pk') if self.edit: admact = self.get_current_object(request, storage) for k in dct: @@ -1581,3 +1589,180 @@ operation_administrativeact_deletion_wizard = AdministrativeActDeletionWizard([ ('final-operation_administrativeact_deletion', FinalAdministrativeActDeleteForm)], url_name='operation_administrativeact_deletion',) + +class RecordWizard(Wizard): + model = models.Operation + edit = False + + def get_form(self, request, storage, step=None, data=None, files=None): + """ + Get associated operation + """ + if data: + data = data.copy() + else: + data = {} + if not step: + step = self.determine_step(request, storage) + form = self.get_form_list(request, storage)[step] + current_object = self.get_current_object(request, storage) + if step.startswith('general-') and current_object: + data['operation'] = current_object + form = super(RecordWizard, self).get_form(request, storage, step, data, + files) + return form + + def get_saved_model(self): + return models.ContextRecord + + def get_current_saved_object(self, request, storage): + return None + + def save_model(self, dct, m2m, request, storage, form_list, return_object): + if 'pk' in dct: + dct.pop('pk') + return super(RecordWizard, self).save_model(dct, m2m, request, storage, + form_list, return_object) + + def done(self, request, storage, form_list, **kwargs): + ''' + Save datings + ''' + r = super(RecordWizard, self).done(request, storage, form_list, + return_object=True, **kwargs) + if type(r) not in (list, tuple) or len(r) != 2: + print 1 + print r + return r + print 2 + obj, res = r + for form in form_list: + if not hasattr(form, 'prefix') \ + or not form.prefix.startswith('datings-') \ + or not hasattr(form, 'forms'): + continue + datings = obj.datings.clear() + for frm in form.forms: + if not frm.is_valid(): + continue + dct = frm.cleaned_data.copy() + print dct + if not dct: + continue + try: + dct['period'] = models.Period.objects.get( + pk=int(dct['period'])) + except (ValueError, ObjectDoesNotExist): + continue + try: + dct['dating_type'] = models.DatingType.objects.get( + pk=int(dct['dating_type'])) + except (ValueError, ObjectDoesNotExist): + continue + try: + dct['quality'] = models.DatingQuality.objects.get( + pk=int(dct['quality'])) + except (ValueError, ObjectDoesNotExist): + continue + if 'DELETE' in dct: + dct.pop('DELETE') + dating = models.Dating.objects.filter(**dct).all() + if dating: + dating = dating[0] + else: + dating = models.Dating(**dct) + dating.save() + obj.datings.add(dating) + return res + + +class RecordFormGeneral(forms.Form): + form_label = _("General") + associated_models = {'parcel':models.Parcel,} + parcel = forms.ChoiceField(label=_("Parcel"), choices=[('', '--')]) + label = forms.CharField(label=_(u"Label"), + validators=[validators.MaxLengthValidator(200)]) + description = forms.CharField(label=_(u"Description"), + widget=forms.Textarea, required=False) + lenght = forms.IntegerField(label=_(u"Lenght")) + width = forms.IntegerField(label=_(u"Width")) + thickness = forms.IntegerField(label=_(u"Thickness")) + depth = forms.IntegerField(label=_(u"Depth")) + location = forms.CharField(label=_(u"Location"), widget=forms.Textarea, + required=False, validators=[validators.MaxLengthValidator(200)]) + + def __init__(self, *args, **kwargs): + operation = None + if 'data' in kwargs and kwargs['data'] and \ + 'operation' in kwargs['data']: + operation = kwargs['data']['operation'] + # clean data if not "real" data + prefix_value = kwargs['prefix'] + if not [k for k in kwargs['data'].keys() + if k.startswith(kwargs['prefix']) and kwargs['data'][k]]: + kwargs['data'] = None + if 'files' in kwargs: + kwargs.pop('files') + super(RecordFormGeneral, self).__init__(*args, **kwargs) + if operation and len(self.fields['parcel'].choices) == 1: + parcels = operation.parcels.all() + sort = lambda x: (x.town.name, x.section) + parcels = sorted(parcels, key=sort) + for key, gparcels in groupby(parcels, sort): + self.fields['parcel'].choices.append( + (" - ".join(key), [(parcel.pk, parcel.short_label()) for parcel in gparcels]) + ) + +class DatingForm(forms.Form): + form_label = _("Datings") + period = forms.ChoiceField(label=_("Period"), + choices=models.Period.get_types()) + start_date = forms.IntegerField(label=_(u"Start date")) + end_date = forms.IntegerField(label=_(u"End date")) + dating_type = forms.ChoiceField(label=_("Dating type"), + choices=models.DatingType.get_types()) + quality = forms.ChoiceField(label=_("Quality"), + choices=models.DatingQuality.get_types()) + +DatingFormSet = formset_factory(DatingForm, can_delete=True, + formset=FormSet) +DatingFormSet.form_label = _("Dating") + +class UnitForm(forms.Form): + form_label = _("Units") + associated_models = {'unit':models.Unit} + unit = forms.ChoiceField(label=_("Unit"), + choices=models.Unit.get_types()) + +class UnitFormSet(FormSet): + def clean(self): + return clean_duplicated(self, ['unit']) + +UnitFormSet = formset_factory(UnitForm, can_delete=True, + formset=UnitFormSet) +UnitFormSet.form_label = _("Unit") + +class RecordFormInterpretation(forms.Form): + form_label = _("Interpretation") + associated_models = {'parcel':models.Parcel,} + has_furniture = forms.BooleanField(label=_(u"Has furniture?")) + filling = forms.CharField(label=_(u"Filling"), + widget=forms.Textarea, required=False) + interpretation = forms.CharField(label=_(u"Interpretation"), + widget=forms.Textarea, required=False) + taq = forms.IntegerField(label=_(u"TAQ"), required=False) + taq_estimated = forms.IntegerField(label=_(u"Estimated TAQ"), + required=False) + tpq = forms.IntegerField(label=_(u"TPQ"), required=False) + tpq_estimated = forms.IntegerField(label=_(u"Estimated TPQ"), + required=False) + +record_creation_wizard = RecordWizard([ + ('selec-record_creation', OperationFormSelection), + ('general-record_creation', RecordFormGeneral), + ('datings-record_creation', DatingFormSet), + ('units-record_creation', UnitFormSet), + ('interpretation-record_creation', RecordFormInterpretation), + ('final-record_creation', FinalForm)], + url_name='record_creation',) + diff --git a/ishtar/furnitures/menus.py b/ishtar/furnitures/menus.py index 12c81ced3..d2fa5fba4 100644 --- a/ishtar/furnitures/menus.py +++ b/ishtar/furnitures/menus.py @@ -168,6 +168,23 @@ class Menu: 'delete_own_operation']), ],), ]), + SectionItem('record_management', _(u"Context record management"), + childs=[SectionItem('by_operation', _(u"By operation"), + childs=[ + MenuItem('record_creation', _(u"Creation"), + model=models.ContextRecord, + access_controls=['add_contextrecord', + 'add_own_contextrecord']), + MenuItem('record_modification', _(u"Modification"), + model=models.ContextRecord, + access_controls=['change_contextrecord', + 'change_own_contextrecord']), + MenuItem('record_deletion', _(u"Deletion"), + model=models.ContextRecord, + access_controls=['delete_contextrecord', + 'delete_own_contextrecord']), + ],), + ]) ] self.items = {} diff --git a/ishtar/furnitures/models.py b/ishtar/furnitures/models.py index cea0c1b4c..c1980f68c 100644 --- a/ishtar/furnitures/models.py +++ b/ishtar/furnitures/models.py @@ -456,7 +456,8 @@ class Parcel(LightHistorizedItem): null=True, verbose_name=_(u"Operation")) year = models.IntegerField(_(u"Year"), default=lambda:datetime.datetime.now().year) - town = models.ForeignKey("Town", related_name='+', verbose_name=_(u"Town")) + town = models.ForeignKey("Town", related_name='parcels', + verbose_name=_(u"Town")) section = models.CharField(_(u"Section"), max_length=4) parcel_number = models.CharField(_(u"Parcel number"), max_length=6) @@ -464,6 +465,11 @@ class Parcel(LightHistorizedItem): verbose_name = _(u"Parcel") verbose_name_plural = _(u"Parcels") + def short_label(self): + return u" - ".join([unicode(item) for item in \ + [self.town, self.section, self.parcel_number] + if item]) + def __unicode__(self): return u" - ".join([unicode(item) for item in \ [self.associated_file, self.operation, self.section, self.parcel_number] @@ -550,12 +556,15 @@ class ContextRecord(BaseHistorizedItem, OwnPerms): width = models.IntegerField(_(u"Width")) thickness = models.IntegerField(_(u"Thickness")) depth = models.IntegerField(_(u"Depth")) + location = models.CharField(_(u"Location"), blank=True, null=True, + max_length=200, + help_text=_(u"A short description of the location of the context record")) + datings = models.ManyToManyField(Dating) + units = models.ManyToManyField(Unit) has_furniture = models.BooleanField(u"Has furniture?") + filling = models.TextField(_(u"Filling"), blank=True, null=True) interpretation = models.TextField(_(u"Interpretation"), blank=True, null=True) - filling = models.TextField(_(u"Filling"), blank=True, null=True) - datings = models.ManyToManyField(Dating) - units = models.ManyToManyField(Unit) taq = models.IntegerField(_(u"TAQ"), blank=True, null=True, help_text=_("\"Terminus Ante Quem\" the context record can't have been " "created after this date")) @@ -566,8 +575,6 @@ class ContextRecord(BaseHistorizedItem, OwnPerms): " created before this date")) tpq_estimated = models.IntegerField(_(u"Estimated TPQ"), blank=True, null=True, help_text=_("Estimation of a \"Terminus Post Quem\"")) - location = models.CharField(_(u"Location"), max_length=200, - help_text=_(u"A short description of the location of the context record")) history = HistoricalRecords() class Meta: diff --git a/ishtar/furnitures/urls.py b/ishtar/furnitures/urls.py index c93f14c78..0e28043e2 100644 --- a/ishtar/furnitures/urls.py +++ b/ishtar/furnitures/urls.py @@ -63,6 +63,8 @@ urlpatterns = patterns('', url(BASE_URL + r'operation_administrativeact_deletion/(?P<step>.+)$', ishtar_forms.operation_administrativeact_deletion_wizard, name='operation_administrativeact_deletion'), + url(BASE_URL + r'record_creation/(?P<step>.+)$', + ishtar_forms.record_creation_wizard, name='record_creation'), ) for section in menu.childs: for menu_item in section.childs: diff --git a/static/media/style.css b/static/media/style.css index 27a31c08b..5d00ff793 100644 --- a/static/media/style.css +++ b/static/media/style.css @@ -29,6 +29,10 @@ label:first-letter { text-transform: uppercase; } +textarea{ + height:80px; +} + td{ text-align:left; } |