#/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 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # See the file COPYING for details. """ Forms definition """ import datetime import re from django.core.urlresolvers import reverse from django.core import validators from django.core.exceptions import ObjectDoesNotExist from django.utils import formats from django.utils.functional import lazy from django.utils.translation import ugettext_lazy as _ from django.shortcuts import render_to_response from django.template import Context, RequestContext, loader from django.db.models import Max from django import forms from django.core.mail import send_mail from django.forms.formsets import formset_factory, BaseFormSet, \ DELETION_FIELD_NAME from django.contrib.auth.models import User from django.contrib.sites.models import Site from formwizard.forms import NamedUrlSessionFormWizard import models import widgets from ishtar import settings reverse_lazy = lazy(reverse, unicode) def clean_duplicated(formset, key_names): """Checks for duplicated.""" if any(formset.errors): return items = [] for i in range(0, formset.total_form_count()): form = formset.forms[i] if not form.is_valid(): continue item = [key_name in form.cleaned_data and form.cleaned_data[key_name] for key_name in key_names] if not [v for v in item if v]: continue if item in items: raise forms.ValidationError, \ _("There are identical items.") items.append(item) class FinalForm(forms.Form): final = True form_label = _("Confirm") class FormSet(BaseFormSet): def add_fields(self, form, index): super(FormSet, self).add_fields(form, index) form.fields[DELETION_FIELD_NAME].label = '' form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget() class Wizard(NamedUrlSessionFormWizard): model = None def get_wizard_name(self): """ As the class name can interfere when reused, use the url_name """ return self.url_name def get_template(self, request, storage): templates = ['default_wizard.html'] current_step = storage.get_current_step() or self.get_first_step( request, storage) if current_step == self.get_last_step(request, storage): templates = ['confirm_wizard.html'] + templates return templates def get_template_context(self, request, storage, form=None): """ Add previous and current steps to manage the wizard path """ context = super(Wizard, self).get_template_context(request, storage, form) step = self.get_first_step(request, storage) current_step = storage.get_current_step() or self.get_first_step( request, storage) context.update({'current_step':self.form_list[current_step]}) if step == current_step: return context previous_steps = [] while step: if step == current_step: break previous_steps.append(self.form_list[step]) step = self.get_next_step(request, storage, step) context.update({'previous_steps':previous_steps}) # not last step: validation if step != self.get_last_step(request, storage): return context final_form_list = [] for form_key in self.get_form_list(request, storage).keys(): form_obj = self.get_form(request, storage, step=form_key, data=storage.get_step_data(form_key), files=storage.get_step_files(form_key)) form_obj.is_valid() final_form_list.append(form_obj) last_form = final_form_list[-1] context.update({'datas':self.get_formated_datas(final_form_list)}) if hasattr(last_form, 'confirm_msg'): context.update({'confirm_msg':last_form.confirm_msg}) if hasattr(last_form, 'confirm_end_msg'): context.update({'confirm_end_msg':last_form.confirm_end_msg}) return context def get_formated_datas(self, forms): """ Get the data to present in the last page """ datas = [] for form in forms: form_datas = [] base_form = hasattr(form, 'forms') and form.forms[0] or form associated_models = hasattr(base_form, 'associated_models') and \ base_form.associated_models or {} if not hasattr(form, 'cleaned_data') and hasattr(form, 'forms'): cleaned_datas = [frm.cleaned_data for frm in form.forms if frm.is_valid()] if not cleaned_datas: continue elif not hasattr(form, 'cleaned_data'): continue else: cleaned_datas = type(form.cleaned_data) == list and \ form.cleaned_data \ or [form.cleaned_data] for cleaned_data in cleaned_datas: if not cleaned_data: continue if form_datas: form_datas.append(("", "", "spacer")) for key in cleaned_data: lbl = None if key.startswith('hidden_'): continue if hasattr(base_form, 'fields') and key in base_form.fields: lbl = base_form.fields[key].label if not lbl: continue value = cleaned_data[key] if not value and value != False: continue if type(value) == bool: if value == True: value = _("Yes") elif value == False: value = _("No") elif key in associated_models: value = unicode(associated_models[key].objects.get( pk=value)) form_datas.append((lbl, value, '')) if form_datas: datas.append((form.form_label, form_datas)) return datas def get_extra_model(self, dct, request, storage, form_list): dct['history_modifier'] = request.user return dct def done(self, request, storage, form_list, return_object=False, **kwargs): """ Save to the model """ dct, m2m = {}, [] for form in form_list: if not form.is_valid(): return self.render(request, storage, form) base_form = hasattr(form, 'forms') and form.forms[0] or form associated_models = hasattr(base_form, 'associated_models') and \ base_form.associated_models or {} if hasattr(form, 'forms'): for frm in form.forms: if not frm.is_valid(): continue for key in frm.cleaned_data: if key not in associated_models: # datas not managed continue value = frm.cleaned_data[key] if not value and value != False: continue value = associated_models[key].objects.get(pk=value) m2m.append((key, value)) elif type(form.cleaned_data) == dict: for key in form.cleaned_data: if key.startswith('hidden_'): continue value = form.cleaned_data[key] if key in associated_models: if value: value = associated_models[key].objects.get(pk=value) else: value = None dct[key] = value dct = self.get_extra_model(dct, request, storage, form_list) obj = self.get_current_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.save() for key, value in m2m: if value not in getattr(obj, key+'s').all(): getattr(obj, key+'s').add(value) obj.save() res = render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) return return_object and (obj, res) or res def get_form(self, request, storage, step=None, data=None, files=None): """ Manage formset """ if data: data = data.copy() if not step: step = self.determine_step(request, storage) form = self.get_form_list(request, storage)[step] if hasattr(form, 'management_form'): # manage deletion not_to_delete, to_delete = [], [] for key in data.keys(): items = key.split('-') if len(items) == 4: if items[2] not in to_delete and \ items[2] not in not_to_delete: del_key = "-".join(items[:3]+["DELETE"]) if del_key in data and data[del_key]: to_delete.append(items[2]) else: not_to_delete.append(items[2]) if items[2] in to_delete: data.pop(key) if to_delete: # reorganize for idx, number in enumerate(sorted(not_to_delete)): if unicode(idx) == number: continue for key in data.keys(): items = key.split('-') if len(items) == 3 and items[1] == number: ck = '-'.join([items[0], unicode(idx), items[2]]) data[ck] = data.pop(key)[0] # get a form key base_key = form.form.base_fields.keys()[0] init = self.get_form_initial(request, storage, step) total_field = len([key for key in data.keys() if base_key in key.split('-') and data[key]]) if init and not to_delete: total_field = max((total_field, len(init))) data[step + u'-INITIAL_FORMS'] = unicode(total_field) data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1) data = data or None form = super(Wizard, self).get_form(request, storage, step, data, files) return form def render_next_step(self, request, storage, form, **kwargs): """ Manage the modify or delete button in formset: next_step = current_step """ if request.POST.has_key('formset_modify') \ and request.POST['formset_modify'] \ or [key for key in request.POST.keys() if key.endswith('DELETE') and request.POST[key]]: return self.render(request, storage, form, **kwargs) return super(Wizard, self).render_next_step(request, storage, form, **kwargs) def process_post_request(self, request, storage, *args, **kwargs): """ Convert numerical step number to step name """ if request.POST.has_key('form_prev_step'): try: step_number = int(request.POST['form_prev_step']) post_data = request.POST.copy() post_data['form_prev_step'] = self.get_form_list(request, storage).keys()[step_number] request.POST = post_data except ValueError: pass return super(Wizard, self).process_post_request(request, storage, *args, **kwargs) @classmethod def session_has_key(cls, request, storage, form_key, key=None, multi=None): """ Check if the session has value of a specific form and (if provided) of a key """ test = storage.prefix in request.session \ and 'step_data' in request.session[storage.prefix] \ and form_key in request.session[storage.prefix]['step_data'] if not key or not test: return test key = key.startswith(form_key) and key or \ not multi and form_key + '-' + key or \ form_key + '-0-' + key #only check if the first field is available return key in request.session[storage.prefix]['step_data'][form_key] @classmethod def session_get_value(cls, request, storage, form_key, key, multi=False): """ Get the value of a specific form """ if not cls.session_has_key(request, storage, form_key, key, multi): return if not multi: key = key.startswith(form_key) and key or form_key + '-' + key return request.session[storage.prefix]['step_data'][form_key][key] vals = [] for k in request.session[storage.prefix]['step_data'][form_key]: if k.startswith(form_key) and k.endswith(key) and \ request.session[storage.prefix]['step_data'][form_key][k]: vals.append(request.session[storage.prefix]['step_data']\ [form_key][k]) return vals def get_current_object(self, request, storage): """ Get the current object for an instancied wizard """ current_obj = None main_form_key = 'selec-' + self.url_name try: idx = int(self.session_get_value(request, storage, main_form_key, 'pk')) current_obj = self.model.objects.get(pk=idx) except(TypeError, ObjectDoesNotExist): pass return current_obj def get_form_initial(self, request, storage, step): current_obj = self.get_current_object(request, storage) current_step = storage.get_current_step() or self.get_first_step( request, storage) if step.startswith('selec-') and step in self.form_list \ and 'pk' in self.form_list[step].associated_models: model_name = self.form_list[step].associated_models['pk' ].__name__.lower() if step == current_step: self.reset_wizard(request, storage) val = model_name in request.session and request.session[model_name] if val: return {'pk':val} elif current_obj: return self.get_instanced_init(current_obj, request, storage, step) current_form = self.form_list[current_step] if hasattr(current_form, 'currents'): initial = {} for key in current_form.currents: model_name = current_form.currents[key].__name__.lower() val = model_name in request.session and \ request.session[model_name] if val: initial[key] = val if initial: return initial return super(Wizard, self).get_form_initial(request, storage, step) def get_instanced_init(self, obj, request, storage, step): """ Get initial data from an init """ current_step = storage.get_current_step() or self.get_first_step( request, storage) c_form = self.form_list[current_step] # make the current object the default item for the session request.session[obj.__class__.__name__.lower()] = unicode(obj.pk) initial = {} if hasattr(c_form, 'base_fields'): for field in c_form.base_fields.keys(): if hasattr(obj, field): value = getattr(obj, field) if hasattr(value, 'pk'): value = value.pk if value in (True, False): initial[field] = value elif value != None: initial[field] = unicode(value) elif hasattr(c_form, 'management_form'): initial = [] key = current_step.split('-')[0] if not hasattr(obj, key): return initial for child_obj in getattr(obj, key).all(): vals = {} keys = c_form.form.base_fields.keys() if len(keys) == 1: # only one field: must be the id of the object vals[keys[0]] = unicode(child_obj.pk) else: for field in keys: if hasattr(child_obj, field): value = getattr(child_obj, field) if hasattr(value, 'pk'): value = value.pk if value != None: vals[field] = unicode(value) if vals: initial.append(vals) return initial def get_now(): format = formats.get_format('DATE_INPUT_FORMATS')[0] value = datetime.datetime.now().strftime(format) return value regexp_name = re.compile(r'^[\w\- ]+$', re.UNICODE) name_validator = validators.RegexValidator(regexp_name, _(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid') class PersonWizard(Wizard): model = models.Person class PersonFormSelection(forms.Form): form_label = _("Person") associated_models = {'pk':models.Person} currents = {'pk':models.Person} pk = forms.IntegerField(label=_("Person"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=models.Person), validators=[models.valid_id(models.Person)]) class PersonForm(forms.Form): form_label = _("Identity") associated_models = {'attached_to':models.Organization, 'person_type':models.PersonType} title = forms.ChoiceField(label=_("Title"), choices=models.Person.TYPE) surname = forms.CharField(label=_(u"Surname"), max_length=20, validators=[name_validator]) name = forms.CharField(label=_(u"Name"), max_length=30, validators=[name_validator]) email = forms.CharField(label=_(u"Email"), max_length=40, required=False, validators=[validators.validate_email]) person_type = forms.ChoiceField(label=_("Person type"), choices=models.PersonType.get_types()) attached_to = forms.IntegerField(label=_("Current organization"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-organization'), associated_model=models.Organization), validators=[models.valid_id(models.Organization)], required=False) is_author = forms.BooleanField(label=_(u"Is an author?"), required=False) in_charge_storage = forms.BooleanField(required=False, label=_(u"In charge of a storage?")) person_creation_wizard = PersonWizard([ ('identity-person_creation', PersonForm), ('final-person_creation', FinalForm)], url_name='person_creation',) person_modification_wizard = PersonWizard([ ('selec-person_modification', PersonFormSelection), ('identity-person_modification', PersonForm), ('final-person_modification', FinalForm)], url_name='person_modification',) class AccountWizard(Wizard): model = models.Person def get_formated_datas(self, forms): datas = super(AccountWizard, self).get_formated_datas(forms) for form in forms: if not hasattr(form, "cleaned_data"): continue for key in form.cleaned_data: if key == 'hidden_password' and form.cleaned_data[key]: datas[-1][1].append((_("New password"), "*"*8)) return datas def done(self, request, storage, form_list, **kwargs): ''' Save the account ''' 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 person = self.get_current_object(request, storage) if not person: return self.render(request, storage, form) for key in dct.keys(): if key.startswith('hidden_password'): dct['password'] = dct.pop(key) try: account = models.IshtarUser.objects.get(person=person) account.username = dct['username'] account.email = dct['email'] except ObjectDoesNotExist: now = datetime.datetime.now() account = models.IshtarUser(person=person, username=dct['username'], email=dct['email'], first_name=person.surname, last_name=person.name, is_staff=False, is_active=True, is_superuser=False, last_login=now, date_joined=now) if dct['password']: account.set_password(dct['password']) account.save() if 'send_password' in dct and dct['send_password'] and \ settings.ADMINS: site = Site.objects.get_current() app_name = site and ("Ishtar - " + site.name) \ or "Ishtar" context = Context({'login':dct['username'], 'password':dct['password'], 'app_name':app_name, 'site': site and site.domain or "" }) t = loader.get_template('account_activation_email.txt') msg = t.render(context) subject = _(u"[%(app_name)s] Account creation/modification") % { "app_name":app_name} send_mail(subject, msg, settings.ADMINS[0][1], [dct['email']], fail_silently=True) res = render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) return res def get_form(self, request, storage, step=None, data=None, files=None): """ Display the "Send email" field if necessary """ form = super(AccountWizard, self).get_form(request, storage, step, data, files) if not hasattr(form, 'is_hidden'): return form if self.session_get_value(request, storage, 'account-account_management', 'hidden_password'): form.is_hidden = False return form class AccountForm(forms.Form): form_label = _("Account") associated_models = {'pk':models.Person} currents = {'pk':models.Person} pk = forms.IntegerField(widget=forms.HiddenInput, required=False) username = forms.CharField(label=_(u"Account"), max_length=30) email = forms.CharField(label=_(u"Email"), max_length=75, validators=[validators.validate_email]) hidden_password = forms.CharField(label=_(u"New password"), max_length=128, widget=forms.PasswordInput, required=False, validators=[validators.MinLengthValidator(4)]) hidden_password_confirm = forms.CharField( label=_(u"New password (confirmation)"), max_length=128, widget=forms.PasswordInput, required=False) def __init__(self, *args, **kwargs): if 'initial' in kwargs and 'pk' in kwargs['initial']: try: person = models.Person.objects.get(pk=kwargs['initial']['pk']) account = models.IshtarUser.objects.get(person=person) kwargs['initial'].update({'username':account.username, 'email':account.email}) except ObjectDoesNotExist: pass return super(AccountForm, self).__init__(*args, **kwargs) def clean(self): cleaned_data = self.cleaned_data password = cleaned_data.get("hidden_password") if password and password != cleaned_data.get("hidden_password_confirm"): raise forms.ValidationError(_(u"Your password and confirmation " u"password do not match.")) if not cleaned_data.get("pk"): models.is_unique(User, 'username')(cleaned_data.get("username")) if not password: raise forms.ValidationError(_(u"You must provide a correct \ password.")) return cleaned_data class FinalAccountForm(forms.Form): final = True form_label = _("Confirm") send_password = forms.BooleanField(label=_(u"Send the new password by " u"email?"), required=False) def __init__(self, *args, **kwargs): self.is_hidden = True return super(FinalAccountForm, self).__init__(*args, **kwargs) account_management_wizard = AccountWizard([ ('selec-account_management', PersonFormSelection), ('account-account_management', AccountForm), ('final-account_management', FinalAccountForm)], url_name='account_management',) class FileWizard(Wizard): model = models.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 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() try: dct['town'] = models.Town.objects.get(pk=int(dct['town'])) except (ValueError, ObjectDoesNotExist): continue dct['associated_file'] = obj dct['operation'] = None 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 = _("Archaelogical 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 FileFormSelection(forms.Form): form_label = _("Archaelogical file") associated_models = {'pk':models.File} currents = {'pk':models.File} pk = forms.IntegerField(label=_("References/location"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'), associated_model=models.File), validators=[models.valid_id(models.File)]) """ 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(label=_("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") 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( label=_("Total developed surface"), 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_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',) class FileClosingWizard(Wizard): 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'] def get_formated_datas(self, forms): datas = super(FileClosingWizard, self).get_formated_datas(forms) self.current_obj = None for form in forms: if not hasattr(form, "cleaned_data"): continue for key in form.cleaned_data: if key == 'pk': model = form.associated_models['pk'] self.current_obj = model.objects.get(pk=form.cleaned_data['pk']) if not self.current_obj: return datas res = {} for field in self.model._meta.fields + self.model._meta.many_to_many: if field.name not in self.fields: continue value = getattr(self.current_obj, field.name) if not value: continue if hasattr(value, 'all'): value = ", ".join([unicode(item) for item in value.all()]) if not value: continue else: value = unicode(value) res[field.name] = (field.verbose_name, value, '') if not datas and self.fields: datas = [['', []]] for field in self.fields: if field in res: datas[0][1].append(res[field]) return datas 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 FinalOperationDeleteForm(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', FinalOperationDeleteForm)], url_name='file_deletion',) """ file_closing_wizard = FileWizard([ ('selec-file_closing', FileFormSelection), ('date-operation_closing', OperationDateFormSelection), ('final-operation_closing', FinalOperationClosingForm)], url_name='operation_closing',) """ 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 associated_item = self.get_associated_item(request, storage, dct) if not associated_item: return self.render(request, storage, form) 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 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 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 AdministrativeActForm(forms.Form): form_label = _("General") associated_models = {'act_type':models.ActType, 'signatory':models.Person} act_type = forms.ChoiceField(label=_("Act type"), choices=models.ActType.get_types(dct={'intented_to':'F'})) signatory = forms.IntegerField(label=_("Signatory"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=models.Person), 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) class AdministrativeActFileSelect(forms.Form): associated_file__towns = forms.IntegerField(label=_(u"Town"), widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ 'autocomplete-town', associated_model=models.Town), validators=[models.valid_id(models.Town)]) act_type = forms.ChoiceField(label=_("Act type"), choices=models.ActType.get_types(dct={'intented_to':'F'})) class AdministrativeActFileFormSelection(forms.Form): form_label = _("Administrative Act") associated_models = {'pk':models.AdministrativeAct} currents = {'pk':models.AdministrativeAct} pk = forms.IntegerField(label="", required=False, widget=widgets.JQueryJqGrid(reverse_lazy('get-administrativeact'), AdministrativeActFileSelect(), models.AdministrativeAct, table_cols='TABLE_COLS_FILE'), 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 AdministrativeActDeletionWizard(FileClosingWizard): 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?") file_administrativeact_wizard = FileAdministrativeActWizard([ ('selec-file_administrativeact', FileFormSelection), ('administrativeact-file_administrativeact', AdministrativeActForm), ('final-file_administrativeact', FinalForm)], url_name='file_administrativeact',) file_administrativeact_modification_wizard = FileEditAdministrativeActWizard([ ('selec-file_administrativeact_modification', AdministrativeActFileFormSelection), ('administrativeact-file_administrativeact_modification', AdministrativeActForm), ('final-file_administrativeact_modification', FinalForm)], url_name='file_administrativeact_modification',) file_administrativeact_deletion_wizard = AdministrativeActDeletionWizard([ ('selec-file_administrativeact_deletion', AdministrativeActFileFormSelection), ('final-file_administrativeact_deletion', FinalAdministrativeActDeleteForm)], url_name='file_administrativeact_deletion',) class OperationWizard(Wizard): model = models.Operation def process_post_request(self, request, storage, *args, **kwargs): """ Change the town (and parcel) form to a free selection town's (parcel's) form if no archaelogical file is provided """ file_key = 'general-' + self.url_name + '-associated_file' if file_key in request.POST.keys(): town_form_key = 'towns-' + self.url_name parcel_form_key = 'parcels-' + self.url_name if request.POST[file_key]: self.form_list[unicode(town_form_key)] = SelectedTownFormSet self.form_list[unicode(parcel_form_key)] = SelectedParcelFormSet else: self.form_list[unicode(town_form_key)] = \ SelectedTownGeneralFormSet self.form_list[unicode(parcel_form_key)] = \ SelectedParcelGeneralFormSet return super(OperationWizard, self).process_post_request(request, storage, *args, **kwargs) 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 # put hidden year field for refs if data and step.startswith('refs-') \ and self.session_has_key(request, storage, general_form_key): prefix = 'refs-' + self.url_name year = int(request.session[storage.prefix]['step_data']\ [general_form_key][general_form_key+"-year"]) data[prefix+'-hidden_year'] = year data[prefix+'-hidden_ope'] = True # manage the dynamic choice of towns if step.startswith('towns-') and hasattr(form, 'management_form') \ and self.session_has_key(request, storage, general_form_key): 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 data['TOWNS'] = sorted(towns, key=lambda x:x[1]) 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, unicode(parcel))) except (ValueError, ObjectDoesNotExist): pass data['PARCELS'] = sorted(parcels, key=lambda x:x[1]) else: towns = [] town_form_key = 'towns-' + self.url_name town_ids = self.session_get_value(request, storage, town_form_key, 'town', multi=True) 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_form_initial(self, request, storage, step): initial = super(OperationWizard, self).get_form_initial(request, storage, step) if initial: return initial # put hidden year and default operation_code field for refs general_form_key = 'general-' + self.url_name initial = {} if step.startswith('refs-') \ and self.session_has_key(request, storage, general_form_key): year = int(request.session[storage.prefix]['step_data']\ [general_form_key][general_form_key+"-year"]) initial['hidden_year'] = year max_val = models.Operation.objects.filter(year=year).aggregate( Max('operation_code'))["operation_code__max"] initial['operation_code'] = max_val and (max_val + 1) or 1 return initial def get_formated_datas(self, forms): """ Show a specific warning if no archaelogical file is provided """ datas = super(OperationWizard, self).get_formated_datas(forms) # simple selection town is used if no Archaelogical File is provided has_af = [form for form in forms if isinstance(form, SelectedTownFormSet)] if not has_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): towns = forms.IntegerField(label=_(u"Town"), widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ 'autocomplete-town', associated_model=models.Town), validators=[models.valid_id(models.Town)]) operation_type = forms.ChoiceField(label=_("Operation type"), choices=models.OperationType.get_types()) remains = forms.ChoiceField(label=_("Remains"), choices=models.RemainType.get_types()) year = forms.IntegerField(label=_("Year")) class OperationFormSelection(forms.Form): form_label = _("Operation") 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), 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 OperationFormGeneral(forms.Form): form_label = _("General") associated_models = {'in_charge':models.Person, 'associated_file':models.File, 'operation_type':models.OperationType} currents = {'associated_file':models.File} 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), validators=[models.valid_id(models.Person)], required=False) associated_file = forms.IntegerField(label=_("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=_("Operation type"), choices=models.OperationType.get_types()) start_date = forms.DateField(label=_(u"Start date"), required=False, widget=widgets.JQueryDate) year = forms.IntegerField(label=_("Year"), initial=lambda:datetime.datetime.now().year, validators=[validators.MinValueValidator(1900), validators.MaxValueValidator(2100)]) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) class OperationFormReference(forms.Form): form_label = _("References") associated_models = {'in_charge':models.Person, 'associated_file':models.File, 'operation_type':models.OperationType} currents = {'associated_file':models.File} hidden_year = forms.IntegerField(widget=forms.HiddenInput) hidden_ope = forms.BooleanField(widget=forms.HiddenInput, required=False) operation_code = forms.IntegerField(label=_(u"Operation code")) 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)]) def clean(self): cleaned_data = self.cleaned_data if 'hidden_ope' in cleaned_data and cleaned_data['hidden_ope']: return cleaned_data year = cleaned_data.get("hidden_year") operation_code = cleaned_data.get("operation_code") ops = models.Operation.objects.filter(year=year, operation_code=operation_code).count() if ops: max_val = models.Operation.objects.filter(year=year).aggregate( Max('operation_code'))["operation_code__max"] raise forms.ValidationError(_(u"Operation code already exist for " "year: %(year)d - use a value bigger than %(last_val)d") % {'year':year, 'last_val':max_val}) return cleaned_data class OperationFormPreventive(forms.Form): form_label = _("Preventive informations - excavation") cost = forms.IntegerField(label=_(u"Cost"), 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: self.fields['town'].choices = [('', '--')] + towns SelectedTownFormSet = formset_factory(SelectedTownForm, can_delete=True, formset=TownFormSet) SelectedTownFormSet.form_label = _("Towns") SelectedTownGeneralFormSet = formset_factory(TownForm, can_delete=True, formset=TownFormSet) SelectedTownGeneralFormSet.form_label = _("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") 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 clean_duplicated(self, ['remain_type']) RemainFormset = formset_factory(RemainForm, can_delete=True, formset=RemainFormSet) RemainFormset.form_label = _("Remain types") class PeriodForm(forms.Form): form_label = _("Periods") 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 clean_duplicated(self, ['period']) PeriodFormset = formset_factory(PeriodForm, can_delete=True, formset=PeriodFormSet) PeriodFormset.form_label = _("Periods") operation_creation_wizard = OperationWizard([ ('general-operation_creation', OperationFormGeneral), ('refs-operation_creation', OperationFormReference), ('preventive-operation_creation', OperationFormPreventive), ('preventivediag-operation_creation', OperationFormPreventiveDiag), ('towns-operation_creation', SelectedTownFormSet), ('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') }, url_name='operation_creation',) operation_modification_wizard = OperationWizard([ ('selec-operation_modification', OperationFormSelection), ('general-operation_modification', OperationFormGeneral), ('refs-operation_modification', OperationFormReference), ('preventive-operation_modification', OperationFormPreventive), ('preventivediag-operation_modification', OperationFormPreventiveDiag), ('towns-operation_modification', SelectedTownFormSet), ('parcels-operation_modification', SelectedParcelFormSet), ('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') }, url_name='operation_modification',) class OperationDateFormSelection(forms.Form): form_label = _("Closing date") end_date = forms.DateField(label=_(u"Closing date"), widget=widgets.JQueryDate) class OperationClosingWizard(FileClosingWizard): model = models.Operation fields = ['year', 'operation_code', 'operation_type', 'associated_file', 'in_charge', 'start_date', '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', OperationDateFormSelection), ('final-operation_closing', FinalOperationClosingForm)], url_name='operation_closing',) class OperationDeletionWizard(OperationClosingWizard): 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 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',) class OperationAdministrativeActWizard(FileAdministrativeActWizard): model = models.Operation class OperationEditAdministrativeActWizard(FileAdministrativeActWizard): 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 = forms.IntegerField(label=_(u"Town"), widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ 'autocomplete-town', associated_model=models.Town), validators=[models.valid_id(models.Town)]) act_type = forms.ChoiceField(label=_("Act type"), choices=models.ActType.get_types(dct={'intented_to':'O'})) class AdministrativeActOpeFormSelection(AdministrativeActFileFormSelection): pk = forms.IntegerField(label="", required=False, widget=widgets.JQueryJqGrid(reverse_lazy('get-administrativeact'), AdministrativeActOpeSelect(), models.AdministrativeAct, table_cols='TABLE_COLS_OPE'), validators=[models.valid_id(models.AdministrativeAct)]) class AdministrativeActOpeForm(AdministrativeActForm): form_label = _("General") act_type = forms.ChoiceField(label=_("Act type"), choices=models.ActType.get_types(dct={'intented_to':'O'})) operation_administrativeact_wizard = OperationAdministrativeActWizard([ ('selec-operation_administrativeact', OperationFormSelection), ('administrativeact-operation_administrativeact', AdministrativeActOpeForm), ('final-operation_administrativeact', FinalForm)], url_name='operation_administrativeact',) operation_administrativeact_modification_wizard = \ OperationEditAdministrativeActWizard([ ('selec-operation_administrativeact_modification', AdministrativeActOpeFormSelection), ('administrativeact-operation_administrativeact_modification', AdministrativeActOpeForm), ('final-operation_administrativeact_modification', FinalForm)], url_name='operation_administrativeact_modification',) operation_administrativeact_deletion_wizard = AdministrativeActDeletionWizard([ ('selec-operation_administrativeact_deletion', AdministrativeActOpeFormSelection), ('final-operation_administrativeact_deletion', FinalAdministrativeActDeleteForm)], url_name='operation_administrativeact_deletion',)