#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010-2011 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # See the file COPYING for details. """ Items forms definitions """ import datetime from django import forms from django.shortcuts import render_to_response from django.template import RequestContext from django.core import validators from django.core.exceptions import ObjectDoesNotExist from django.utils.safestring import mark_safe 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,\ FloatField, formset_factory, get_now, get_form_selection, reverse_lazy from forms_common import get_town_field, get_warehouse_field, SourceForm, \ SourceWizard, SourceSelect, SourceDeletionForm, AuthorFormset from forms_context_records import RecordFormSelection class ItemWizard(Wizard): model = models.Item def get_current_contextrecord(self, request, storage): step = storage.get_current_step() if not step: return if step.endswith('_creation'): # a context record has been selected main_form_key = 'selecrecord-' + self.url_name try: idx = int(self.session_get_value(request, storage, main_form_key, 'pk')) current_cr = models.ContextRecord.objects.get(pk=idx) return current_cr except(TypeError, ValueError, ObjectDoesNotExist): pass current_item = self.get_current_object(request, storage) if current_item: base_items = current_item.base_items.all() if base_items: return base_items[0].context_record def get_template_context(self, request, storage, form=None): """ Get the operation and context record "reminder" on top of wizard forms """ context = super(ItemWizard, self).get_template_context(request, storage, form) current_cr = self.get_current_contextrecord(request, storage) if not current_cr: return context operation = current_cr.operation items = [] if hasattr(operation, 'code_patriarche') and operation.code_patriarche: items.append(unicode(operation.code_patriarche)) items.append("-".join((unicode(operation.year), unicode(operation.operation_code)))) reminder = unicode(_("Current operation: ")) + u" - ".join(items) reminder += u"
" + unicode(_("Current context record: "))\ + unicode(current_cr.label) context['reminder'] = mark_safe(reminder) return context 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 ItemForm(forms.Form): form_label = _("Item") base_model = 'base_items' associated_models = {'material_type':models.MaterialType,} label = forms.CharField(label=_(u"ID"), validators=[validators.MaxLengthValidator(60)]) description = forms.CharField(label=_("Description"), widget=forms.Textarea) base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"), required=False) material_type = forms.ChoiceField(label=_("Material type"), choices=models.MaterialType.get_types()) volume = FloatField(label=_(u"Volume (l)"), required=False) weight = FloatField(label=_(u"Weight (g)"), 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=[]) def __init__(self, *args, **kwargs): super(DateForm, self).__init__(*args, **kwargs) self.fields['dating__dating_type'].choices = models.DatingType.get_types() self.fields['dating__dating_type'].help_text = models.DatingType.get_help() item_creation_wizard = ItemWizard([ ('selecrecord-item_creation', RecordFormSelection), ('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 = get_town_field() base_items__context_record__operation__year = forms.IntegerField( label=_(u"Year")) base_items__context_record__operation__code_patriarche = \ forms.IntegerField(label=_(u"Code PATRIARCHE")) dating__period = forms.ChoiceField(label=_(u"Period"), choices=[]) # TODO search by warehouse material_type = forms.ChoiceField(label=_(u"Material type"), choices=[]) base_items__item__description = forms.CharField(label=_(u"Description")) base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?")) def __init__(self, *args, **kwargs): super(ItemSelect, self).__init__(*args, **kwargs) self.fields['dating__period'].choices = \ models.Period.get_types() self.fields['dating__period'].help_text = \ models.Period.get_help() self.fields['material_type'].choices = \ models.MaterialType.get_types() self.fields['material_type'].help_text = \ models.MaterialType.get_help() class ItemFormSelection(forms.Form): form_label = _("Item search") 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, source_full=reverse_lazy('get-item-full')), validators=[models.valid_id(models.Item)]) item_search_wizard = SearchWizard([ ('general-item_search', ItemFormSelection)], url_name='item_search',) class ItemModificationWizard(ItemWizard): modification = True item_modification_wizard = ItemModificationWizard([ ('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=[]) person = forms.IntegerField(label=_(u"Person"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=models.Person, new=True), 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)]) description = forms.CharField(label=_(u"Description"), widget=forms.Textarea, required=False) 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) def __init__(self, *args, **kwargs): super(BaseTreatmentForm, self).__init__(*args, **kwargs) self.fields['treatment_type'].choices = models.TreatmentType.get_types( exclude=['packaging']) self.fields['treatment_type'].help_text = models.TreatmentType.get_help( exclude=['packaging']) class ItemMultipleFormSelection(forms.Form): form_label = _(u"Upstream items") associated_models = {'items':models.Item} associated_labels = {'items':_(u"Items")} items = forms.CharField(label="", required=False, widget=widgets.JQueryJqGrid(reverse_lazy('get-item'), ItemSelect(), models.Item, multiple=True, multiple_cols=[2, 3, 4]), validators=[models.valid_ids(models.Item)]) def clean(self): if not 'items' in self.cleaned_data or not self.cleaned_data['items']: raise forms.ValidationError(_(u"You should at least select one " u"archaeological item.")) return self.cleaned_data class ContainerForm(forms.Form): form_label = _(u"Container") reference = forms.CharField(label=_(u"Reference")) container_type = forms.ChoiceField(label=_(u"Container type"), choices=[]) location = forms.IntegerField(label=_(u"Warehouse"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-warehouse'), associated_model=models.Warehouse, new=True), validators=[models.valid_id(models.Warehouse)]) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) def __init__(self, *args, **kwargs): super(ContainerForm, self).__init__(*args, **kwargs) self.fields['container_type'].choices = \ models.ContainerType.get_types() self.fields['container_type'].help_text = \ models.ContainerType.get_help() def save(self, user): dct = self.cleaned_data dct['history_modifier'] = user dct['container_type'] = models.ContainerType.objects.get( pk=dct['container_type']) dct['location'] = models.Warehouse.objects.get(pk=dct['location']) new_item = models.Container(**dct) new_item.save() return new_item 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 = _(u"Resulting item") associated_models = {'material_type':models.MaterialType} label = forms.CharField(label=_(u"ID"), validators=[validators.MaxLengthValidator(60)]) description = forms.CharField(label=_(u"Precise description"), widget=forms.Textarea) material_type = forms.ChoiceField(label=_(u"Material type"), choices=models.MaterialType.get_types()) volume = forms.IntegerField(label=_(u"Volume (l)")) weight = forms.IntegerField(label=_(u"Weight (g)")) 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', 'packaging']), 'multiselecitems-treatment_creation': check_treatment('basetreatment-treatment_creation', 'treatment_type', ['physical_grouping', 'packaging']), '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',) ############# # Packaging # ############# class PackagingWizard(TreatmentWizard): def save_model(self, dct, m2m, whole_associated_models, request, storage, form_list, return_object): dct = self.get_extra_model(dct, request, storage, form_list) obj = self.get_current_saved_object(request, storage) dct['location'] = dct['container'].location items = dct.pop('items') treatment = models.Treatment(**dct) treatment.save() if not hasattr(items, '__iter__'): items = [items] for item in items: new = item.duplicate(request.user) item.downstream_treatment = treatment item.save() new.upstream_treatment = treatment new.container = dct['container'] new.save() res = render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) return return_object and (obj, res) or res class ContainerSelect(forms.Form): location = get_warehouse_field() container_type = forms.ChoiceField(label=_(u"Container type"), choices=[]) reference = forms.CharField(label=_(u"Reference")) def __init__(self, *args, **kwargs): super(ContainerSelect, self).__init__(*args, **kwargs) self.fields['container_type'].choices = \ models.ContainerType.get_types() self.fields['container_type'].help_text = \ models.ContainerType.get_help() ContainerFormSelection = get_form_selection( 'ContainerFormSelection', _(u"Container search"), 'container', models.Container, ContainerSelect, 'get-container', _(u"You should select a container."), new=True, new_message=_(u"Add a new container")) class BasePackagingForm(forms.Form): form_label = _(u"Packaging") associated_models = {'treatment_type':models.TreatmentType, 'person':models.Person, 'location':models.Warehouse} treatment_type = forms.IntegerField(label="", widget=forms.HiddenInput) person = forms.IntegerField(label=_(u"Packager"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=models.Person, new=True), validators=[models.valid_id(models.Person)]) start_date = forms.DateField(label=_(u"Date"), required=False, widget=widgets.JQueryDate) def __init__(self, *args, **kwargs): super(BasePackagingForm, self).__init__(*args, **kwargs) self.fields['treatment_type'].initial = \ models.TreatmentType.objects.get(txt_idx='packaging').pk class ItemPackagingFormSelection(ItemMultipleFormSelection): form_label = _(u"Packaged items") warehouse_packaging_wizard = PackagingWizard([ ('seleccontainer-packaging', ContainerFormSelection), ('base-packaging', BasePackagingForm), ('multiselecitems-packaging', ItemPackagingFormSelection), ('final-packaging', FinalForm)], url_name='warehouse_packaging',) """ warehouse_packaging_wizard = ItemSourceWizard([ ('selec-warehouse_packaging', ItemsSelection), ('final-warehouse_packaging', FinalForm)], url_name='warehouse_packaging',) """ ############################################# # Source management for archaelogical items # ############################################# class ItemSourceWizard(SourceWizard): model = models.ItemSource SourceItemFormSelection = get_form_selection( 'SourceItemFormSelection', _(u"Archaelogical item search"), 'item', models.Item, ItemSelect, 'get-item', _(u"You should select an archaelogical item.")) item_source_creation_wizard = ItemSourceWizard([ ('selec-item_source_creation', SourceItemFormSelection), ('source-item_source_creation', SourceForm), ('authors-item_source_creation', AuthorFormset), ('final-item_source_creation', FinalForm)], url_name='item_source_creation',) class ItemSourceSelect(SourceSelect): item__base_items__context_record__operation__year = forms.IntegerField( label=_(u"Year of the operation")) item__dating__period = forms.ChoiceField( label=_(u"Period of the archaelogical item"), choices=[]) item__material_type = forms.ChoiceField( label=_("Material type of the archaelogical item"), choices=models.MaterialType.get_types()) item__description = forms.CharField( label=_(u"Description of the archaelogical item")) def __init__(self, *args, **kwargs): super(ItemSourceSelect, self).__init__(*args, **kwargs) self.fields['item__dating__period'].choices = \ models.Period.get_types() self.fields['item__dating__period'].help_text = \ models.Period.get_help() self.fields['item__material_type'].choices = \ models.MaterialType.get_types() self.fields['item__material_type'].help_text = \ models.MaterialType.get_help() ItemSourceFormSelection = get_form_selection( 'ItemSourceFormSelection', _(u"Documentation search"), 'pk', models.ItemSource, ItemSourceSelect, 'get-itemsource', _(u"You should select a document.")) item_source_modification_wizard = ItemSourceWizard([ ('selec-item_source_modification', ItemSourceFormSelection), ('source-item_source_modification', SourceForm), ('authors-item_source_modification', AuthorFormset), ('final-item_source_modification', FinalForm)], url_name='item_source_modification',) class ItemSourceDeletionWizard(DeletionWizard): model = models.ItemSource fields = ['item', 'title', 'source_type', 'authors',] item_source_deletion_wizard = ItemSourceDeletionWizard([ ('selec-item_source_deletion', ItemSourceFormSelection), ('final-item_source_deletion', SourceDeletionForm)], url_name='item_source_deletion',) """ #################################### # Source management for treatments # #################################### class TreatmentSourceWizard(SourceWizard): model = models.TreamentSource SourceTreatementFormSelection = get_form_selection( 'SourceTreatmentFormSelection', _(u"Treatment search"), 'operation', models.Treatment, TreatmentSelect, 'get-treatment', _(u"You should select a treatment.")) treatment_source_creation_wizard = TreatmentSourceWizard([ ('selec-treatment_source_creation', SourceTreatmentFormSelection), ('source-treatment_source_creation', SourceForm), ('authors-treatment_source_creation', AuthorFormset), ('final-treatment_source_creation', FinalForm)], url_name='treatment_source_creation',) class TreatmentSourceSelect(SourceSelect): operation__towns = get_town_field(label=_(u"Operation's town")) treatment__treatment_type = forms.ChoiceField(label=_(u"Operation type"), choices=[]) operation__year = forms.IntegerField(label=_(u"Operation's year")) def __init__(self, *args, **kwargs): super(OperationSourceSelect, self).__init__(*args, **kwargs) self.fields['operation__operation_type'].choices = \ models.OperationType.get_types() self.fields['operation__operation_type'].help_text = \ models.OperationType.get_help() OperationSourceFormSelection = get_form_selection( 'OperationSourceFormSelection', _(u"Documentation search"), 'pk', models.OperationSource, OperationSourceSelect, 'get-operationsource', _(u"You should select a document.")) operation_source_modification_wizard = OperationSourceWizard([ ('selec-operation_source_modification', OperationSourceFormSelection), ('source-operation_source_modification', SourceForm), ('authors-operation_source_modification', AuthorFormset), ('final-operation_source_modification', FinalForm)], url_name='operation_source_modification',) class OperationSourceDeletionWizard(DeletionWizard): model = models.OperationSource fields = ['operation', 'title', 'source_type', 'authors',] operation_source_deletion_wizard = OperationSourceDeletionWizard([ ('selec-operation_source_deletion', OperationSourceFormSelection), ('final-operation_source_deletion', SourceDeletionForm)], url_name='operation_source_deletion',) """