#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2011 Étienne Loks # 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 . # See the file COPYING for details. """ Context records forms definitions """ import datetime from itertools import groupby from django import forms from django.core import validators from django.core.exceptions import ObjectDoesNotExist from django.db.models import Max from django.utils.translation import ugettext_lazy as _ from ishtar import settings import models import widgets from forms import Wizard, FinalForm, FormSet, SearchWizard, DeletionWizard, \ formset_factory, get_now, reverse_lazy, get_form_selection from forms_common import get_town_field, SourceForm, SourceWizard, \ SourceSelect, AuthorFormset from forms_operations import OperationSelect class RecordWizard(Wizard): model = models.ContextRecord edit = False def get_current_operation(self, request, storage): step = storage.get_current_step() if not step: return if step.endswith('_creation'): # an operation has been selected main_form_key = 'selec-' + self.url_name try: idx = int(self.session_get_value(request, storage, main_form_key, 'operation_id')) current_ope = models.Operation.objects.get(pk=idx) return current_ope except(TypeError, ValueError, ObjectDoesNotExist): pass current_cr = self.get_current_object(request, storage) if current_cr: return current_cr.parcel.operation def get_template_context(self, request, storage, form=None): """ Get the operation "reminder" on top of wizard forms """ context = super(RecordWizard, self).get_template_context(request, storage, form) operation = self.get_current_operation(request, storage) if not operation: return context items = [] if hasattr(operation, 'code_patriarche') and operation.code_patriarche: items.append(unicode(operation.code_patriarche)) items.append("-".join((unicode(operation.year), unicode(operation.operation_code)))) context['reminder'] = _("Current operation: ") + " - ".join(items) return context 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] general_form_key = 'general-' + self.url_name if step.startswith('general-'): if step.endswith('_creation'): # an operation has been selected main_form_key = 'selec-' + self.url_name try: idx = int(self.session_get_value(request, storage, main_form_key, 'operation_id')) current_obj = models.Operation.objects.get(pk=idx) data['operation'] = current_obj except(TypeError, ValueError, ObjectDoesNotExist): pass else: current_object = self.get_current_object(request, storage) data['context_record'] = current_object form = super(RecordWizard, self).get_form(request, storage, step, data, files) return form class RecordModifWizard(RecordWizard): modification = True model = models.ContextRecord class RecordSelect(forms.Form): parcel__town = get_town_field() operation__year = forms.IntegerField(label=_(u"Year")) datings__period = forms.ChoiceField(label=_(u"Period"), choices=[]) unit = forms.ChoiceField(label=_(u"Unit type"), choices=[]) def __init__(self, *args, **kwargs): super(RecordSelect, self).__init__(*args, **kwargs) self.fields['datings__period'].choices = \ models.Period.get_types() self.fields['datings__period'].help_text = \ models.Period.get_help() self.fields['unit'].choices = models.Unit.get_types() self.fields['unit'].help_text = models.Unit.get_help() class RecordFormSelection(forms.Form): form_label = _("Context record search") associated_models = {'pk':models.ContextRecord} currents = {'pk':models.ContextRecord} pk = forms.IntegerField(label="", required=False, widget=widgets.JQueryJqGrid(reverse_lazy('get-contextrecord'), RecordSelect(), models.ContextRecord, source_full=reverse_lazy('get-contextrecord-full')), validators=[models.valid_id(models.ContextRecord)]) def clean(self): cleaned_data = self.cleaned_data if 'pk' not in cleaned_data or not cleaned_data['pk']: raise forms.ValidationError(_(u"You should at least select one " u"context record.")) return cleaned_data class RecordFormGeneral(forms.Form): form_label = _("General") associated_models = {'parcel':models.Parcel, 'unit':models.Unit} pk = forms.IntegerField(required=False, widget=forms.HiddenInput) operation_id = forms.IntegerField(widget=forms.HiddenInput) parcel = forms.ChoiceField(label=_("Parcel"), choices=[]) label = forms.CharField(label=_(u"ID"), validators=[validators.MaxLengthValidator(200)]) description = forms.CharField(label=_(u"Description"), widget=forms.Textarea, required=False) length = forms.IntegerField(label=_(u"Length (cm)"), required=False) width = forms.IntegerField(label=_(u"Width (cm)"), required=False) thickness = forms.IntegerField(label=_(u"Thickness (cm)"), required=False) depth = forms.IntegerField(label=_(u"Depth (cm)"), required=False) unit = forms.ChoiceField(label=_("Unit"), required=False, choices=models.Unit.get_types()) 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'] or 'context_record' in kwargs['data']): if 'operation' in kwargs['data']: operation = kwargs['data']['operation'] if 'context_record' in kwargs['data'] and \ kwargs['data']['context_record']: operation = kwargs['data']['context_record'].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) self.fields['parcel'].choices = [('', '--')] if operation: self.fields['operation_id'].initial = operation.pk 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]) ) def clean(self): # manage unique context record ID cleaned_data = self.cleaned_data operation_id = cleaned_data.get("operation_id") label = cleaned_data.get("label") cr = models.ContextRecord.objects.filter(label=label, parcel__operation__pk=operation_id) if 'pk' in cleaned_data and cleaned_data['pk']: cr = cr.exclude(pk=cleaned_data['pk']) if cr.count(): raise forms.ValidationError(_(u"This ID already exist for " u"this operation.")) return cleaned_data class DatingForm(forms.Form): form_label = _("Dating") base_model = 'dating' associated_models = {'dating_type':models.DatingType, 'quality':models.DatingQuality, 'period':models.Period} period = forms.ChoiceField(label=_("Period"), choices=models.Period.get_types()) start_date = forms.IntegerField(label=_(u"Start date"), required=False) end_date = forms.IntegerField(label=_(u"End date"), required=False) quality = forms.ChoiceField(label=_("Quality"), required=False, choices=models.DatingQuality.get_types()) dating_type = forms.ChoiceField(label=_("Dating type"), required=False, choices=[]) def __init__(self, *args, **kwargs): super(DatingForm, self).__init__(*args, **kwargs) self.fields['dating_type'].choices = models.DatingType.get_types() self.fields['dating_type'].help_text = models.DatingType.get_help() DatingFormSet = formset_factory(DatingForm, can_delete=True, formset=FormSet) DatingFormSet.form_label = _("Dating") class RecordFormInterpretation(forms.Form): form_label = _("Interpretation") associated_models = {'activity':models.ActivityType, 'identification':models.IdentificationType,} has_furniture = forms.NullBooleanField(label=_(u"Has furniture?"), required=False) filling = forms.CharField(label=_(u"Filling"), widget=forms.Textarea, required=False) interpretation = forms.CharField(label=_(u"Interpretation"), widget=forms.Textarea, required=False) activity = forms.ChoiceField(label=_(u"Activity"), required=False, choices=[]) identification = forms.ChoiceField(label=_("Identification"), required=False, choices=[]) 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) def __init__(self, *args, **kwargs): super(RecordFormInterpretation, self).__init__(*args, **kwargs) self.fields['activity'].choices = models.ActivityType.get_types() self.fields['activity'].help_text = models.ActivityType.get_help() self.fields['identification'].choices = \ models.IdentificationType.get_types() self.fields['identification'].help_text = \ models.IdentificationType.get_help() record_search_wizard = SearchWizard([ ('general-record_search', RecordFormSelection)], url_name='record_search',) OperationRecordFormSelection = get_form_selection( 'OperationRecordFormSelection', _(u"Operation search"), 'operation_id', models.Operation, OperationSelect, 'get-operation', _(u"You should select an operation.")) record_creation_wizard = RecordWizard([ ('selec-record_creation', OperationRecordFormSelection), ('general-record_creation', RecordFormGeneral), ('datings-record_creation', DatingFormSet), ('interpretation-record_creation', RecordFormInterpretation), ('final-record_creation', FinalForm)], url_name='record_creation',) record_modification_wizard = RecordModifWizard([ ('selec-record_modification', RecordFormSelection), ('general-record_modification', RecordFormGeneral), ('datings-record_modification', DatingFormSet), ('interpretation-record_modification', RecordFormInterpretation), ('final-record_modification', FinalForm)], url_name='record_modification',) class RecordDeletionWizard(DeletionWizard): model = models.ContextRecord fields = ['label', 'parcel', 'description', 'length', 'width', 'thickness', 'depth', 'location', 'datings', 'units', 'has_furniture', 'filling', 'interpretation', 'taq', 'taq_estimated', 'tpq', 'tpq_estimated'] class RecordDeletionForm(FinalForm): confirm_msg = " " confirm_end_msg = _(u"Would you like to delete this context record?") record_deletion_wizard = RecordDeletionWizard([ ('selec-record_deletion', RecordFormSelection), ('final-record_deletion', RecordDeletionForm)], url_name='record_deletion',) ######################################### # Source management for context records # ######################################### class RecordSourceWizard(SourceWizard): model = models.ContextRecordSource SourceRecordFormSelection = get_form_selection( 'SourceRecordFormSelection', _(u"Context record search"), 'context_record', models.ContextRecord, RecordSelect, 'get-contextrecord', _(u"You should select a context record.")) record_source_creation_wizard = RecordSourceWizard([ ('selec-record_source_creation', SourceRecordFormSelection), ('source-record_source_creation', SourceForm), ('authors-record_source_creation', AuthorFormset), ('final-record_source_creation', FinalForm)], url_name='record_source_creation',) class RecordSourceSelect(SourceSelect): context_record__parcel__town = get_town_field( label=_(u"Town of the operation")) context_record__operation__year = forms.IntegerField( label=_(u"Year of the operation")) context_record__datings__period = forms.ChoiceField( label=_(u"Period of the context record"), choices=[]) context_record__unit = forms.ChoiceField( label=_(u"Unit type of the context record"), choices=[]) def __init__(self, *args, **kwargs): super(RecordSourceSelect, self).__init__(*args, **kwargs) self.fields['context_record__datings__period'].choices = \ models.Period.get_types() self.fields['context_record__datings__period'].help_text = \ models.Period.get_help() self.fields['context_record__unit'].choices = models.Unit.get_types() self.fields['context_record__unit'].help_text = models.Unit.get_help() RecordSourceFormSelection = get_form_selection( 'RecordSourceFormSelection', _(u"Documentation search"), 'pk', models.ContextRecordSource, RecordSourceSelect, 'get-contextrecordsource', _(u"You should select a document.")) record_source_modification_wizard = RecordSourceWizard([ ('selec-record_source_modification', RecordSourceFormSelection), ('source-record_source_modification', SourceForm), ('authors-record_source_modification', AuthorFormset), ('final-record_source_modification', FinalForm)], url_name='record_source_modification',) class RecordSourceDeletionWizard(DeletionWizard): model = models.ContextRecordSource fields = ['context_record', 'title', 'source_type', 'authors',] record_source_deletion_wizard = RecordSourceDeletionWizard([ ('selec-record_source_deletion', RecordSourceFormSelection), ('final-record_source_deletion', RecordDeletionForm)], url_name='record_source_deletion',)