diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-20 15:25:07 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-10-20 15:25:07 +0200 |
commit | dc7abf75836b59ad33d92da04fe727320400d512 (patch) | |
tree | b26e820671aa6af552a4b03147c44a9d2aa84be8 /archaeological_finds | |
parent | 029d08540f66524c371ae87ede5c1281fbe2c568 (diff) | |
download | Ishtar-dc7abf75836b59ad33d92da04fe727320400d512.tar.bz2 Ishtar-dc7abf75836b59ad33d92da04fe727320400d512.zip |
Djangoization - Major refactoring (step 3)
Reorganization of views, urls, menus, admin, forms.
Changes on models.
Diffstat (limited to 'archaeological_finds')
-rw-r--r-- | archaeological_finds/admin.py | 75 | ||||
-rw-r--r-- | archaeological_finds/forms.py | 525 | ||||
-rw-r--r-- | archaeological_finds/ishtar_menu.py | 67 | ||||
-rw-r--r-- | archaeological_finds/migrations/0001_initial.py | 188 | ||||
-rw-r--r-- | archaeological_finds/models.py | 134 | ||||
-rw-r--r-- | archaeological_finds/urls.py | 52 | ||||
-rw-r--r-- | archaeological_finds/views.py | 43 |
7 files changed, 923 insertions, 161 deletions
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py new file mode 100644 index 000000000..096f05bf3 --- /dev/null +++ b/archaeological_finds/admin.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 É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. + +from django.conf import settings +from django.contrib import admin + +from ishtar_common.admin import HistorizedObjectAdmin + +import models + +class BaseFindAdmin(HistorizedObjectAdmin): + list_display = ('label', 'context_record', 'is_isolated') + search_fields = ('label', 'context_record__parcel__operation__name',) + model = models.BaseFind + +admin.site.register(models.BaseFind, BaseFindAdmin) + +class FindAdmin(HistorizedObjectAdmin): + list_display = ('label', 'material_type', 'dating', 'volume', 'weight', + 'find_number',) + list_filter = ('material_type',) + search_fields = ('label', "dating__period__label") + model = models.Find + +admin.site.register(models.Find, FindAdmin) + +class FindSourceAdmin(admin.ModelAdmin): + list_display = ('find', 'title', 'source_type',) + list_filter = ('source_type',) + search_fields = ('title', ) + model = models.FindSource + +admin.site.register(models.FindSource, FindSourceAdmin) + +class PropertyAdmin(admin.ModelAdmin): + list_display = ['find', 'person', 'start_date', 'end_date'] + search_fields = ('find__label', 'person__name') + model = models.Property + +admin.site.register(models.Property, PropertyAdmin) + +class TreatmentAdmin(HistorizedObjectAdmin): + list_display = ('location', 'treatment_type', 'container', 'person') + list_filter = ('treatment_type',) + model = models.Treatment + +admin.site.register(models.Treatment, TreatmentAdmin) + +class TreatmentSourceAdmin(admin.ModelAdmin): + list_display = ('treatment', 'title', 'source_type',) + list_filter = ('source_type',) + search_fields = ('title',) + model = models.TreatmentSource + +admin.site.register(models.TreatmentSource, TreatmentSourceAdmin) + +basic_models = [models.MaterialType, models.TreatmentType] +for model in basic_models: + admin.site.register(model) diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py new file mode 100644 index 000000000..7d64214f5 --- /dev/null +++ b/archaeological_finds/forms.py @@ -0,0 +1,525 @@ +#!/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.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_finds = current_item.base_finds.all() + if base_finds: + return base_finds[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"<br/>" + 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_finds__context_record'] = dct.pop('pk') + return dct + +class ItemForm(forms.Form): + form_label = _("Item") + base_model = 'base_finds' + 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_finds__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_finds__context_record__parcel__town = get_town_field() + base_finds__context_record__operation__year = forms.IntegerField( + label=_(u"Year")) + base_finds__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_finds__item__description = forms.CharField(label=_(u"Description")) + base_finds__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_finds__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',) +""" diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py new file mode 100644 index 000000000..55a498184 --- /dev/null +++ b/archaeological_finds/ishtar_menu.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012 É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. + +from django.utils.translation import ugettext_lazy as _ + +from ishtar_common.menu_base import SectionItem, MenuItem + +import models + +MENU_SECTIONS = [ + (50, SectionItem('find_management', _(u"Find"), + childs=[ + MenuItem('find_search', _(u"Search"), + model=models.Find, + access_controls=['view_item', + 'view_own_item']), + MenuItem('find_creation', _(u"Creation"), + model=models.Find, + access_controls=['add_item', + 'add_own_item']), + MenuItem('find_modification', _(u"Modification"), + model=models.Find, + access_controls=['change_item', + 'change_own_item']), + MenuItem('warehouse_packaging', _(u"Packaging"), + model=models.Treatment, + access_controls=['add_treatment', 'add_own_treatment']), + #MenuItem('treatment_creation', _(u"Add a treatment"), + # model=models.Treatment, + # access_controls=['add_treatment', + # 'add_own_treatment']), + SectionItem('find_source', _(u"Documentation"), + childs=[ + MenuItem('find_source_creation', + _(u"Creation"), + model=models.FindSource, + access_controls=['change_item', + 'change_own_item']), + MenuItem('find_source_modification', + _(u"Modification"), + model=models.FindSource, + access_controls=['change_item', + 'change_own_item']), + MenuItem('find_source_deletion', + _(u"Deletion"), + model=models.FindSource, + access_controls=['change_item', + 'change_own_item']), + ]) + ])) +] diff --git a/archaeological_finds/migrations/0001_initial.py b/archaeological_finds/migrations/0001_initial.py index 03a45ed8d..eab75b03c 100644 --- a/archaeological_finds/migrations/0001_initial.py +++ b/archaeological_finds/migrations/0001_initial.py @@ -20,8 +20,8 @@ class Migration(SchemaMigration): )) db.send_create_signal('archaeological_finds', ['MaterialType']) - # Adding model 'HistoricalBaseItem' - db.create_table('archaeological_finds_historicalbaseitem', ( + # Adding model 'HistoricalBaseFind' + db.create_table('archaeological_finds_historicalbasefind', ( ('id', self.gf('django.db.models.fields.IntegerField')(db_index=True, blank=True)), ('history_modifier_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), ('label', self.gf('django.db.models.fields.CharField')(max_length=60)), @@ -35,23 +35,23 @@ class Migration(SchemaMigration): ('history_user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), ('history_type', self.gf('django.db.models.fields.CharField')(max_length=1)), )) - db.send_create_signal('archaeological_finds', ['HistoricalBaseItem']) + db.send_create_signal('archaeological_finds', ['HistoricalBaseFind']) - # Adding model 'BaseItem' - db.create_table('archaeological_finds_baseitem', ( + # Adding model 'BaseFind' + db.create_table('archaeological_finds_basefind', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])), ('label', self.gf('django.db.models.fields.CharField')(max_length=60)), ('description', self.gf('django.db.models.fields.TextField')()), - ('context_record', self.gf('django.db.models.fields.related.ForeignKey')(related_name='base_items', to=orm['archaeological_context_records.ContextRecord'])), + ('context_record', self.gf('django.db.models.fields.related.ForeignKey')(related_name='base_finds', to=orm['archaeological_context_records.ContextRecord'])), ('is_isolated', self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True)), ('index', self.gf('django.db.models.fields.IntegerField')(default=0)), ('material_index', self.gf('django.db.models.fields.IntegerField')(default=0)), )) - db.send_create_signal('archaeological_finds', ['BaseItem']) + db.send_create_signal('archaeological_finds', ['BaseFind']) - # Adding model 'HistoricalItem' - db.create_table('archaeological_finds_historicalitem', ( + # Adding model 'HistoricalFind' + db.create_table('archaeological_finds_historicalfind', ( ('id', self.gf('django.db.models.fields.IntegerField')(db_index=True, blank=True)), ('history_modifier_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), ('order', self.gf('django.db.models.fields.IntegerField')()), @@ -60,7 +60,7 @@ class Migration(SchemaMigration): ('material_type_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), ('volume', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)), ('weight', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)), - ('item_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('find_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), ('upstream_treatment_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), ('downstream_treatment_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), ('dating_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)), @@ -70,10 +70,10 @@ class Migration(SchemaMigration): ('history_user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)), ('history_type', self.gf('django.db.models.fields.CharField')(max_length=1)), )) - db.send_create_signal('archaeological_finds', ['HistoricalItem']) + db.send_create_signal('archaeological_finds', ['HistoricalFind']) - # Adding model 'Item' - db.create_table('archaeological_finds_item', ( + # Adding model 'Find' + db.create_table('archaeological_finds_find', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])), ('order', self.gf('django.db.models.fields.IntegerField')()), @@ -82,41 +82,41 @@ class Migration(SchemaMigration): ('material_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.MaterialType'])), ('volume', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)), ('weight', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)), - ('item_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), + ('find_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)), ('upstream_treatment', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='downstream_treatment', null=True, to=orm['archaeological_finds.Treatment'])), ('downstream_treatment', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='upstream_treatment', null=True, to=orm['archaeological_finds.Treatment'])), ('dating', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_context_records.Dating'])), - ('container', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='items', null=True, to=orm['archaeological_warehouse.Container'])), + ('container', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='finds', null=True, to=orm['archaeological_warehouse.Container'])), )) - db.send_create_signal('archaeological_finds', ['Item']) + db.send_create_signal('archaeological_finds', ['Find']) - # Adding M2M table for field base_items on 'Item' - db.create_table('archaeological_finds_item_base_items', ( + # Adding M2M table for field base_finds on 'Find' + db.create_table('archaeological_finds_find_base_finds', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('item', models.ForeignKey(orm['archaeological_finds.item'], null=False)), - ('baseitem', models.ForeignKey(orm['archaeological_finds.baseitem'], null=False)) + ('find', models.ForeignKey(orm['archaeological_finds.find'], null=False)), + ('basefind', models.ForeignKey(orm['archaeological_finds.basefind'], null=False)) )) - db.create_unique('archaeological_finds_item_base_items', ['item_id', 'baseitem_id']) + db.create_unique('archaeological_finds_find_base_finds', ['find_id', 'basefind_id']) - # Adding model 'ItemSource' - db.create_table('archaeological_finds_itemsource', ( + # Adding model 'FindSource' + db.create_table('archaeological_finds_findsource', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('title', self.gf('django.db.models.fields.CharField')(max_length=200)), ('source_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.SourceType'])), ('associated_url', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True)), ('receipt_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), ('creation_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)), - ('item', self.gf('django.db.models.fields.related.ForeignKey')(related_name='source', to=orm['archaeological_finds.Item'])), + ('find', self.gf('django.db.models.fields.related.ForeignKey')(related_name='source', to=orm['archaeological_finds.Find'])), )) - db.send_create_signal('archaeological_finds', ['ItemSource']) + db.send_create_signal('archaeological_finds', ['FindSource']) - # Adding M2M table for field authors on 'ItemSource' - db.create_table('archaeological_finds_itemsource_authors', ( + # Adding M2M table for field authors on 'FindSource' + db.create_table('archaeological_finds_findsource_authors', ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('itemsource', models.ForeignKey(orm['archaeological_finds.itemsource'], null=False)), + ('findsource', models.ForeignKey(orm['archaeological_finds.findsource'], null=False)), ('author', models.ForeignKey(orm['ishtar_common.author'], null=False)) )) - db.create_unique('archaeological_finds_itemsource_authors', ['itemsource_id', 'author_id']) + db.create_unique('archaeological_finds_findsource_authors', ['findsource_id', 'author_id']) # Adding model 'TreatmentType' db.create_table('archaeological_finds_treatmenttype', ( @@ -186,7 +186,7 @@ class Migration(SchemaMigration): ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])), ('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), - ('item', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.Item'])), + ('find', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.Find'])), ('administrative_act', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_operations.AdministrativeAct'])), ('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Person'])), ('start_date', self.gf('django.db.models.fields.DateField')()), @@ -199,26 +199,26 @@ class Migration(SchemaMigration): # Deleting model 'MaterialType' db.delete_table('archaeological_finds_materialtype') - # Deleting model 'HistoricalBaseItem' - db.delete_table('archaeological_finds_historicalbaseitem') + # Deleting model 'HistoricalBaseFind' + db.delete_table('archaeological_finds_historicalbasefind') - # Deleting model 'BaseItem' - db.delete_table('archaeological_finds_baseitem') + # Deleting model 'BaseFind' + db.delete_table('archaeological_finds_basefind') - # Deleting model 'HistoricalItem' - db.delete_table('archaeological_finds_historicalitem') + # Deleting model 'HistoricalFind' + db.delete_table('archaeological_finds_historicalfind') - # Deleting model 'Item' - db.delete_table('archaeological_finds_item') + # Deleting model 'Find' + db.delete_table('archaeological_finds_find') - # Removing M2M table for field base_items on 'Item' - db.delete_table('archaeological_finds_item_base_items') + # Removing M2M table for field base_finds on 'Find' + db.delete_table('archaeological_finds_find_base_finds') - # Deleting model 'ItemSource' - db.delete_table('archaeological_finds_itemsource') + # Deleting model 'FindSource' + db.delete_table('archaeological_finds_findsource') - # Removing M2M table for field authors on 'ItemSource' - db.delete_table('archaeological_finds_itemsource_authors') + # Removing M2M table for field authors on 'FindSource' + db.delete_table('archaeological_finds_findsource_authors') # Deleting model 'TreatmentType' db.delete_table('archaeological_finds_treatmenttype') @@ -265,7 +265,7 @@ class Migration(SchemaMigration): 'length': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'location': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 'operation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Operation']"}), - 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_context_records.Parcel']"}), + 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Parcel']"}), 'taq': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'taq_estimated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'thickness': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), @@ -308,18 +308,6 @@ class Migration(SchemaMigration): 'order': ('django.db.models.fields.IntegerField', [], {}), 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, - 'archaeological_context_records.parcel': { - 'Meta': {'object_name': 'Parcel'}, - 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}), - 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}), - 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}), - 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}), - 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}), - 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) - }, 'archaeological_context_records.unit': { 'Meta': {'object_name': 'Unit'}, 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -382,9 +370,9 @@ class Migration(SchemaMigration): 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, - 'archaeological_finds.baseitem': { - 'Meta': {'object_name': 'BaseItem'}, - 'context_record': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'base_items'", 'to': "orm['archaeological_context_records.ContextRecord']"}), + 'archaeological_finds.basefind': { + 'Meta': {'object_name': 'BaseFind'}, + 'context_record': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'base_finds'", 'to': "orm['archaeological_context_records.ContextRecord']"}), 'description': ('django.db.models.fields.TextField', [], {}), 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -393,8 +381,36 @@ class Migration(SchemaMigration): 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}), 'material_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}) }, - 'archaeological_finds.historicalbaseitem': { - 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalBaseItem'}, + 'archaeological_finds.find': { + 'Meta': {'object_name': 'Find'}, + 'base_finds': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'find'", 'symmetrical': 'False', 'to': "orm['archaeological_finds.BaseFind']"}), + 'container': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'finds'", 'null': 'True', 'to': "orm['archaeological_warehouse.Container']"}), + 'dating': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_context_records.Dating']"}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'downstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'upstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}), + 'find_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}), + 'material_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.MaterialType']"}), + 'order': ('django.db.models.fields.IntegerField', [], {}), + 'upstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'downstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}), + 'volume': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), + 'weight': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}) + }, + 'archaeological_finds.findsource': { + 'Meta': {'object_name': 'FindSource'}, + 'associated_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.Author']", 'symmetrical': 'False'}), + 'creation_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'find': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['archaeological_finds.Find']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'receipt_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'source_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.SourceType']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'archaeological_finds.historicalbasefind': { + 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalBaseFind'}, 'context_record_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), 'description': ('django.db.models.fields.TextField', [], {}), 'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), @@ -408,19 +424,19 @@ class Migration(SchemaMigration): 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}), 'material_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}) }, - 'archaeological_finds.historicalitem': { - 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalItem'}, + 'archaeological_finds.historicalfind': { + 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalFind'}, 'container_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), 'dating_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), 'downstream_treatment_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'find_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), 'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), 'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), 'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}), - 'item_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}), 'material_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), 'order': ('django.db.models.fields.IntegerField', [], {}), @@ -444,34 +460,6 @@ class Migration(SchemaMigration): 'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 'treatment_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}) }, - 'archaeological_finds.item': { - 'Meta': {'object_name': 'Item'}, - 'base_items': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'item'", 'symmetrical': 'False', 'to': "orm['archaeological_finds.BaseItem']"}), - 'container': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'to': "orm['archaeological_warehouse.Container']"}), - 'dating': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_context_records.Dating']"}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'downstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'upstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}), - 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}), - 'material_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.MaterialType']"}), - 'order': ('django.db.models.fields.IntegerField', [], {}), - 'upstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'downstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}), - 'volume': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'weight': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}) - }, - 'archaeological_finds.itemsource': { - 'Meta': {'object_name': 'ItemSource'}, - 'associated_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), - 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.Author']", 'symmetrical': 'False'}), - 'creation_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['archaeological_finds.Item']"}), - 'receipt_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'source_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.SourceType']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) - }, 'archaeological_finds.materialtype': { 'Meta': {'object_name': 'MaterialType'}, 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -486,10 +474,10 @@ class Migration(SchemaMigration): 'Meta': {'object_name': 'Property'}, 'administrative_act': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_operations.AdministrativeAct']"}), 'end_date': ('django.db.models.fields.DateField', [], {}), + 'find': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.Find']"}), 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.Item']"}), 'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']"}), 'start_date': ('django.db.models.fields.DateField', [], {}) }, @@ -588,6 +576,18 @@ class Migration(SchemaMigration): 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, + 'archaeological_operations.parcel': { + 'Meta': {'object_name': 'Parcel'}, + 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}), + 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}), + 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}), + 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}), + 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}), + 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + }, 'archaeological_operations.period': { 'Meta': {'object_name': 'Period'}, 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index cea9a35f1..c61e22e68 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -39,11 +39,11 @@ class MaterialType(GeneralType): verbose_name = _(u"Material type") verbose_name_plural = _(u"Material types") -class BaseItem(BaseHistorizedItem, OwnPerms): +class BaseFind(BaseHistorizedItem, OwnPerms): label = models.CharField(_(u"ID"), max_length=60) description = models.TextField(_(u"Description")) context_record = models.ForeignKey(ContextRecord, - related_name='base_items', verbose_name=_(u"Context Record")) + related_name='base_finds', verbose_name=_(u"Context Record")) is_isolated = models.NullBooleanField(_(u"Is isolated?"), blank=True, null=True) index = models.IntegerField(u"Index", default=0) @@ -51,40 +51,40 @@ class BaseItem(BaseHistorizedItem, OwnPerms): history = HistoricalRecords() class Meta: - verbose_name = _(u"Base item") - verbose_name_plural = _(u"Base items") + verbose_name = _(u"Base find") + verbose_name_plural = _(u"Base finds") permissions = ( - ("view_own_baseitem", ugettext(u"Can view own Base item")), - ("add_own_baseitem", ugettext(u"Can add own Base item")), - ("change_own_baseitem", ugettext(u"Can change own Base item")), - ("delete_own_baseitem", ugettext(u"Can delete own Base item")), + ("view_own_basefind", ugettext(u"Can view own Base find")), + ("add_own_basefind", ugettext(u"Can add own Base find")), + ("change_own_basefind", ugettext(u"Can change own Base find")), + ("delete_own_basefind", ugettext(u"Can delete own Base find")), ) def __unicode__(self): return self.label - def get_last_item(self): - #TODO: manage virtuals - property(last_item) ? - items = self.item.filter().order_by("-order").all() - return items and items[0] + def get_last_find(self): + #TODO: manage virtuals - property(last_find) ? + finds = self.find.filter().order_by("-order").all() + return finds and finds[0] def full_label(self): return self._real_label() or self._temp_label() def material_type_label(self): - item = self.get_last_item() - items = [item and unicode(item.material_type) or ''] + find = self.get_last_find() + finds = [find and unicode(find.material_type) or ''] ope = self.context_record.operation - items += [ope.code_patriarche or \ + finds += [ope.code_patriarche or \ (unicode(ope.year) + "-" + unicode(ope.operation_code))] - items += [self.context_record.label, unicode(self.material_index)] - return JOINT.join(items) + finds += [self.context_record.label, unicode(self.material_index)] + return JOINT.join(finds) def _real_label(self): if not self.context_record.parcel.operation.code_patriarche: return - item = self.get_last_item() - lbl = item.label or self.label + find = self.get_last_find() + lbl = find.label or self.label return JOINT.join([unicode(it) for it in ( self.context_record.parcel.operation.code_patriarche, self.context_record.label, @@ -93,25 +93,25 @@ class BaseItem(BaseHistorizedItem, OwnPerms): def _temp_label(self): if self.context_record.parcel.operation.code_patriarche: return - item = self.get_last_item() - lbl = item.label or self.label + find = self.get_last_find() + lbl = find.label or self.label return JOINT.join([unicode(it) for it in ( self.context_record.parcel.year, self.index, self.context_record.label, lbl) if it]) -class Item(BaseHistorizedItem, OwnPerms): +class Find(BaseHistorizedItem, OwnPerms): TABLE_COLS = ['label', 'material_type', 'dating.period', - 'base_items.context_record.parcel.town', - 'base_items.context_record.parcel.operation.year', - 'base_items.context_record.parcel.operation.operation_code', - 'base_items.is_isolated'] + 'base_finds.context_record.parcel.town', + 'base_finds.context_record.parcel.operation.year', + 'base_finds.context_record.parcel.operation.operation_code', + 'base_finds.is_isolated'] if settings.COUNTRY == 'fr': TABLE_COLS.insert(6, - 'base_items.context_record.parcel.operation.code_patriarche') - base_items = models.ManyToManyField(BaseItem, verbose_name=_(u"Base item"), - related_name='item') + 'base_finds.context_record.parcel.operation.code_patriarche') + base_finds = models.ManyToManyField(BaseFind, verbose_name=_(u"Base find"), + related_name='find') order = models.IntegerField(_(u"Order")) label = models.CharField(_(u"ID"), max_length=60) description = models.TextField(_(u"Description"), blank=True, null=True) @@ -119,7 +119,7 @@ class Item(BaseHistorizedItem, OwnPerms): verbose_name = _(u"Material type")) volume = models.FloatField(_(u"Volume (l)"), blank=True, null=True) weight = models.FloatField(_(u"Weight (g)"), blank=True, null=True) - item_number = models.IntegerField(_("Item number"), blank=True, null=True) + find_number = models.IntegerField(_("Find number"), blank=True, null=True) upstream_treatment = models.ForeignKey("Treatment", blank=True, null=True, related_name='downstream_treatment', verbose_name=_("Upstream treatment")) downstream_treatment = models.ForeignKey("Treatment", blank=True, null=True, @@ -127,15 +127,15 @@ class Item(BaseHistorizedItem, OwnPerms): dating = models.ForeignKey(Dating, verbose_name=_(u"Dating")) if WAREHOUSE_AVAILABLE: container = models.ForeignKey(Container, verbose_name=_(u"Container"), - blank=True, null=True, related_name='items') + blank=True, null=True, related_name='finds') history = HistoricalRecords() @classmethod def get_years(cls): years = set() - items = cls.objects.filter(downstream_treatment__isnull=True) - for item in items: - bi = item.base_items.all() + finds = cls.objects.filter(downstream_treatment__isnull=True) + for find in finds: + bi = find.base_finds.all() if not bi: continue bi = bi[0] @@ -146,14 +146,14 @@ class Item(BaseHistorizedItem, OwnPerms): @classmethod def get_by_year(cls, year): return cls.objects.filter(downstream_treatment__isnull=True, - base_items__context_record__operation__start_date__year=year) + base_finds__context_record__operation__start_date__year=year) @classmethod def get_operations(cls): operations = set() - items = cls.objects.filter(downstream_treatment__isnull=True) - for item in items: - bi = item.base_items.all() + finds = cls.objects.filter(downstream_treatment__isnull=True) + for find in finds: + bi = find.base_finds.all() if not bi: continue bi = bi[0] @@ -164,7 +164,7 @@ class Item(BaseHistorizedItem, OwnPerms): @classmethod def get_by_operation(cls, operation_id): return cls.objects.filter(downstream_treatment__isnull=True, - base_items__context_record__operation__pk=operation_id) + base_finds__context_record__operation__pk=operation_id) @classmethod def get_total_number(cls): @@ -173,23 +173,23 @@ class Item(BaseHistorizedItem, OwnPerms): def duplicate(self, user): dct = dict([(attr, getattr(self, attr)) for attr in ('order', 'label', 'description', 'material_type', 'volume', 'weight', - 'item_number', 'dating')]) + 'find_number', 'dating')]) dct['order'] += 1 dct['history_modifier'] = user new = self.__class__(**dct) new.save() - for base_item in self.base_items.all(): - new.base_items.add(base_item) + for base_find in self.base_finds.all(): + new.base_finds.add(base_find) return new class Meta: - verbose_name = _(u"Item") - verbose_name_plural = _(u"Items") + verbose_name = _(u"Find") + verbose_name_plural = _(u"Finds") permissions = ( - ("view_own_item", ugettext(u"Can view own Item")), - ("add_own_item", ugettext(u"Can add own Item")), - ("change_own_item", ugettext(u"Can change own Item")), - ("delete_own_item", ugettext(u"Can delete own Item")), + ("view_own_find", ugettext(u"Can view own Find")), + ("add_own_find", ugettext(u"Can add own Find")), + ("change_own_find", ugettext(u"Can change own Find")), + ("delete_own_find", ugettext(u"Can delete own Find")), ) def __unicode__(self): @@ -197,27 +197,27 @@ class Item(BaseHistorizedItem, OwnPerms): def save(self, *args, **kwargs): if not self.pk: - super(Item, self).save(*args, **kwargs) - for base_item in self.base_items.all(): - if not base_item.index: - idx = BaseItem.objects.filter(context_record=\ - base_item.context_record).aggregate(Max('index')) - base_item.index = idx and idx['index__max'] + 1 or 1 - if not base_item.material_index: - idx = BaseItem.objects.filter(context_record=\ - base_item.context_record, - item__material_type=self.material_type).aggregate( + super(Find, self).save(*args, **kwargs) + for base_find in self.base_finds.all(): + if not base_find.index: + idx = BaseFind.objects.filter(context_record=\ + base_find.context_record).aggregate(Max('index')) + base_find.index = idx and idx['index__max'] + 1 or 1 + if not base_find.material_index: + idx = BaseFind.objects.filter(context_record=\ + base_find.context_record, + find__material_type=self.material_type).aggregate( Max('material_index')) - base_item.material_index = idx and \ + base_find.material_index = idx and \ idx['material_index__max'] + 1 or 1 - base_item.save() - super(Item, self).save(*args, **kwargs) + base_find.save() + super(Find, self).save(*args, **kwargs) -class ItemSource(Source): +class FindSource(Source): class Meta: - verbose_name = _(u"Item documentation") - verbose_name_plural = _(u"Item documentations") - item = models.ForeignKey(Item, verbose_name=_(u"Item"), + verbose_name = _(u"Find documentation") + verbose_name_plural = _(u"Find documentations") + find = models.ForeignKey(Find, verbose_name=_(u"Find"), related_name="source") class TreatmentType(GeneralType): @@ -265,7 +265,7 @@ class TreatmentSource(Source): related_name="source") class Property(LightHistorizedItem): - item = models.ForeignKey(Item, verbose_name=_(u"Item")) + find = models.ForeignKey(Find, verbose_name=_(u"Find")) administrative_act = models.ForeignKey(AdministrativeAct, verbose_name=_(u"Administrative act")) person = models.ForeignKey(Person, verbose_name=_(u"Person")) @@ -277,5 +277,5 @@ class Property(LightHistorizedItem): verbose_name_plural = _(u"Properties") def __unicode__(self): - return self.person + JOINT + self.item + return self.person + JOINT + self.find diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py new file mode 100644 index 000000000..4c733436d --- /dev/null +++ b/archaeological_finds/urls.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2012 É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. + +from django.conf.urls.defaults import * + +""" +import forms + +# forms +urlpatterns = patterns('', + url(r'item_search/(?P<step>.+)$', + forms.item_search_wizard, name='item_search'), + url(r'item_creation/(?P<step>.+)$', + forms.item_creation_wizard, name='item_creation'), + url(r'item_modification/(?P<step>.+)$', + forms.item_modification_wizard, name='item_modification'), + url(r'item_source_creation/(?P<step>.+)$', + forms.item_source_creation_wizard, + name='item_source_creation'), + url(r'item_source_modification/(?P<step>.+)$', + forms.item_source_modification_wizard, + name='item_source_modification'), + url(r'item_source_deletion/(?P<step>.+)$', + forms.item_source_deletion_wizard, + name='item_source_deletion'), +) + +urlpatterns += patterns('archaeological_finds.views', + url(r'get-find/(?P<type>.+)?$', 'get_find', + name='get-find'), + url(r'get-find-full/(?P<type>.+)?$', 'get_find', + name='get-find-full', kwargs={'full':True}), + url(r'get-findsource/(?P<type>.+)?$', + 'get_findsource', name='get-findsource'), +) +""" diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py new file mode 100644 index 000000000..af428d59e --- /dev/null +++ b/archaeological_finds/views.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2012 É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. + +from ishtar_common.views import get_item, show_item, revert_item +import models + +get_find = get_item(models.Find, + 'get_find', 'find', + bool_fields = ['base_finds__is_isolated'], + base_request={'downstream_treatment__isnull':True}, + extra_request_keys={ +'base_finds__context_record__parcel__town': + 'base_finds__context_record__parcel__town', +'base_finds__context_record__operation__year': + 'base_finds__context_record__operation__year__contains', +'base_finds__context_record__operation__code_patriarche': + 'base_finds__context_record__operation__code_patriarche', +'dating__period':'dating__period__pk', +'base_finds__find__description':'base_finds__find__description__icontains', +'base_finds__is_isolated':'base_finds__is_isolated'}) +get_findsource = get_item(models.FindSource, + 'get_findsource', 'findsource', + extra_request_keys={ +'find__context_record__operation__year':'find__context_record__operation__year', +'find__dating__period':'find__dating__period__pk', +'find__description':'find__description__icontains', + }) |