diff options
Diffstat (limited to 'ishtar/furnitures/forms_files.py')
| -rw-r--r-- | ishtar/furnitures/forms_files.py | 354 | 
1 files changed, 354 insertions, 0 deletions
| diff --git a/ishtar/furnitures/forms_files.py b/ishtar/furnitures/forms_files.py new file mode 100644 index 000000000..ae52fc8cc --- /dev/null +++ b/ishtar/furnitures/forms_files.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2011  É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. + +""" +Files forms definitions +""" +import datetime + +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, formset_factory, \ +                  get_now, reverse_lazy + +class FileWizard(Wizard): +    model = models.File +    object_parcel_type = 'associated_file' + +    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] +        town_form_key = 'towns-' + self.url_name +        if step.startswith('parcels-') and hasattr(form, 'management_form') \ +           and self.session_has_key(request, storage, town_form_key): +            towns = [] +            qdict = request.session[storage.prefix]['step_data'][town_form_key] +            for k in qdict.keys(): +                if k.endswith("town") and qdict[k]: +                    try: +                        town = models.Town.objects.get(pk=int(qdict[k])) +                        towns.append((town.pk, unicode(town))) +                    except (ObjectDoesNotExist, ValueError): +                        pass +            data['TOWNS'] = sorted(towns, key=lambda x:x[1]) +        form = super(FileWizard, self).get_form(request, storage, step, data, +                                                files) +        return form + +    def get_extra_model(self, dct, request, storage, form_list): +        dct = super(FileWizard, self).get_extra_model(dct, request, storage, +                                                      form_list) +        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 +        return dct + +    def done(self, request, storage, form_list, **kwargs): +        ''' +        Save parcels +        ''' +        r = super(FileWizard, self).done(request, storage, form_list, +                                         return_object=True, **kwargs) +        if type(r) not in (list, tuple) or len(r) != 2: +            return r +        obj, res = r +        obj.parcels.clear() +        for form in form_list: +            if not hasattr(form, 'prefix') \ +               or not form.prefix.startswith('parcels-') \ +               or not hasattr(form, 'forms'): +                continue +            for frm in form.forms: +                if not frm.is_valid(): +                    continue +                dct = frm.cleaned_data.copy() +                if 'parcel' in dct: +                    try: +                        parcel = models.Parcel.objects.get(pk=dct['parcel']) +                        setattr(parcel, self.object_parcel_type, obj) +                        parcel.save() +                    except (ValueError, ObjectDoesNotExist): +                        continue +                    continue +                try: +                    dct['town'] = models.Town.objects.get(pk=int(dct['town'])) +                except (ValueError, ObjectDoesNotExist): +                    continue +                dct['associated_file'], dct['operation'] = None, None +                dct[self.object_parcel_type] = obj +                if 'DELETE' in dct: +                    dct.pop('DELETE') +                parcel = models.Parcel.objects.filter(**dct).count() +                if not parcel: +                    dct['history_modifier'] = request.user +                    parcel = models.Parcel(**dct) +                    parcel.save() +        return res + +class FileSelect(forms.Form): +    towns = forms.IntegerField(label=_(u"Town"), +         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ +                     'autocomplete-town', associated_model=models.Town), +         validators=[models.valid_id(models.Town)]) +    file_type = forms.ChoiceField(label=_("File type"), +                                  choices=models.FileType.get_types()) +    saisine_type = forms.ChoiceField(label=_("Saisine type"), +                                  choices=models.SaisineType.get_types()) +    year = forms.IntegerField(label=_("Year")) + +class FileFormSelection(forms.Form): +    form_label = _("Archaeological file") +    associated_models = {'pk':models.File} +    currents = {'pk':models.File} +    pk = forms.IntegerField(label="", required=False, +       widget=widgets.JQueryJqGrid(reverse_lazy('get-file'), +                                   FileSelect(), models.File), +       validators=[models.valid_id(models.File)]) + +    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 a file.")) +        return cleaned_data + +class FileFormGeneral(forms.Form): +    form_label = _("General") +    associated_models = {'in_charge':models.Person, +                         'related_file':models.File, +                         'file_type':models.FileType} +    in_charge = forms.IntegerField(label=_("Person in charge"), +        widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person', +          args=[models.PersonType.objects.get(txt_idx='sra_agent').pk]), +        associated_model=models.Person), +        validators=[models.valid_id(models.Person)]) +    year = forms.IntegerField(label=_("Year"), +                              initial=lambda:datetime.datetime.now().year, +                              validators=[validators.MinValueValidator(1900), +                                          validators.MaxValueValidator(2100)]) +    numeric_reference = forms.IntegerField(label=_("Numeric reference"), +                widget=forms.HiddenInput, required=False) +    internal_reference = forms.CharField(label=_(u"Internal reference"), +max_length=60, validators=[models.is_unique(models.File, 'internal_reference')]) +    creation_date = forms.DateField(label=_(u"Creation date"), +                                    initial=get_now, widget=widgets.JQueryDate) +    file_type = forms.ChoiceField(label=_("File type"), +                                  choices=models.FileType.get_types()) +    related_file = forms.IntegerField(label=_("Related file"), required=False, +         widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'), +                                           associated_model=models.File), +         validators=[models.valid_id(models.File)]) +    comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, +                              required=False) + +class FileFormGeneralRO(FileFormGeneral): +    year = forms.IntegerField(label=_("Year"), +                        widget=forms.TextInput(attrs={'readonly':True})) +    numeric_reference = forms.IntegerField(label=_("Numeric reference"), +                        widget=forms.TextInput(attrs={'readonly':True})) +    internal_reference = forms.CharField(label=_(u"Internal reference"), +                        widget=forms.TextInput(attrs={'readonly':True},)) + +class FileFormAddress(forms.Form): +    form_label = _("Address") +    associated_models = {'town':models.Town} +    total_surface = forms.IntegerField(required=False, +                           widget=widgets.AreaWidget, +                           label=_(u"Total surface"), +                           validators=[validators.MinValueValidator(0), +                                       validators.MaxValueValidator(999999999)]) +    address = forms.CharField(label=_(u"Main address"), widget=forms.Textarea) +    address_complement = forms.CharField(label=_(u"Main address - complement"), +                                         required=False) +    postal_code = forms.CharField(label=_(u"Main address - postal code"), +                                  max_length=10) + +class TownForm(forms.Form): +    form_label = _("Towns") +    associated_models = {'town':models.Town} +    # !FIXME hard_link, reverse_lazy doen't seem to work with formsets +    town = forms.IntegerField(label=_(u"Town"), required=False, +         widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ +                     'autocomplete-town', associated_model=models.Town), +         validators=[models.valid_id(models.Town)]) + +class TownFormSet(FormSet): +    def clean(self): +        """Checks that no towns are duplicated.""" +        if any(self.errors): +            return +        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 or not form.cleaned_data['town']: +                continue +            town = form.cleaned_data['town'] +            if town in towns: +                raise forms.ValidationError, _("There are identical towns.") +            towns.append(town) + +TownFormSet = formset_factory(TownForm, can_delete=True, formset=TownFormSet) +TownFormSet.form_label = _("Towns") + +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, +                              initial=lambda:datetime.datetime.now().year, +                           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', 'year'): +            if not key in self.cleaned_data or not self.cleaned_data[key]: +                raise forms.ValidationError(_(u"All fields are required")) +        return self.cleaned_data + + +class ParcelFormSet(FormSet): +    def clean(self): +        """Checks that no parcels are duplicated.""" +        return clean_duplicated(self, ('town', 'parcel_number', 'year')) + +ParcelFormSet = formset_factory(ParcelForm, can_delete=True, +                                formset=ParcelFormSet) +ParcelFormSet.form_label = _("Parcels") + +class FileFormPreventive(forms.Form): +    form_label = _("Preventive informations") +    associated_models = {'general_contractor':models.Person, +                         'saisine_type':models.SaisineType, +                         'permit_type':models.PermitType, +                         'town_planning_service':models.Organization} +    general_contractor = forms.IntegerField(label=_(u"General contractor"), +            widget=widgets.JQueryAutoComplete( +                reverse_lazy('autocomplete-person', +         args=[models.PersonType.objects.get(txt_idx='general_contractor').pk]), +                associated_model=models.Person), +            validators=[models.valid_id(models.Person)]) +    town_planning_service = forms.IntegerField(required=False, +            label=_(u"Town planning service"), +            widget=widgets.JQueryAutoComplete( +                reverse_lazy('autocomplete-organization', +     args=[models.OrganizationType.objects.get(txt_idx='planning_service').pk]), +                associated_model=models.Organization), +            validators=[models.valid_id(models.Organization)]) +    permit_type = forms.ChoiceField(label=_("Permit type"), required=False, +                                  choices=models.PermitType.get_types()) +    permit_reference = forms.CharField(label=_(u"Permit reference"), +            required=False, validators=[validators.MaxLengthValidator(60)]) +    total_developed_surface = forms.IntegerField(widget=widgets.AreaWidget, +           label=_(u"Total developed surface"), +           required=False, validators=[validators.MinValueValidator(0), +                                       validators.MaxValueValidator(999999999)]) +    if settings.COUNTRY == 'fr': +        saisine_type = forms.ChoiceField(label=_("Saisine type"), +                                  choices=models.SaisineType.get_types()) +    reception_date = forms.DateField(label=_(u"Reception date"), +                                     initial=get_now, widget=widgets.JQueryDate) + +def is_preventive(form_name, model, type_key='file_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: +            type = int(request.session[storage.prefix]['step_data']\ +                                      [form_name][form_name+'-'+type_key]) +            return model.is_preventive(type, key) +        except ValueError: +            return False +    return func + +file_search_wizard = SearchWizard([('general-file_search', FileFormSelection)], +                            url_name='file_search',) + +file_creation_wizard = FileWizard([ +                            ('general-file_creation', FileFormGeneral), +                            ('address-file_creation', FileFormAddress), +                            ('towns-file_creation', TownFormSet), +                            ('parcels-file_creation', ParcelFormSet), +                            ('preventive-file_creation', FileFormPreventive), +                            ('final-file_creation', FinalForm)], +             condition_list={ +'preventive-file_creation':is_preventive('general-file_creation', models.FileType) +                            }, +                            url_name='file_creation',) + +file_modification_wizard = FileWizard([ +                          ('selec-file_modification', FileFormSelection), +                          ('general-file_modification', FileFormGeneralRO), +                          ('adress-file_modification', FileFormAddress), +                          ('towns-file_modification', TownFormSet), +                          ('parcels-file_modification', ParcelFormSet), +                          ('preventive-file_modification', FileFormPreventive), +                          ('final-file_modification', FinalForm)], +             condition_list={ +'preventive-file_modification':is_preventive('general-file_modification', +                                             models.FileType) +                            }, +                          url_name='file_modification',) | 
