diff options
Diffstat (limited to 'archaeological_operations/forms.py')
| -rw-r--r-- | archaeological_operations/forms.py | 804 | 
1 files changed, 804 insertions, 0 deletions
| diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py new file mode 100644 index 000000000..d4152d4fa --- /dev/null +++ b/archaeological_operations/forms.py @@ -0,0 +1,804 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2012  É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. + +""" +Operations forms definitions +""" +import datetime + +from django import forms +from django.conf import settings +from django.shortcuts import render_to_response +from django.template import RequestContext +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 _ + +import models +import widgets +from ishtar_common.forms import Wizard, FinalForm, FormSet, SearchWizard, \ +     ClosingWizard, ClosingDateFormSelection, DeletionWizard, formset_factory, \ +     get_now, reverse_lazy, get_form_selection +from ishtar_common.forms_common import TownForm, TownFormSet, TownFormset, \ +     AuthorFormset, SourceForm, SourceWizard, SourceSelect, \ +     SourceDeletionForm, get_town_field + +def is_preventive(form_name, model, type_key='operation_type', key=''): +    def func(self, request, storage): +        if storage.prefix not in request.session or \ +           'step_data' not in request.session[storage.prefix] or \ +           form_name not in request.session[storage.prefix]['step_data'] or\ +           form_name + '-' + type_key not in \ +                     request.session[storage.prefix]['step_data'][form_name]: +            return False +        try: +            typ = int(request.session[storage.prefix]['step_data']\ +                                     [form_name][form_name+'-'+type_key]) +            return model.is_preventive(typ, key) +        except ValueError: +            return False +    return func + +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=[models.valid_id(models.Town)]) +    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']: +            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(ParcelForm, self).__init__(*args, **kwargs) +        if towns: +            self.fields['town'].choices = [('', '--')] + towns + +    def clean(self): +        """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]: +            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 " +                                              u"fields are required.")) +        return self.cleaned_data + +class ParcelFormSet(FormSet): +    def clean(self): +        """Checks that no parcels are duplicated.""" +        return self.check_duplicate(('town', 'parcel_number', 'year'), +                                    _(u"There are identical parcels.")) + +ParcelFormSet = formset_factory(ParcelForm, can_delete=True, +                                formset=ParcelFormSet) +ParcelFormSet.form_label = _(u"Parcels") + +class OperationWizard(Wizard): +    model = models.Operation +    object_parcel_type = 'operation' + +    def get_template(self, request, storage): +        templates = super(OperationWizard, self).get_template(request, storage) +        current_step = storage.get_current_step() or self.get_first_step( +                                                            request, storage) +        if current_step.startswith('towns-'): +            templates = ['towns_wizard.html'] + templates +        return templates + +    def get_extra_context(self, request, storage): +        """ +        Return extra context for templates +        """ +        context = super(OperationWizard, self).get_extra_context(request, +                                                                 storage) +        step = self.determine_step(request, storage) +        if not step.startswith('towns-'): +            return context +        context['TOWNS'] = self.get_towns(request, storage) +        return context + +    def get_towns(self, request, storage): +        """ +        Obtention des villes disponibles +        """ +        general_form_key = 'general-' + self.url_name +        towns = [] +        file_id = self.session_get_value(request, storage, general_form_key, +                                             "associated_file") +        if file_id: +            try: +                for town in models.File.objects.get(pk=int(file_id) +                                                    ).towns.all(): +                    towns.append((town.pk, unicode(town))) +            except (ValueError, ObjectDoesNotExist): +                pass +            return sorted(towns, key=lambda x:x[1]) +        else: +            return -1 + +    def get_form(self, request, storage, step=None, data=None, files=None): +        """ +        Manage specifics fields +        """ +        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 +        # manage the dynamic choice of towns +        if step.startswith('towns-') and hasattr(form, 'management_form'): +            data['TOWNS'] = self.get_towns(request, storage) +        elif step.startswith('parcels') and hasattr(form, 'management_form'): +            file_id = self.session_get_value(request, storage, general_form_key, +                                             "associated_file") +            if file_id: +                parcels = [] +                try: +                    for parcel in models.File.objects.get(pk=int(file_id) +                                                        ).parcels.all(): +                        parcels.append((parcel.pk, parcel.short_label())) +                except (ValueError, ObjectDoesNotExist): +                    pass +                data['PARCELS'] = sorted(parcels, key=lambda x:x[1]) +            else: +                town_form_key = step.startswith('parcelsgeneral') \ +                                and 'townsgeneral-' or 'towns-' +                town_form_key += self.url_name +                town_ids = self.session_get_value(request, storage, +                                  town_form_key, 'town', multi=True) or [] +                towns = [] +                for town_id in town_ids: +                    try: +                        town = models.Town.objects.get(pk=int(town_id)) +                        towns.append((town.pk, unicode(town))) +                    except (ValueError, ObjectDoesNotExist): +                        pass +                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 + +    def get_formated_datas(self, forms): +        """ +        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 +        has_no_af = [form.prefix for form in forms +                  if form.prefix == 'townsgeneral-operation'] and True +        if has_no_af: +            datas = [[_(u"Warning: No Archaelogical File is provided. " +                      u"If you have forget it return to the first step."), []]]\ +                + datas +        return datas + +class OperationSelect(forms.Form): +    common_name = forms.CharField(label=_(u"Name"), max_length=30) +    towns = get_town_field() +    operation_type = forms.ChoiceField(label=_(u"Operation type"), +                                       choices=[]) +    remains = forms.ChoiceField(label=_(u"Remains"), +                                choices=models.RemainType.get_types()) +    year = forms.IntegerField(label=_("Year")) +    end_date = forms.NullBooleanField(label=_(u"Is open?")) + +    def __init__(self, *args, **kwargs): +        super(OperationSelect, self).__init__(*args, **kwargs) +        self.fields['operation_type'].choices = models.OperationType.get_types() +        self.fields['operation_type'].help_text = models.OperationType.get_help() + +class OperationFormSelection(forms.Form): +    form_label = _(u"Operation search") +    associated_models = {'pk':models.Operation} +    currents = {'pk':models.Operation} +    pk = forms.IntegerField(label="", required=False, +       widget=widgets.JQueryJqGrid(reverse_lazy('get-operation'), +             OperationSelect(), models.Operation, +             source_full=reverse_lazy('get-operation-full')), +       validators=[models.valid_id(models.Operation)]) + +    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 select an operation.")) +        return cleaned_data + +class OperationCodeInput(forms.TextInput): +    """Manage auto complete whene changing year in form""" +    def render(self, *args, **kwargs): +        name, value = args +        base_name = '-'.join(name.split('-')[:-1]) +        rendered = super(OperationCodeInput, self).render(*args, **kwargs) +        js = u"""\n    <script type="text/javascript"><!--// +        function initialyse_operation_code () { +            // if the form is in creation mode +            if(!$("#id_%(base_name)s-pk").val()){ +                $("#id_%(base_name)s-year").change(function() { +                    var year = $("#id_%(base_name)s-year").val(); +                    var url = "%(url)s" + year; +                    $.getJSON(url, function(data) { +                        $("#id_%(name)s").val(data.id); +                    }); +                }); +            } +        } +        $(document).ready(initialyse_operation_code()); +        //--></script>\n""" % {'base_name':base_name, 'name':name, +                               'url':reverse_lazy('get_available_operation_code')} +        return rendered + js + +class OperationFormGeneral(forms.Form): +    form_label = _(u"General") +    associated_models = {'in_charge':models.Person, +                         'associated_file':models.File, +                         'operation_type':models.OperationType} +    currents = {'associated_file':models.File} +    pk = forms.IntegerField(required=False, widget=forms.HiddenInput) +    in_charge = forms.IntegerField(label=_("Person in charge of the operation"), +        widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person', +          args=["_".join( +         [unicode(models.PersonType.objects.get(txt_idx='head_scientist').pk), +          unicode(models.PersonType.objects.get(txt_idx='sra_agent').pk)])]), +        associated_model=models.Person, new=True), +        validators=[models.valid_id(models.Person)], required=False) +    associated_file = forms.IntegerField(label=_(u"Archaelogical file"), +         widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'), +                                           associated_model=models.File), +         validators=[models.valid_id(models.File)], required=False) +    operation_type = forms.ChoiceField(label=_(u"Operation type"), +                                       choices=[]) +    start_date = forms.DateField(label=_(u"Start date"), required=False, +                                 widget=widgets.JQueryDate) +    excavation_end_date = forms.DateField(label=_(u"Excavation end date"), +                                 required=False, widget=widgets.JQueryDate) +    surface = forms.IntegerField(required=False, widget=widgets.AreaWidget, +                           label=_(u"Total surface (m²)"), +                           validators=[validators.MinValueValidator(0), +                                       validators.MaxValueValidator(999999999)]) +    year = forms.IntegerField(label=_(u"Year"), +                              initial=lambda:datetime.datetime.now().year, +                              validators=[validators.MinValueValidator(1900), +                                          validators.MaxValueValidator(2100)]) +    operation_code = forms.IntegerField(label=_(u"Operation code"), +                        initial=models.Operation.get_available_operation_code, +                        widget=OperationCodeInput) +    common_name = forms.CharField(label=_(u"Generic name"), required=False, +                                  max_length=120, widget=forms.Textarea) +    operator_reference = forms.CharField(label=_(u"Operator reference"), +                                         required=False, max_length=20) +    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)]) +    comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, +                              required=False) + +    def __init__(self, *args, **kwargs): +        super(OperationFormGeneral, self).__init__(*args, **kwargs) +        self.fields['operation_type'].choices = models.OperationType.get_types() +        self.fields['operation_type'].help_text = models.OperationType.get_help() + +    def clean(self): +        cleaned_data = self.cleaned_data +        # verify the logic between start date and excavation end date +        if cleaned_data['excavation_end_date']: +            if not self.cleaned_data['start_date']: +                raise forms.ValidationError(_(u"If you want to set an " +                      u"excavation end date you have to provide a start date.")) +            if cleaned_data['excavation_end_date'] < cleaned_data['start_date']: +                raise forms.ValidationError(_(u"The excavation end date "\ +                      u"cannot be before the start date.")) +        year = self.cleaned_data.get("year") +        operation_code = cleaned_data.get("operation_code") +        ops = models.Operation.objects.filter(year=year, +                                              operation_code=operation_code) +        # manage unique operation ID +        if 'pk' in cleaned_data and cleaned_data['pk']: +            ops = ops.exclude(pk=cleaned_data['pk']) +        if ops.count(): +            max_val = models.Operation.objects.filter(year=year).aggregate( +                                Max('operation_code'))["operation_code__max"] +            raise forms.ValidationError(_(u"Operation code already exist for " +                   u"year: %(year)d - use a value bigger than %(last_val)d") % { +                                               'year':year, 'last_val':max_val}) +        return self.cleaned_data + +class OperationFormPreventive(forms.Form): +    form_label = _(u"Preventive informations - excavation") +    cost = forms.IntegerField(label=_(u"Cost (€)"), required=False) +    scheduled_man_days = forms.IntegerField(label=_(u"Scheduled man-days"), +                                            required=False) +    optional_man_days = forms.IntegerField(label=_(u"Optional man-days"), +                                           required=False) +    effective_man_days = forms.IntegerField(label=_(u"Effective man-days"), +                                            required=False) +    if settings.COUNTRY == 'fr': +        fnap_financing = forms.FloatField(required=False, +                               label=u"Pourcentage de financement FNAP", +                               validators=[validators.MinValueValidator(0), +                                           validators.MaxValueValidator(100)]) + +class OperationFormPreventiveDiag(forms.Form): +    form_label = _("Preventive informations - diagnostic") +    if settings.COUNTRY == 'fr': +        zoning_prescription = forms.NullBooleanField(required=False, +                                            label=_(u"Prescription on zoning")) +        large_area_prescription = forms.NullBooleanField(required=False, +                                        label=_(u"Prescription on large area")) +        geoarchaeological_context_prescription = forms.NullBooleanField( +         required=False, label=_(u"Prescription on geoarchaeological context")) + +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 and towns != -1: +            self.fields['town'].choices = [('', '--')] + towns + +SelectedTownFormset = formset_factory(SelectedTownForm, can_delete=True, +                                formset=TownFormSet) +SelectedTownFormset.form_label = _(u"Towns") + +class SelectedParcelForm(forms.Form): +    form_label = _("Parcels") +    associated_models = {'parcel':models.Parcel} +    parcel = forms.ChoiceField(label=_("Parcel"), choices=(), +                             validators=[models.valid_id(models.Parcel)]) +    def __init__(self, *args, **kwargs): +        parcels = None +        if 'data' in kwargs and 'PARCELS' in kwargs['data']: +            parcels = kwargs['data']['PARCELS'] +            # clean data if not "real" data +            prefix_value = kwargs['prefix'] + '-parcel' +            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(SelectedParcelForm, self).__init__(*args, **kwargs) +        if parcels: +            self.fields['parcel'].choices = [('', '--')] + parcels + +SelectedParcelFormSet = formset_factory(SelectedParcelForm, can_delete=True, +                                formset=ParcelFormSet) +SelectedParcelFormSet.form_label = _("Parcels") + +SelectedParcelGeneralFormSet = formset_factory(ParcelForm, can_delete=True, +                                             formset=ParcelFormSet) +SelectedParcelGeneralFormSet.form_label = _("Parcels") + +class RemainForm(forms.Form): +    form_label = _("Remain types") +    base_model = 'remain' +    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.""" +        return self.check_duplicate(['remain_type'], +                                    _(u"There are identical remain types")) + +RemainFormset = formset_factory(RemainForm, can_delete=True, +                                formset=RemainFormSet) +RemainFormset.form_label = _("Remain types") + +class PeriodForm(forms.Form): +    form_label = _("Periods") +    base_model = 'period' +    associated_models = {'period':models.Period} +    period = forms.ChoiceField(label=_("Period"), required=False, +                                       choices=models.Period.get_types()) + +class PeriodFormSet(FormSet): +    def clean(self): +        """Checks that no period are duplicated.""" +        return self.check_duplicate(['period'], +                                    _(u"There are identical periods")) + +PeriodFormset = formset_factory(PeriodForm, can_delete=True, +                                formset=PeriodFormSet) +PeriodFormset.form_label = _("Periods") + +operation_search_wizard = SearchWizard([ +                          ('general-operation_search', OperationFormSelection)], +                          url_name='operation_search',) + +def has_associated_file(form_name, file_key='associated_file', negate=False): +    def func(self, request, storage): +        if storage.prefix not in request.session or \ +           'step_data' not in request.session[storage.prefix] or \ +           form_name not in request.session[storage.prefix]['step_data'] or\ +           form_name + '-' + file_key not in \ +                     request.session[storage.prefix]['step_data'][form_name]: +            return negate +        try: +            file_id = int(request.session[storage.prefix]['step_data']\ +                                      [form_name][form_name+'-'+file_key]) +            return not negate +        except ValueError: +            return negate +    return func + +operation_creation_wizard = OperationWizard([ +           ('general-operation_creation', OperationFormGeneral), +           ('preventive-operation_creation', OperationFormPreventive), +           ('preventivediag-operation_creation', OperationFormPreventiveDiag), +           ('townsgeneral-operation_creation', TownFormset), +           ('towns-operation_creation', SelectedTownFormset), +           ('parcelsgeneral-operation_creation', SelectedParcelGeneralFormSet), +           ('parcels-operation_creation', SelectedParcelFormSet), +           ('remains-operation_creation', RemainFormset), +           ('periods-operation_creation', PeriodFormset), +           ('final-operation_creation', FinalForm)], +             condition_list={ +'preventive-operation_creation':is_preventive('general-operation_creation', +                     models.OperationType, 'operation_type', 'prev_excavation'), +'preventivediag-operation_creation':is_preventive('general-operation_creation', +                     models.OperationType, 'operation_type', 'arch_diagnostic'), +'townsgeneral-operation_creation':has_associated_file( +                                     'general-operation_creation', negate=True), +'towns-operation_creation':has_associated_file('general-operation_creation'), +'parcelsgeneral-operation_creation':has_associated_file( +                                     'general-operation_creation', negate=True), +'parcels-operation_creation':has_associated_file('general-operation_creation'), +                            }, +                    url_name='operation_creation',) + +class OperationModificationWizard(OperationWizard): +    modification = True + +operation_modification_wizard = OperationModificationWizard([ +         ('selec-operation_modification', OperationFormSelection), +         ('general-operation_modification', OperationFormGeneral), +         ('preventive-operation_modification', OperationFormPreventive), +         ('preventivediag-operation_modification', OperationFormPreventiveDiag), +         ('towns-operation_modification', SelectedTownFormset), +         ('townsgeneral-operation_modification', TownFormset), +         ('parcels-operation_modification', SelectedParcelFormSet), +         ('parcelsgeneral-operation_modification', SelectedParcelGeneralFormSet), +         ('remains-operation_modification', RemainFormset), +         ('periods-operation_modification', PeriodFormset), +         ('final-operation_modification', FinalForm)], +             condition_list={ +'preventive-operation_modification':is_preventive( +                         'general-operation_modification', models.OperationType, +                         'operation_type', 'prev_excavation'), +'preventivediag-operation_modification':is_preventive( +                         'general-operation_modification', models.OperationType, +                         'operation_type', 'arch_diagnostic'), +'townsgeneral-operation_modification':has_associated_file( +                                 'general-operation_modification', negate=True), +'towns-operation_modification':has_associated_file( +                                 'general-operation_modification'), +'parcelsgeneral-operation_modification':has_associated_file( +                                 'general-operation_modification', negate=True), +'parcels-operation_modification':has_associated_file( +                                 'general-operation_modification'), +                            }, +                    url_name='operation_modification',) + +class OperationClosingWizard(ClosingWizard): +    model = models.Operation +    fields = ['year', 'operation_code', 'operation_type', 'associated_file', +'in_charge', 'start_date', 'excavation_end_date', 'comment', 'towns', 'remains'] + +class FinalOperationClosingForm(FinalForm): +    confirm_msg = " " +    confirm_end_msg = _(u"Would you like to close this operation?") + +operation_closing_wizard = OperationClosingWizard([ +                     ('selec-operation_closing', OperationFormSelection), +                     ('date-operation_closing', ClosingDateFormSelection), +                     ('final-operation_closing', FinalOperationClosingForm)], +                      url_name='operation_closing',) + +class OperationDeletionWizard(DeletionWizard): +    model = models.Operation +    fields = OperationClosingWizard.fields + +class OperationDeletionForm(FinalForm): +    confirm_msg = " " +    confirm_end_msg = _(u"Would you like to delete this operation?") + +operation_deletion_wizard = OperationDeletionWizard([ +                     ('selec-operation_deletion', OperationFormSelection), +                     ('final-operation_deletion', OperationDeletionForm)], +                      url_name='operation_deletion',) + +#################################### +# Source management for operations # +#################################### + +class OperationSourceWizard(SourceWizard): +    model = models.OperationSource +    def get_form_initial(self, request, storage, step): +        initial = super(OperationSourceWizard, self).get_form_initial(request, +                                                           storage, step) +        # put default index and operation_id field in the main source form +        general_form_key = 'selec-' + self.url_name +        if step.startswith('source-') \ +           and self.session_has_key(request, storage, general_form_key): +            gen_storage = request.session[storage.prefix]['step_data']\ +                                         [general_form_key] +            if general_form_key+"-operation" in gen_storage: +                operation_id = int(gen_storage[general_form_key+"-operation"]) +            elif general_form_key+"-pk" in gen_storage: +                pk = int(gen_storage[general_form_key+"-pk"]) +                try: +                    source = models.OperationSource.objects.get(pk=pk) +                    operation_id = source.operation.pk +                except ObjectDoesNotExist: +                    pass +            if operation_id: +                initial['hidden_operation_id'] = operation_id +                if 'index' not in initial: +                    max_val = models.OperationSource.objects.filter( +                                    operation__pk=operation_id).aggregate( +                                        Max('index'))["index__max"] +                    initial['index'] = max_val and (max_val + 1) or 1 +        return initial + +class OperationSourceForm(SourceForm): +    pk = forms.IntegerField(required=False, widget=forms.HiddenInput) +    index = forms.IntegerField(label=_(u"Index")) +    hidden_operation_id = forms.IntegerField(label="", widget=forms.HiddenInput) + +    def __init__(self, *args, **kwargs): +        super(OperationSourceForm, self).__init__(*args, **kwargs) +        keyOrder = self.fields.keyOrder +        keyOrder.pop(keyOrder.index('index')) +        keyOrder.insert(keyOrder.index('source_type') + 1, 'index') + +    def clean(self): +        # manage unique operation ID +        cleaned_data = self.cleaned_data +        operation_id = cleaned_data.get("hidden_operation_id") +        index = cleaned_data.get("index") +        srcs = models.OperationSource.objects.filter(index=index, +                                                     operation__pk=operation_id) +        if 'pk' in cleaned_data and cleaned_data['pk']: +            srcs = srcs.exclude(pk=cleaned_data['pk']) +        if srcs.count(): +            max_val = models.OperationSource.objects.filter( +                                                     operation__pk=operation_id +                                   ).aggregate(Max('index'))["index__max"] +            operation = models.Operation.objects.get(pk=operation_id) +            raise forms.ValidationError(_(u"Index already exist for " +"operation: %(operation)s - use a value bigger than %(last_val)d") % { +                    "operation":unicode(operation), 'last_val':max_val}) +        return cleaned_data + +SourceOperationFormSelection = get_form_selection( +    'SourceOperationFormSelection', _(u"Operation search"), 'operation', +    models.Operation, OperationSelect, 'get-operation', +    _(u"You should select an operation.")) + +operation_source_creation_wizard = OperationSourceWizard([ +             ('selec-operation_source_creation', SourceOperationFormSelection), +             ('source-operation_source_creation',OperationSourceForm), +             ('authors-operation_source_creation', AuthorFormset), +             ('final-operation_source_creation', FinalForm)], +                  url_name='operation_source_creation',) + +class OperationSourceSelect(SourceSelect): +    operation__towns = get_town_field(label=_(u"Operation's town")) +    operation__operation_type = forms.ChoiceField(label=_(u"Operation type"), +                                                  choices=[]) +    operation__year = forms.IntegerField(label=_(u"Operation's year")) + +    def __init__(self, *args, **kwargs): +        super(OperationSourceSelect, self).__init__(*args, **kwargs) +        self.fields['operation__operation_type'].choices = \ +                                            models.OperationType.get_types() +        self.fields['operation__operation_type'].help_text = \ +                                            models.OperationType.get_help() + + +OperationSourceFormSelection = get_form_selection( +    'OperationSourceFormSelection', _(u"Documentation search"), 'pk', +    models.OperationSource, OperationSourceSelect, 'get-operationsource', +    _(u"You should select a document.")) + +operation_source_modification_wizard = OperationSourceWizard([ +         ('selec-operation_source_modification', OperationSourceFormSelection), +         ('source-operation_source_modification', OperationSourceForm), +         ('authors-operation_source_modification', AuthorFormset), +         ('final-operation_source_modification', FinalForm)], +          url_name='operation_source_modification',) + +class OperationSourceDeletionWizard(DeletionWizard): +    model = models.OperationSource +    fields = ['operation', 'title', 'source_type', 'authors',] + +operation_source_deletion_wizard = OperationSourceDeletionWizard([ +         ('selec-operation_source_deletion', OperationSourceFormSelection), +         ('final-operation_source_deletion', SourceDeletionForm)], +          url_name='operation_source_deletion',) + +################################################ +# Administrative act management for operations # +################################################ + +class OperationAdministrativeActWizard(OperationWizard): +    edit = False + +    def get_extra_model(self, dct, request, storage, form_list): +        dct['history_modifier'] = request.user +        return dct + +    def get_associated_item(self, request, storage, dct): +        return self.get_current_object(request, storage) + +    def save_model(self, dct, m2m, whole_associated_models, 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_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: +                if hasattr(admact, k): +                    setattr(admact, k, dct[k]) +        else: +            admact = models.AdministrativeAct(**dct) +        admact.save() +        res = render_to_response('wizard_done.html', {}, +                                  context_instance=RequestContext(request)) +        return res + +class OperationEditAdministrativeActWizard(OperationAdministrativeActWizard): +    model = models.AdministrativeAct +    edit = True +    def get_associated_item(self, request, storage, dct): +        return self.get_current_object(request, storage).operation + +class AdministrativeActOpeSelect(forms.Form): +    operation__towns = get_town_field() +    act_type = forms.ChoiceField(label=_("Act type"), choices=[]) + +    def __init__(self, *args, **kwargs): +        super(AdministrativeActOpeSelect, self).__init__(*args, **kwargs) +        self.fields['act_type'].choices = models.ActType.get_types( +                                                   dct={'intented_to':'O'}) +        self.fields['act_type'].help_text = models.ActType.get_help( +                                                   dct={'intented_to':'O'}) + +class AdministrativeActOpeFormSelection(forms.Form): +    form_label = _("Administrative act search") +    associated_models = {'pk':models.AdministrativeAct} +    currents = {'pk':models.AdministrativeAct} +    pk = forms.IntegerField(label="", required=False, +       widget=widgets.JQueryJqGrid(reverse_lazy('get-administrativeactop'), +            AdministrativeActOpeSelect(), models.AdministrativeAct, +            table_cols='TABLE_COLS_OPE'), +       validators=[models.valid_id(models.AdministrativeAct)]) + +    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 select an administrative" +                                           " act.")) +        return cleaned_data + +class AdministrativeActOpeForm(forms.Form): +    form_label = _("General") +    associated_models = {'act_type':models.ActType, +                         'signatory':models.Person} +    act_type = forms.ChoiceField(label=_("Act type"), choices=[]) +    signatory = forms.IntegerField(label=_("Signatory"), +         widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), +                                     associated_model=models.Person, new=True), +         validators=[models.valid_id(models.Person)]) +    act_object = forms.CharField(label=_(u"Object"), max_length=200, +                                 widget=forms.Textarea) +    signature_date = forms.DateField(label=_(u"Signature date"), +                                     widget=widgets.JQueryDate) +    if settings.COUNTRY == 'fr': +        ref_sra = forms.CharField(label=u"Référence SRA", max_length=15) + +    def __init__(self, *args, **kwargs): +        super(AdministrativeActOpeForm, self).__init__(*args, **kwargs) +        self.fields['act_type'].choices = models.ActType.get_types( +                                                   dct={'intented_to':'O'}) +        self.fields['act_type'].help_text = models.ActType.get_help( +                                                   dct={'intented_to':'O'}) + +class AdministrativeActDeletionWizard(ClosingWizard): +    model = models.AdministrativeAct +    fields = ['act_type', 'in_charge', 'operator', 'scientific', 'signatory', +              'operation', 'associated_file', 'signature_date', 'act_object',] +    if settings.COUNTRY == 'fr': +        fields += ['ref_sra'] + +    def done(self, request, storage, form_list, **kwargs): +        obj = self.get_current_object(request, storage) +        obj.delete() +        return render_to_response('wizard_done.html', {}, +                                  context_instance=RequestContext(request)) + +class FinalAdministrativeActDeleteForm(FinalForm): +    confirm_msg = " " +    confirm_end_msg = _(u"Would you like to delete this administrative act?") + +operation_administrativeactop_wizard = OperationAdministrativeActWizard([ +    ('selec-operation_administrativeactop', OperationFormSelection), +    ('administrativeact-operation_administrativeactop', AdministrativeActOpeForm), +    ('final-operation_administrativeactop', FinalForm)], +     url_name='operation_administrativeactop',) + +operation_administrativeactop_modification_wizard = \ +    OperationEditAdministrativeActWizard([ +       ('selec-operation_administrativeactop_modification', +                                            AdministrativeActOpeFormSelection), +       ('administrativeact-operation_administrativeactop_modification', +                                            AdministrativeActOpeForm), +       ('final-operation_administrativeactop_modification', FinalForm)], +       url_name='operation_administrativeactop_modification',) + +operation_administrativeactop_deletion_wizard = AdministrativeActDeletionWizard([ +                     ('selec-operation_administrativeactop_deletion', +                                 AdministrativeActOpeFormSelection), +                     ('final-operation_administrativeactop_deletion', +                                 FinalAdministrativeActDeleteForm)], +                      url_name='operation_administrativeactop_deletion',) | 
