#!/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. """ Files forms definitions """ import datetime from django import forms 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 _ from ishtar import settings import models import widgets from forms import Wizard, FinalForm, FormSet, ClosingWizard, \ ClosingDateFormSelection, SearchWizard, formset_factory, get_now, \ reverse_lazy from forms_common import TownFormset, ParcelFormSet, \ get_town_field, get_person_field from forms_operations import OperationAdministrativeActWizard, \ AdministrativeActOpeForm, AdministrativeActOpeFormSelection, \ AdministrativeActDeletionWizard, FinalAdministrativeActDeleteForm, is_preventive 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) if not dct['numeric_reference']: 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 = get_town_field() in_charge = get_person_field(label=_(u"Person in charge"), person_type='sra_agent') file_type = forms.ChoiceField(label=_("File type"), choices=models.FileType.get_types()) saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[]) year = forms.IntegerField(label=_("Year")) def __init__(self, *args, **kwargs): super(FileSelect, self).__init__(*args, **kwargs) self.fields['saisine_type'].choices = models.SaisineType.get_types() self.fields['saisine_type'].help_text = models.SaisineType.get_help() class FileFormSelection(forms.Form): form_label = _("Archaeological file search") 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, source_full=reverse_lazy('get-file-full')), 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, new=True), 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=_(u"Year"), widget=forms.TextInput(attrs={'readonly':True})) numeric_reference = forms.IntegerField(label=_(u"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 = _(u"Address") associated_models = {'town':models.Town} total_surface = forms.IntegerField(required=False, widget=widgets.AreaWidget, label=_(u"Total surface (m²)"), 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 FileFormPreventive(forms.Form): form_label = _(u"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, new=True), 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, new=True), validators=[models.valid_id(models.Organization)]) permit_type = forms.ChoiceField(label=_(u"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 (m²)"), required=False, validators=[validators.MinValueValidator(0), validators.MaxValueValidator(999999999)]) if settings.COUNTRY == 'fr': saisine_type = forms.ChoiceField(label=_(u"Saisine type"), choices=[]) reception_date = forms.DateField(label=_(u"Reception date"), initial=get_now, widget=widgets.JQueryDate) def __init__(self, *args, **kwargs): super(FileFormPreventive, self).__init__(*args, **kwargs) self.fields['saisine_type'].choices = models.SaisineType.get_types() self.fields['saisine_type'].help_text = models.SaisineType.get_help() 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, type_key='file_type') }, url_name='file_creation',) class FileModificationWizard(FileWizard): modification = True file_modification_wizard = FileModificationWizard([ ('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, type_key='file_type') }, url_name='file_modification',) class FileClosingWizard(ClosingWizard): model = models.File fields = ['year', 'numeric_reference', 'internal_reference', 'file_type', 'in_charge', 'general_contractor', 'creation_date', 'reception_date', 'total_surface', 'total_developed_surface', 'address', 'address_complement', 'postal_code', 'comment'] if settings.COUNTRY == 'fr': fields += ['saisine_type', 'reference_number'] fields += ['towns'] class FinalFileClosingForm(FinalForm): confirm_msg = " " confirm_end_msg = _(u"Would you like to close this archaeological file?") file_closing_wizard = FileClosingWizard([ ('selec-file_closing', FileFormSelection), ('date-file_closing', ClosingDateFormSelection), ('final-file_closing', FinalFileClosingForm)], url_name='file_closing',) class FileDeletionWizard(FileClosingWizard): def get_formated_datas(self, forms): datas = super(FileDeletionWizard, self).get_formated_datas(forms) datas.append((_("Associated operations"), [])) for operation in models.Operation.objects.filter( associated_file=self.current_obj).all(): if operation.end_date: datas[-1][1].append(('', unicode(operation))) return datas def done(self, request, storage, form_list, **kwargs): obj = self.get_current_object(request, storage) for operation in models.Operation.objects.filter( associated_file=obj).all(): operation.delete() obj.delete() return render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) class FinalFileDeleteForm(FinalForm): confirm_msg = " " confirm_end_msg = _(u"Would you like to delete this archaelogical file ?") file_deletion_wizard = FileDeletionWizard([ ('selec-file_deletion', FileFormSelection), ('final-file_deletion', FinalFileDeleteForm)], url_name='file_deletion',) class FileAdministrativeActWizard(OperationAdministrativeActWizard): model = models.File class FileEditAdministrativeActWizard(FileAdministrativeActWizard): model = models.AdministrativeAct edit = True def get_associated_item(self, request, storage, dct): return self.get_current_object(request, storage).associated_file class AdministrativeActFileSelect(forms.Form): associated_file__towns = get_town_field() act_type = forms.ChoiceField(label=_("Act type"), choices=[]) def __init__(self, *args, **kwargs): super(AdministrativeActFileSelect, self).__init__(*args, **kwargs) self.fields['act_type'].choices = models.ActType.get_types( dct={'intented_to':'F'}) self.fields['act_type'].help_text = models.ActType.get_help( dct={'intented_to':'F'}) class AdministrativeActFileFormSelection(AdministrativeActOpeFormSelection): pk = forms.IntegerField(label="", required=False, widget=widgets.JQueryJqGrid(reverse_lazy('get-administrativeactfile'), AdministrativeActFileSelect(), models.AdministrativeAct, table_cols='TABLE_COLS_FILE'), validators=[models.valid_id(models.AdministrativeAct)]) class AdministrativeActFileForm(AdministrativeActOpeForm): act_type = forms.ChoiceField(label=_(u"Act type"), choices=[]) def __init__(self, *args, **kwargs): super(AdministrativeActFileForm, self).__init__(*args, **kwargs) self.fields['act_type'].choices = models.ActType.get_types( dct={'intented_to':'F'}) self.fields['act_type'].help_text = models.ActType.get_help( dct={'intented_to':'F'}) file_administrativeactfile_wizard = FileAdministrativeActWizard([ ('selec-file_administrativeactfile', FileFormSelection), ('administrativeact-file_administrativeactfile', AdministrativeActFileForm), ('final-file_administrativeactfile', FinalForm)], url_name='file_administrativeactfile',) file_administrativeactfile_modification_wizard = FileEditAdministrativeActWizard([ ('selec-file_administrativeactfile_modification', AdministrativeActFileFormSelection), ('administrativeact-file_administrativeactfile_modification', AdministrativeActFileForm), ('final-file_administrativeactfile_modification', FinalForm)], url_name='file_administrativeactfile_modification',) file_administrativeactfile_deletion_wizard = AdministrativeActDeletionWizard([ ('selec-file_administrativeactfile_deletion', AdministrativeActFileFormSelection), ('final-file_administrativeactfile_deletion', FinalAdministrativeActDeleteForm)], url_name='file_administrativeactfile_deletion',)