diff options
-rw-r--r-- | ishtar/furnitures/forms.py | 1058 | ||||
-rw-r--r-- | ishtar/furnitures/forms_common.py (renamed from ishtar/furnitures/forms_administrative.py) | 82 | ||||
-rw-r--r-- | ishtar/furnitures/forms_context_records.py | 235 | ||||
-rw-r--r-- | ishtar/furnitures/forms_files.py | 205 | ||||
-rw-r--r-- | ishtar/furnitures/forms_items.py | 240 | ||||
-rw-r--r-- | ishtar/furnitures/forms_main.py | 5 | ||||
-rw-r--r-- | ishtar/furnitures/forms_operations.py | 605 |
7 files changed, 1278 insertions, 1152 deletions
diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py index 4f23b49b2..efbae4b2b 100644 --- a/ishtar/furnitures/forms.py +++ b/ishtar/furnitures/forms.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -425,7 +425,6 @@ class Wizard(NamedUrlSessionFormWizard): not_to_delete.add(idx) return (to_delete, not_to_delete) - def get_form(self, request, storage, step=None, data=None, files=None): """ Manage formset @@ -680,19 +679,14 @@ class DeletionWizard(Wizard): return render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) - -class FileClosingWizard(DeletionWizard): - 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 ClosingWizard(Wizard): + # "close" an item + # to be define in the overloaded class + model = None + fields = [] def get_formated_datas(self, forms): - datas = super(FileClosingWizard, self).get_formated_datas(forms) + datas = super(ClosingWizard, self).get_formated_datas(forms) self.current_obj = None for form in forms: if not hasattr(form, "cleaned_data"): @@ -700,7 +694,8 @@ class FileClosingWizard(DeletionWizard): 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']) + self.current_obj = model.objects.get( + pk=form.cleaned_data['pk']) if not self.current_obj: return datas res = {} @@ -734,1038 +729,3 @@ class FileClosingWizard(DeletionWizard): return render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) -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_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 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-administrativeactfile'), - 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_administrativeactfile_wizard = FileAdministrativeActWizard([ - ('selec-file_administrativeactfile', FileFormSelection), - ('administrativeact-file_administrativeactfile', AdministrativeActForm), - ('final-file_administrativeactfile', FinalForm)], - url_name='file_administrativeactfile',) - -file_administrativeactfile_modification_wizard = FileEditAdministrativeActWizard([ - ('selec-file_administrativeactfile_modification', - AdministrativeActFileFormSelection), - ('administrativeact-file_administrativeactfile_modification', - AdministrativeActForm), - ('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',) - -class OperationWizard(FileWizard): - 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 - # 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'): - 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: - towns = [] - town_form_key = 'towns-' + self.url_name - town_ids = self.session_get_value(request, storage, - town_form_key, 'town', multi=True) or [] - 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_extra_model(self, dct, request, storage, form_list): - dct['history_modifier'] = request.user - return dct - - 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) - surface = forms.IntegerField(required=False, widget=widgets.AreaWidget, - label=_(u"Total surface"), - validators=[validators.MinValueValidator(0), - validators.MaxValueValidator(999999999)]) - 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 and towns != -1: - 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_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), - ('refs-operation_creation', OperationFormReference), - ('preventive-operation_creation', OperationFormPreventive), - ('preventivediag-operation_creation', OperationFormPreventiveDiag), - ('townsgeneral-operation_creation', SelectedTownGeneralFormSet), - ('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',) - -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), - ('townsgeneral-operation_modification', SelectedTownGeneralFormSet), - ('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 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 OperationDeletionForm(FinalForm): - confirm_msg = " " - confirm_end_msg = _(u"Would you like to delete this operation?") - -operation_deletion_wizard = DeletionWizard([ - ('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-administrativeactop'), - 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_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',) - -class RecordWizard(Wizard): - model = models.Operation - edit = False - - def get_form(self, request, storage, step=None, data=None, files=None): - """ - Get associated operation - """ - if data: - data = data.copy() - else: - data = {} - if not step: - step = self.determine_step(request, storage) - form = self.get_form_list(request, storage)[step] - current_object = self.get_current_object(request, storage) - if step.startswith('general-') and current_object: - data[self.model._meta.object_name] = current_object - form = super(RecordWizard, self).get_form(request, storage, step, data, - files) - return form - - def get_saved_model(self): - return models.ContextRecord - - def get_current_saved_object(self, request, storage): - """ - Permit a distinguo when saved model is not the base selected model - """ - if self.model == models.Operation: - return None - return self.get_current_object(request, storage) - - def save_model(self, dct, m2m, whole_associated_models, request, storage, - form_list, return_object): - if 'pk' in dct: - dct.pop('pk') - return super(RecordWizard, self).save_model(dct, m2m, - whole_associated_models, request, storage, form_list, return_object) - -class RecordModifWizard(RecordWizard): - model = models.ContextRecord - -class RecordSelect(forms.Form): - parcel__town = forms.IntegerField(label=_(u"Town"), - widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ - 'autocomplete-town', associated_model=models.Town), - validators=[models.valid_id(models.Town)]) - parcel__operation__year = forms.IntegerField(label=_("Year")) - datings__period = forms.ChoiceField(label=_("Period"), - choices=models.Period.get_types()) - unit = forms.ChoiceField(label=_("Unit type"), - choices=models.Unit.get_types()) - -class RecordFormSelection(forms.Form): - form_label = _("Context record") - associated_models = {'pk':models.ContextRecord} - currents = {'pk':models.ContextRecord} - pk = forms.IntegerField(label="", required=False, - widget=widgets.JQueryJqGrid(reverse_lazy('get-contextrecord'), - RecordSelect(), models.ContextRecord), - validators=[models.valid_id(models.ContextRecord)]) - - def clean(self): - cleaned_data = self.cleaned_data - if 'pk' not in cleaned_data or not cleaned_data['pk']: - raise forms.ValidationError(_(u"You should select a context " - u"record.")) - return cleaned_data - - -class RecordFormGeneral(forms.Form): - form_label = _("General") - associated_models = {'parcel':models.Parcel, 'unit':models.Unit} - parcel = forms.ChoiceField(label=_("Parcel"), choices=[]) - label = forms.CharField(label=_(u"ID"), - validators=[validators.MaxLengthValidator(200)]) - description = forms.CharField(label=_(u"Description"), - widget=forms.Textarea, required=False) - length = forms.IntegerField(label=_(u"Length"), required=False) - width = forms.IntegerField(label=_(u"Width"), required=False) - thickness = forms.IntegerField(label=_(u"Thickness"), required=False) - depth = forms.IntegerField(label=_(u"Depth"), required=False) - unit = forms.ChoiceField(label=_("Unit"), required=False, - choices=models.Unit.get_types()) - location = forms.CharField(label=_(u"Location"), widget=forms.Textarea, - required=False, validators=[validators.MaxLengthValidator(200)]) - - def __init__(self, *args, **kwargs): - operation = None - if 'data' in kwargs and kwargs['data'] and \ - ('Operation' in kwargs['data'] or 'ContextRecord' in kwargs['data']): - if 'Operation' in kwargs['data']: - operation = kwargs['data']['Operation'] - if 'ContextRecord' in kwargs['data']: - operation = kwargs['data']['ContextRecord'].parcel.operation - # clean data if not "real" data - prefix_value = kwargs['prefix'] - if not [k for k in kwargs['data'].keys() - if k.startswith(kwargs['prefix']) and kwargs['data'][k]]: - kwargs['data'] = None - if 'files' in kwargs: - kwargs.pop('files') - super(RecordFormGeneral, self).__init__(*args, **kwargs) - self.fields['parcel'].choices = [('', '--')] - if operation: - parcels = operation.parcels.all() - sort = lambda x: (x.town.name, x.section) - parcels = sorted(parcels, key=sort) - for key, gparcels in groupby(parcels, sort): - self.fields['parcel'].choices.append( - (" - ".join(key), [(parcel.pk, parcel.short_label()) for parcel in gparcels]) - ) - -class DatingForm(forms.Form): - form_label = _("Dating") - base_model = 'dating' - associated_models = {'dating_type':models.DatingType, - 'quality':models.DatingQuality, - 'period':models.Period} - period = forms.ChoiceField(label=_("Period"), - choices=models.Period.get_types()) - start_date = forms.IntegerField(label=_(u"Start date"), required=False) - end_date = forms.IntegerField(label=_(u"End date"), required=False) - quality = forms.ChoiceField(label=_("Quality"), required=False, - choices=models.DatingQuality.get_types()) - dating_type = forms.ChoiceField(label=_("Dating type"), required=False, - choices=models.DatingType.get_types()) - -DatingFormSet = formset_factory(DatingForm, can_delete=True, - formset=FormSet) -DatingFormSet.form_label = _("Dating") - -class RecordFormInterpretation(forms.Form): - form_label = _("Interpretation") - associated_models = {'activity':models.ActivityType, - 'identification':models.IdentificationType,} - has_furniture = forms.NullBooleanField(label=_(u"Has furniture?"), - required=False) - filling = forms.CharField(label=_(u"Filling"), - widget=forms.Textarea, required=False) - interpretation = forms.CharField(label=_(u"Interpretation"), - widget=forms.Textarea, required=False) - activity = forms.ChoiceField(label=_("Activity"), required=False, - choices=[]) - identification = forms.ChoiceField(label=_("Identification"), - required=False, choices=[]) - taq = forms.IntegerField(label=_(u"TAQ"), required=False) - taq_estimated = forms.IntegerField(label=_(u"Estimated TAQ"), - required=False) - tpq = forms.IntegerField(label=_(u"TPQ"), required=False) - tpq_estimated = forms.IntegerField(label=_(u"Estimated TPQ"), - required=False) - - def __init__(self, *args, **kwargs): - super(RecordFormInterpretation, self).__init__(*args, **kwargs) - self.fields['activity'].choices = models.ActivityType.get_types() - self.fields['identification'].choices = \ - models.IdentificationType.get_types() - -record_search_wizard = SearchWizard([ - ('general-record_search', RecordFormSelection)], - url_name='record_search',) - -record_creation_wizard = RecordWizard([ - ('selec-record_creation', OperationFormSelection), - ('general-record_creation', RecordFormGeneral), - ('datings-record_creation', DatingFormSet), - ('interpretation-record_creation', RecordFormInterpretation), - ('final-record_creation', FinalForm)], - url_name='record_creation',) - -record_modification_wizard = RecordModifWizard([ - ('selec-record_modification', RecordFormSelection), - ('general-record_modification', RecordFormGeneral), - ('datings-record_modification', DatingFormSet), - ('interpretation-record_modification', RecordFormInterpretation), - ('final-record_modification', FinalForm)], - url_name='record_modification',) - -class RecordDeletionWizard(DeletionWizard): - model = models.ContextRecord - fields = ['label', 'parcel', 'description', 'length', 'width', 'thickness', - 'depth', 'location', 'datings', 'units', 'has_furniture', - 'filling', 'interpretation', 'taq', 'taq_estimated', 'tpq', - 'tpq_estimated'] - -class RecordDeletionForm(FinalForm): - confirm_msg = " " - confirm_end_msg = _(u"Would you like to delete this context record?") - -record_deletion_wizard = RecordDeletionWizard([ - ('selec-record_deletion', RecordFormSelection), - ('final-record_deletion', RecordDeletionForm)], - url_name='record_deletion',) - -class ItemWizard(Wizard): - model = models.Item - - def get_extra_model(self, dct, request, storage, form_list): - dct = super(ItemWizard, self).get_extra_model(dct, request, storage, - form_list) - dct['order'] = 1 - if 'pk' in dct and type(dct['pk']) == models.ContextRecord: - dct['base_items__context_record'] = dct.pop('pk') - return dct - -class ItemFormBase(forms.Form): - form_label = _("Base item") - base_model = 'base_items' - base_items__label = forms.CharField(label=_(u"General ID"), - validators=[validators.MaxLengthValidator(60)]) - base_items__description = forms.CharField(label=_("General description"), - widget=forms.Textarea) - base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"), - required=False) - -class ItemForm(forms.Form): - form_label = _("Item") - associated_models = {'material_type':models.MaterialType,} - label = forms.CharField(label=_(u"ID"), - validators=[validators.MaxLengthValidator(60)]) - description = forms.CharField(label=_("Precise description"), - widget=forms.Textarea, required=False) - material_type = forms.ChoiceField(label=_("Material type"), - choices=models.MaterialType.get_types()) - volume = forms.IntegerField(label=_(u"Volume"), required=False) - weight = forms.IntegerField(label=_(u"Weight"), required=False) - item_number = forms.IntegerField(label=_(u"Item number"), required=False) - -class DateForm(forms.Form): - form_label = _("Dating") - base_model = 'dating' - associated_models = {'dating__dating_type':models.DatingType, - 'dating__quality':models.DatingQuality, - 'dating__period':models.Period} - dating__period = forms.ChoiceField(label=_("Period"), - choices=models.Period.get_types()) - dating__start_date = forms.IntegerField(label=_(u"Start date"), - required=False) - dating__end_date = forms.IntegerField(label=_(u"End date"), required=False) - dating__quality = forms.ChoiceField(label=_("Quality"), required=False, - choices=models.DatingQuality.get_types()) - dating__dating_type = forms.ChoiceField(label=_("Dating type"), - required=False, choices=models.DatingType.get_types()) - -item_creation_wizard = ItemWizard([ - ('selecrecord-item_creation', RecordFormSelection), - ('base_item-record_creation', ItemFormBase), - ('item-item_creation', ItemForm), - ('dating-item_creation', DateForm), - ('final-item_creation', FinalForm)], - url_name='item_creation',) - -class ItemSelect(forms.Form): - base_items__context_record__parcel__town = forms.IntegerField( - widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ - 'autocomplete-town', associated_model=models.Town), - validators=[models.valid_id(models.Town)], label=_(u"Town")) - base_items__context_record__parcel__operation__year = forms.IntegerField( - label=_("Year")) - dating__period = forms.ChoiceField( - label=_("Period"), choices=models.Period.get_types()) - material_type = forms.ChoiceField( - label=_("Material type"), choices=models.MaterialType.get_types()) - base_items__is_isolated = forms.NullBooleanField(label=_("Is isolated?")) - -class ItemFormSelection(forms.Form): - form_label = _("Item") - associated_models = {'pk':models.Item} - currents = {'pk':models.Item} - pk = forms.IntegerField(label="", required=False, - widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), - ItemSelect(), models.Item), - validators=[models.valid_id(models.Item)]) - -item_search_wizard = SearchWizard([ - ('general-item_search', ItemFormSelection)], - url_name='item_search',) - -item_modification_wizard = ItemWizard([ - ('selec-item_modification', ItemFormSelection), - ('item-item_modification', ItemForm), - ('dating-item_modification', DateForm), - ('final-item_modification', FinalForm)], - url_name='item_modification',) - -class TreatmentWizard(Wizard): - model = models.Treatment - -class BaseTreatmentForm(forms.Form): - form_label = _(u"Base treatment") - associated_models = {'treatment_type':models.TreatmentType, - 'person':models.Person, - 'location':models.Warehouse} - treatment_type = forms.ChoiceField(label=_(u"Treatment type"), - choices=models.TreatmentType.get_types()) - description = forms.CharField(label=_(u"Description"), - widget=forms.Textarea, required=False) - person = forms.IntegerField(label=_(u"Person"), - widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-person'), associated_model=models.Person), - validators=[models.valid_id(models.Person)]) - location = forms.IntegerField(label=_(u"Location"), - widget=widgets.JQueryAutoComplete( - reverse_lazy('autocomplete-warehouse'), associated_model=models.Warehouse, - new=True), - validators=[models.valid_id(models.Warehouse)]) - start_date = forms.DateField(label=_(u"Start date"), required=False, - widget=widgets.JQueryDate) - end_date = forms.DateField(label=_(u"End date"), required=False, - widget=widgets.JQueryDate) - -class ItemMultipleFormSelection(forms.Form): - form_label = _(u"Upstream items") - associated_models = {'items':models.Item} - items = forms.IntegerField(label="", required=False, - widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), - ItemSelect(), models.Item, multiple=True), - validators=[models.valid_id(models.Item)]) - -class ContainerForm(forms.Form): - form_label = _(u"Container") - associated_models = {'container_type':models.ContainerType,} - reference = forms.CharField(label=_(u"Reference")) - container_type = forms.ChoiceField(label=_(u"Container type"), - choices=models.ContainerType.get_types()) - comment = forms.CharField(label=_(u"Comment"), - widget=forms.Textarea, required=False) - -def check_treatment(form_name, type_key, type_list=[], not_type_list=[]): - type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk - for tpe in type_list] - not_type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk - for tpe in not_type_list] - 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 (not type_list or type in type_list) \ - and type not in not_type_list - except ValueError: - return False - return func - -class ResultItemForm(forms.Form): - form_label = _("Resulting item") - associated_models = {'material_type':models.MaterialType} - label = forms.CharField(label=_(u"ID"), - validators=[validators.MaxLengthValidator(60)]) - description = forms.CharField(label=_("Precise description"), - widget=forms.Textarea) - material_type = forms.ChoiceField(label=_("Material type"), - choices=models.MaterialType.get_types()) - volume = forms.IntegerField(label=_(u"Volume")) - weight = forms.IntegerField(label=_(u"Weight")) - item_number = forms.IntegerField(label=_(u"Item number")) - -ResultItemFormSet = formset_factory(ResultItemForm, can_delete=True, - formset=FormSet) -ResultItemFormSet.form_label = _(u"Resulting items") - -class UpstreamItemFormSelection(ItemFormSelection): - form_label = _(u"Upstream item") - -treatment_creation_wizard = TreatmentWizard([ - ('basetreatment-treatment_creation', BaseTreatmentForm), - ('selecitem-treatment_creation', UpstreamItemFormSelection), - ('multiselecitems-treatment_creation', ItemMultipleFormSelection), - ('container-treatment_creation', ContainerForm), - ('resultitem-treatment_creation', ResultItemForm), - ('resultitems-treatment_creation', ResultItemFormSet), - ('final-treatment_creation', FinalForm)], - condition_list={ -'selecitem-treatment_creation': - check_treatment('basetreatment-treatment_creation', 'treatment_type', - not_type_list=['physical_grouping']), -'multiselecitems-treatment_creation': - check_treatment('basetreatment-treatment_creation', 'treatment_type', - ['physical_grouping']), -'resultitems-treatment_creation': - check_treatment('basetreatment-treatment_creation', 'treatment_type', - ['split']), -'resultitem-treatment_creation': - check_treatment('basetreatment-treatment_creation', 'treatment_type', - not_type_list=['split']), -'container-treatment_creation': - check_treatment('basetreatment-treatment_creation', 'treatment_type', - ['packaging']), - }, - url_name='treatment_creation',) diff --git a/ishtar/furnitures/forms_administrative.py b/ishtar/furnitures/forms_common.py index c7bf47858..ab64babbd 100644 --- a/ishtar/furnitures/forms_administrative.py +++ b/ishtar/furnitures/forms_common.py @@ -1,4 +1,4 @@ -#/usr/bin/env python +#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> @@ -36,7 +36,8 @@ from ishtar import settings import models import widgets -from forms import Wizard, FinalForm, reverse_lazy, name_validator +from forms import Wizard, FinalForm, FormSet, formset_factory, reverse_lazy, \ + name_validator class PersonWizard(Wizard): model = models.Person @@ -227,5 +228,82 @@ account_management_wizard = AccountWizard([ ('final-account_management', FinalAccountForm)], url_name='account_management',) +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") diff --git a/ishtar/furnitures/forms_context_records.py b/ishtar/furnitures/forms_context_records.py new file mode 100644 index 000000000..464b090c1 --- /dev/null +++ b/ishtar/furnitures/forms_context_records.py @@ -0,0 +1,235 @@ +#!/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. + +""" +Context records 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, DeletionWizard, \ + formset_factory, get_now, reverse_lazy +from forms_operations import OperationFormSelection + +class RecordWizard(Wizard): + model = models.Operation + edit = False + + def get_form(self, request, storage, step=None, data=None, files=None): + """ + Get associated operation + """ + if data: + data = data.copy() + else: + data = {} + if not step: + step = self.determine_step(request, storage) + form = self.get_form_list(request, storage)[step] + current_object = self.get_current_object(request, storage) + if step.startswith('general-') and current_object: + data[self.model._meta.object_name] = current_object + form = super(RecordWizard, self).get_form(request, storage, step, data, + files) + return form + + def get_saved_model(self): + return models.ContextRecord + + def get_current_saved_object(self, request, storage): + """ + Permit a distinguo when saved model is not the base selected model + """ + if self.model == models.Operation: + return None + return self.get_current_object(request, storage) + + def save_model(self, dct, m2m, whole_associated_models, request, storage, + form_list, return_object): + if 'pk' in dct: + dct.pop('pk') + return super(RecordWizard, self).save_model(dct, m2m, + whole_associated_models, request, storage, form_list, return_object) + +class RecordModifWizard(RecordWizard): + model = models.ContextRecord + +class RecordSelect(forms.Form): + parcel__town = forms.IntegerField(label=_(u"Town"), + widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ + 'autocomplete-town', associated_model=models.Town), + validators=[models.valid_id(models.Town)]) + parcel__operation__year = forms.IntegerField(label=_("Year")) + datings__period = forms.ChoiceField(label=_("Period"), + choices=models.Period.get_types()) + unit = forms.ChoiceField(label=_("Unit type"), + choices=models.Unit.get_types()) + +class RecordFormSelection(forms.Form): + form_label = _("Context record") + associated_models = {'pk':models.ContextRecord} + currents = {'pk':models.ContextRecord} + pk = forms.IntegerField(label="", required=False, + widget=widgets.JQueryJqGrid(reverse_lazy('get-contextrecord'), + RecordSelect(), models.ContextRecord), + validators=[models.valid_id(models.ContextRecord)]) + + def clean(self): + cleaned_data = self.cleaned_data + if 'pk' not in cleaned_data or not cleaned_data['pk']: + raise forms.ValidationError(_(u"You should select a context " + u"record.")) + return cleaned_data + + +class RecordFormGeneral(forms.Form): + form_label = _("General") + associated_models = {'parcel':models.Parcel, 'unit':models.Unit} + parcel = forms.ChoiceField(label=_("Parcel"), choices=[]) + label = forms.CharField(label=_(u"ID"), + validators=[validators.MaxLengthValidator(200)]) + description = forms.CharField(label=_(u"Description"), + widget=forms.Textarea, required=False) + length = forms.IntegerField(label=_(u"Length"), required=False) + width = forms.IntegerField(label=_(u"Width"), required=False) + thickness = forms.IntegerField(label=_(u"Thickness"), required=False) + depth = forms.IntegerField(label=_(u"Depth"), required=False) + unit = forms.ChoiceField(label=_("Unit"), required=False, + choices=models.Unit.get_types()) + location = forms.CharField(label=_(u"Location"), widget=forms.Textarea, + required=False, validators=[validators.MaxLengthValidator(200)]) + + def __init__(self, *args, **kwargs): + operation = None + if 'data' in kwargs and kwargs['data'] and \ + ('Operation' in kwargs['data'] or 'ContextRecord' in kwargs['data']): + if 'Operation' in kwargs['data']: + operation = kwargs['data']['Operation'] + if 'ContextRecord' in kwargs['data']: + operation = kwargs['data']['ContextRecord'].parcel.operation + # clean data if not "real" data + prefix_value = kwargs['prefix'] + if not [k for k in kwargs['data'].keys() + if k.startswith(kwargs['prefix']) and kwargs['data'][k]]: + kwargs['data'] = None + if 'files' in kwargs: + kwargs.pop('files') + super(RecordFormGeneral, self).__init__(*args, **kwargs) + self.fields['parcel'].choices = [('', '--')] + if operation: + parcels = operation.parcels.all() + sort = lambda x: (x.town.name, x.section) + parcels = sorted(parcels, key=sort) + for key, gparcels in groupby(parcels, sort): + self.fields['parcel'].choices.append( + (" - ".join(key), [(parcel.pk, parcel.short_label()) for parcel in gparcels]) + ) + +class DatingForm(forms.Form): + form_label = _("Dating") + base_model = 'dating' + associated_models = {'dating_type':models.DatingType, + 'quality':models.DatingQuality, + 'period':models.Period} + period = forms.ChoiceField(label=_("Period"), + choices=models.Period.get_types()) + start_date = forms.IntegerField(label=_(u"Start date"), required=False) + end_date = forms.IntegerField(label=_(u"End date"), required=False) + quality = forms.ChoiceField(label=_("Quality"), required=False, + choices=models.DatingQuality.get_types()) + dating_type = forms.ChoiceField(label=_("Dating type"), required=False, + choices=models.DatingType.get_types()) + +DatingFormSet = formset_factory(DatingForm, can_delete=True, + formset=FormSet) +DatingFormSet.form_label = _("Dating") + +class RecordFormInterpretation(forms.Form): + form_label = _("Interpretation") + associated_models = {'activity':models.ActivityType, + 'identification':models.IdentificationType,} + has_furniture = forms.NullBooleanField(label=_(u"Has furniture?"), + required=False) + filling = forms.CharField(label=_(u"Filling"), + widget=forms.Textarea, required=False) + interpretation = forms.CharField(label=_(u"Interpretation"), + widget=forms.Textarea, required=False) + activity = forms.ChoiceField(label=_("Activity"), required=False, + choices=[]) + identification = forms.ChoiceField(label=_("Identification"), + required=False, choices=[]) + taq = forms.IntegerField(label=_(u"TAQ"), required=False) + taq_estimated = forms.IntegerField(label=_(u"Estimated TAQ"), + required=False) + tpq = forms.IntegerField(label=_(u"TPQ"), required=False) + tpq_estimated = forms.IntegerField(label=_(u"Estimated TPQ"), + required=False) + + def __init__(self, *args, **kwargs): + super(RecordFormInterpretation, self).__init__(*args, **kwargs) + self.fields['activity'].choices = models.ActivityType.get_types() + self.fields['identification'].choices = \ + models.IdentificationType.get_types() + +record_search_wizard = SearchWizard([ + ('general-record_search', RecordFormSelection)], + url_name='record_search',) + +record_creation_wizard = RecordWizard([ + ('selec-record_creation', OperationFormSelection), + ('general-record_creation', RecordFormGeneral), + ('datings-record_creation', DatingFormSet), + ('interpretation-record_creation', RecordFormInterpretation), + ('final-record_creation', FinalForm)], + url_name='record_creation',) + +record_modification_wizard = RecordModifWizard([ + ('selec-record_modification', RecordFormSelection), + ('general-record_modification', RecordFormGeneral), + ('datings-record_modification', DatingFormSet), + ('interpretation-record_modification', RecordFormInterpretation), + ('final-record_modification', FinalForm)], + url_name='record_modification',) + +class RecordDeletionWizard(DeletionWizard): + model = models.ContextRecord + fields = ['label', 'parcel', 'description', 'length', 'width', 'thickness', + 'depth', 'location', 'datings', 'units', 'has_furniture', + 'filling', 'interpretation', 'taq', 'taq_estimated', 'tpq', + 'tpq_estimated'] + +class RecordDeletionForm(FinalForm): + confirm_msg = " " + confirm_end_msg = _(u"Would you like to delete this context record?") + +record_deletion_wizard = RecordDeletionWizard([ + ('selec-record_deletion', RecordFormSelection), + ('final-record_deletion', RecordDeletionForm)], + url_name='record_deletion',) + + diff --git a/ishtar/furnitures/forms_files.py b/ishtar/furnitures/forms_files.py index ae52fc8cc..4e63fc588 100644 --- a/ishtar/furnitures/forms_files.py +++ b/ishtar/furnitures/forms_files.py @@ -32,8 +32,12 @@ from ishtar import settings import models import widgets -from forms import Wizard, FinalForm, FormSet, SearchWizard, formset_factory, \ - get_now, reverse_lazy +from forms import Wizard, FinalForm, FormSet, ClosingWizard, SearchWizard, \ + formset_factory, get_now, reverse_lazy +from forms_common import TownFormSet, ParcelFormSet +from forms_operations import OperationAdministrativeActWizard, \ +AdministrativeActOpeForm, AdministrativeActOpeFormSelection, \ +AdministrativeActDeletionWizard, FinalAdministrativeActDeleteForm, is_preventive class FileWizard(Wizard): model = models.File @@ -195,86 +199,6 @@ class FileFormAddress(forms.Form): 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, @@ -308,22 +232,6 @@ class FileFormPreventive(forms.Form): 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',) @@ -335,7 +243,8 @@ file_creation_wizard = FileWizard([ ('preventive-file_creation', FileFormPreventive), ('final-file_creation', FinalForm)], condition_list={ -'preventive-file_creation':is_preventive('general-file_creation', models.FileType) +'preventive-file_creation':is_preventive('general-file_creation', + models.FileType, type_key='file_type') }, url_name='file_creation',) @@ -349,6 +258,102 @@ file_modification_wizard = FileWizard([ ('final-file_modification', FinalForm)], condition_list={ 'preventive-file_modification':is_preventive('general-file_modification', - models.FileType) + 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 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',) +""" +file_closing_wizard = FileWizard([ + ('selec-file_closing', FileFormSelection), + ('date-operation_closing', OperationDateFormSelection), + ('final-operation_closing', FinalOperationClosingForm)], + url_name='operation_closing',) +""" + +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 = 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(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=_("Act type"), + choices=models.ActType.get_types(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',) + diff --git a/ishtar/furnitures/forms_items.py b/ishtar/furnitures/forms_items.py new file mode 100644 index 000000000..5775731ff --- /dev/null +++ b/ishtar/furnitures/forms_items.py @@ -0,0 +1,240 @@ +#!/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. + +""" +Items 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 +from forms_context_records import RecordFormSelection + +class ItemWizard(Wizard): + model = models.Item + + def get_extra_model(self, dct, request, storage, form_list): + dct = super(ItemWizard, self).get_extra_model(dct, request, storage, + form_list) + dct['order'] = 1 + if 'pk' in dct and type(dct['pk']) == models.ContextRecord: + dct['base_items__context_record'] = dct.pop('pk') + return dct + +class ItemFormBase(forms.Form): + form_label = _("Base item") + base_model = 'base_items' + base_items__label = forms.CharField(label=_(u"General ID"), + validators=[validators.MaxLengthValidator(60)]) + base_items__description = forms.CharField(label=_("General description"), + widget=forms.Textarea) + base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"), + required=False) + +class ItemForm(forms.Form): + form_label = _("Item") + associated_models = {'material_type':models.MaterialType,} + label = forms.CharField(label=_(u"ID"), + validators=[validators.MaxLengthValidator(60)]) + description = forms.CharField(label=_("Precise description"), + widget=forms.Textarea, required=False) + material_type = forms.ChoiceField(label=_("Material type"), + choices=models.MaterialType.get_types()) + volume = forms.IntegerField(label=_(u"Volume"), required=False) + weight = forms.IntegerField(label=_(u"Weight"), required=False) + item_number = forms.IntegerField(label=_(u"Item number"), required=False) + +class DateForm(forms.Form): + form_label = _("Dating") + base_model = 'dating' + associated_models = {'dating__dating_type':models.DatingType, + 'dating__quality':models.DatingQuality, + 'dating__period':models.Period} + dating__period = forms.ChoiceField(label=_("Period"), + choices=models.Period.get_types()) + dating__start_date = forms.IntegerField(label=_(u"Start date"), + required=False) + dating__end_date = forms.IntegerField(label=_(u"End date"), required=False) + dating__quality = forms.ChoiceField(label=_("Quality"), required=False, + choices=models.DatingQuality.get_types()) + dating__dating_type = forms.ChoiceField(label=_("Dating type"), + required=False, choices=models.DatingType.get_types()) + +item_creation_wizard = ItemWizard([ + ('selecrecord-item_creation', RecordFormSelection), + ('base_item-record_creation', ItemFormBase), + ('item-item_creation', ItemForm), + ('dating-item_creation', DateForm), + ('final-item_creation', FinalForm)], + url_name='item_creation',) + +class ItemSelect(forms.Form): + base_items__context_record__parcel__town = forms.IntegerField( + widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ + 'autocomplete-town', associated_model=models.Town), + validators=[models.valid_id(models.Town)], label=_(u"Town")) + base_items__context_record__parcel__operation__year = forms.IntegerField( + label=_("Year")) + dating__period = forms.ChoiceField( + label=_("Period"), choices=models.Period.get_types()) + material_type = forms.ChoiceField( + label=_("Material type"), choices=models.MaterialType.get_types()) + base_items__is_isolated = forms.NullBooleanField(label=_("Is isolated?")) + +class ItemFormSelection(forms.Form): + form_label = _("Item") + associated_models = {'pk':models.Item} + currents = {'pk':models.Item} + pk = forms.IntegerField(label="", required=False, + widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), + ItemSelect(), models.Item), + validators=[models.valid_id(models.Item)]) + +item_search_wizard = SearchWizard([ + ('general-item_search', ItemFormSelection)], + url_name='item_search',) + +item_modification_wizard = ItemWizard([ + ('selec-item_modification', ItemFormSelection), + ('item-item_modification', ItemForm), + ('dating-item_modification', DateForm), + ('final-item_modification', FinalForm)], + url_name='item_modification',) + +class TreatmentWizard(Wizard): + model = models.Treatment + +class BaseTreatmentForm(forms.Form): + form_label = _(u"Base treatment") + associated_models = {'treatment_type':models.TreatmentType, + 'person':models.Person, + 'location':models.Warehouse} + treatment_type = forms.ChoiceField(label=_(u"Treatment type"), + choices=models.TreatmentType.get_types()) + description = forms.CharField(label=_(u"Description"), + widget=forms.Textarea, required=False) + person = forms.IntegerField(label=_(u"Person"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-person'), associated_model=models.Person), + validators=[models.valid_id(models.Person)]) + location = forms.IntegerField(label=_(u"Location"), + widget=widgets.JQueryAutoComplete( + reverse_lazy('autocomplete-warehouse'), associated_model=models.Warehouse, + new=True), + validators=[models.valid_id(models.Warehouse)]) + start_date = forms.DateField(label=_(u"Start date"), required=False, + widget=widgets.JQueryDate) + end_date = forms.DateField(label=_(u"End date"), required=False, + widget=widgets.JQueryDate) + +class ItemMultipleFormSelection(forms.Form): + form_label = _(u"Upstream items") + associated_models = {'items':models.Item} + items = forms.IntegerField(label="", required=False, + widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), + ItemSelect(), models.Item, multiple=True), + validators=[models.valid_id(models.Item)]) + +class ContainerForm(forms.Form): + form_label = _(u"Container") + associated_models = {'container_type':models.ContainerType,} + reference = forms.CharField(label=_(u"Reference")) + container_type = forms.ChoiceField(label=_(u"Container type"), + choices=models.ContainerType.get_types()) + comment = forms.CharField(label=_(u"Comment"), + widget=forms.Textarea, required=False) + +def check_treatment(form_name, type_key, type_list=[], not_type_list=[]): + type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk + for tpe in type_list] + not_type_list = [models.TreatmentType.objects.get(txt_idx=tpe).pk + for tpe in not_type_list] + 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 (not type_list or type in type_list) \ + and type not in not_type_list + except ValueError: + return False + return func + +class ResultItemForm(forms.Form): + form_label = _("Resulting item") + associated_models = {'material_type':models.MaterialType} + label = forms.CharField(label=_(u"ID"), + validators=[validators.MaxLengthValidator(60)]) + description = forms.CharField(label=_("Precise description"), + widget=forms.Textarea) + material_type = forms.ChoiceField(label=_("Material type"), + choices=models.MaterialType.get_types()) + volume = forms.IntegerField(label=_(u"Volume")) + weight = forms.IntegerField(label=_(u"Weight")) + item_number = forms.IntegerField(label=_(u"Item number")) + +ResultItemFormSet = formset_factory(ResultItemForm, can_delete=True, + formset=FormSet) +ResultItemFormSet.form_label = _(u"Resulting items") + +class UpstreamItemFormSelection(ItemFormSelection): + form_label = _(u"Upstream item") + +treatment_creation_wizard = TreatmentWizard([ + ('basetreatment-treatment_creation', BaseTreatmentForm), + ('selecitem-treatment_creation', UpstreamItemFormSelection), + ('multiselecitems-treatment_creation', ItemMultipleFormSelection), + ('container-treatment_creation', ContainerForm), + ('resultitem-treatment_creation', ResultItemForm), + ('resultitems-treatment_creation', ResultItemFormSet), + ('final-treatment_creation', FinalForm)], + condition_list={ +'selecitem-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + not_type_list=['physical_grouping']), +'multiselecitems-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['physical_grouping']), +'resultitems-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['split']), +'resultitem-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + not_type_list=['split']), +'container-treatment_creation': + check_treatment('basetreatment-treatment_creation', 'treatment_type', + ['packaging']), + }, + url_name='treatment_creation',) + diff --git a/ishtar/furnitures/forms_main.py b/ishtar/furnitures/forms_main.py index 951f2d234..723b80d83 100644 --- a/ishtar/furnitures/forms_main.py +++ b/ishtar/furnitures/forms_main.py @@ -17,7 +17,10 @@ # See the file COPYING for details. -from forms_administrative import * +from forms_common import * from forms_files import * +from forms_operations import * +from forms_context_records import * +from forms_items import * from forms import * diff --git a/ishtar/furnitures/forms_operations.py b/ishtar/furnitures/forms_operations.py new file mode 100644 index 000000000..e9d62b7ea --- /dev/null +++ b/ishtar/furnitures/forms_operations.py @@ -0,0 +1,605 @@ +#!/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. + +""" +Operations 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, ClosingWizard, \ + DeletionWizard, formset_factory, get_now, reverse_lazy +from forms_common import TownForm, TownFormSet, ParcelFormSet, ParcelForm + +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: + 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 + +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 + # 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'): + 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: + towns = [] + town_form_key = 'towns-' + self.url_name + town_ids = self.session_get_value(request, storage, + town_form_key, 'town', multi=True) or [] + 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_extra_model(self, dct, request, storage, form_list): + dct['history_modifier'] = request.user + return dct + + 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) + surface = forms.IntegerField(required=False, widget=widgets.AreaWidget, + label=_(u"Total surface"), + validators=[validators.MinValueValidator(0), + validators.MaxValueValidator(999999999)]) + 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 and towns != -1: + 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_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), + ('refs-operation_creation', OperationFormReference), + ('preventive-operation_creation', OperationFormPreventive), + ('preventivediag-operation_creation', OperationFormPreventiveDiag), + ('townsgeneral-operation_creation', SelectedTownGeneralFormSet), + ('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',) + +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), + ('townsgeneral-operation_modification', SelectedTownGeneralFormSet), + ('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 OperationDateFormSelection(forms.Form): + form_label = _("Closing date") + end_date = forms.DateField(label=_(u"Closing date"), + widget=widgets.JQueryDate) + +class OperationClosingWizard(ClosingWizard): + 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 OperationDeletionForm(FinalForm): + confirm_msg = " " + confirm_end_msg = _(u"Would you like to delete this operation?") + +operation_deletion_wizard = DeletionWizard([ + ('selec-operation_deletion', OperationFormSelection), + ('final-operation_deletion', OperationDeletionForm)], + url_name='operation_deletion',) + +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 = 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(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-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=models.ActType.get_types(dct={'intented_to':'O'})) + 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 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',) |