summaryrefslogtreecommitdiff
path: root/ishtar/ishtar_base
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar/ishtar_base')
-rw-r--r--ishtar/ishtar_base/__init__.py0
-rw-r--r--ishtar/ishtar_base/admin.py240
-rw-r--r--ishtar/ishtar_base/backend.py62
-rw-r--r--ishtar/ishtar_base/context_processors.py55
-rw-r--r--ishtar/ishtar_base/fixtures/initial_data.json1863
-rw-r--r--ishtar/ishtar_base/forms.py249
-rw-r--r--ishtar/ishtar_base/forms_common.py519
-rw-r--r--ishtar/ishtar_base/forms_context_records.py362
-rw-r--r--ishtar/ishtar_base/forms_files.py387
-rw-r--r--ishtar/ishtar_base/forms_items.py525
-rw-r--r--ishtar/ishtar_base/forms_main.py26
-rw-r--r--ishtar/ishtar_base/forms_operations.py754
-rw-r--r--ishtar/ishtar_base/management/__init__.py0
-rw-r--r--ishtar/ishtar_base/management/commands/__init__.py0
-rw-r--r--ishtar/ishtar_base/management/commands/generate_rights.py71
-rw-r--r--ishtar/ishtar_base/menus.py331
-rw-r--r--ishtar/ishtar_base/models.py2163
-rw-r--r--ishtar/ishtar_base/templatetags/__init__.py1
-rw-r--r--ishtar/ishtar_base/templatetags/range.py10
-rw-r--r--ishtar/ishtar_base/templatetags/table_form.py10
-rw-r--r--ishtar/ishtar_base/tests.py125
-rw-r--r--ishtar/ishtar_base/urls.py223
-rw-r--r--ishtar/ishtar_base/views.py1333
-rw-r--r--ishtar/ishtar_base/widgets.py367
24 files changed, 0 insertions, 9676 deletions
diff --git a/ishtar/ishtar_base/__init__.py b/ishtar/ishtar_base/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/ishtar/ishtar_base/__init__.py
+++ /dev/null
diff --git a/ishtar/ishtar_base/admin.py b/ishtar/ishtar_base/admin.py
deleted file mode 100644
index ac110e9e5..000000000
--- a/ishtar/ishtar_base/admin.py
+++ /dev/null
@@ -1,240 +0,0 @@
-#!/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.
-
-"""
-Admin description
-"""
-
-from django import forms
-from django.contrib import admin
-from django.core.exceptions import ObjectDoesNotExist
-from django.utils.translation import ugettext_lazy as _
-
-from ishtar import settings
-import models
-
-class HistorizedObjectAdmin(admin.ModelAdmin):
- readonly_fields = ('history_modifier',)
- def save_model(self, request, obj, form, change):
- obj.history_modifier = request.user
- obj.save()
-
-class DepartementAdmin(admin.ModelAdmin):
- list_display = ('number', 'label',)
- model = models.Departement
-
-admin.site.register(models.Departement, DepartementAdmin)
-
-class OrganizationAdmin(HistorizedObjectAdmin):
- list_display = ('name', 'organization_type')
- list_filter = ("organization_type",)
- search_fields = ('name',)
- model = models.Organization
-
-admin.site.register(models.Organization, OrganizationAdmin)
-
-class PersonAdmin(HistorizedObjectAdmin):
- list_display = ('name', 'surname', 'email', 'person_type')
- list_filter = ("person_type",)
- search_fields = ('name', 'surname', 'email',)
- model = models.Person
-
-admin.site.register(models.Person, PersonAdmin)
-
-class FileAdmin(HistorizedObjectAdmin):
- list_display = ['year', 'numeric_reference', 'internal_reference',
- 'end_date', 'file_type', 'general_contractor',]
- if settings.COUNTRY == 'fr':
- list_display += ['saisine_type', 'reference_number']
- list_filter = ("file_type", "year",)
- search_fields = ('towns__name',)
- model = models.File
-
-admin.site.register(models.File, FileAdmin)
-
-class OperationAdmin(HistorizedObjectAdmin):
- list_display = ['year', 'operation_code', 'start_date',
- 'excavation_end_date', 'end_date',
- 'operation_type']
- list_filter = ("year", "operation_type",)
- search_fields = ['towns__name', 'operation_code']
- if settings.COUNTRY == 'fr':
- list_display += ['code_patriarche']
- search_fields += ['code_patriarche']
- model = models.Operation
-
-admin.site.register(models.Operation, OperationAdmin)
-
-class OperationSourceAdmin(admin.ModelAdmin):
- list_display = ('operation', 'title', 'source_type',)
- list_filter = ('source_type',)
- search_fields = ('title', 'operation__name')
- model = models.OperationSource
-
-admin.site.register(models.OperationSource, OperationSourceAdmin)
-
-class ParcelAdmin(HistorizedObjectAdmin):
- list_display = ('section', 'parcel_number', 'operation', 'associated_file')
- search_fields = ('operation__name',)
- model = models.Parcel
-
-admin.site.register(models.Parcel, ParcelAdmin)
-
-class PeriodAdmin(admin.ModelAdmin):
- list_display = ('label', 'start_date', 'end_date', 'parent')
- model = models.Period
-
-admin.site.register(models.Period, PeriodAdmin)
-
-class DatingAdmin(admin.ModelAdmin):
- list_display = ('period', 'start_date', 'end_date', 'dating_type',
- 'quality')
- list_filter = ("period", 'dating_type', 'quality')
- model = models.Dating
-
-admin.site.register(models.Dating, DatingAdmin)
-
-class ContextRecordAdmin(HistorizedObjectAdmin):
- list_display = ('label', 'length', 'width',
- 'thickness', 'depth')
- list_filter = ('has_furniture',)
- search_fields = ('parcel__operation__name', "datings__period__label")
- model = models.ContextRecord
-
-admin.site.register(models.ContextRecord, ContextRecordAdmin)
-
-class ContextRecordSourceAdmin(admin.ModelAdmin):
- list_display = ('context_record', 'title', 'source_type',)
- list_filter = ('source_type',)
- search_fields = ('title', )
- model = models.ContextRecordSource
-
-admin.site.register(models.ContextRecordSource, ContextRecordSourceAdmin)
-
-class BaseItemAdmin(HistorizedObjectAdmin):
- list_display = ('label', 'context_record', 'is_isolated')
- search_fields = ('label', 'context_record__parcel__operation__name',)
- model = models.BaseItem
-
-admin.site.register(models.BaseItem, BaseItemAdmin)
-
-class ItemAdmin(HistorizedObjectAdmin):
- list_display = ('label', 'material_type', 'dating', 'volume', 'weight',
- 'item_number',)
- list_filter = ('material_type',)
- search_fields = ('label', "dating__period__label")
- model = models.Item
-
-admin.site.register(models.Item, ItemAdmin)
-
-class ItemSourceAdmin(admin.ModelAdmin):
- list_display = ('item', 'title', 'source_type',)
- list_filter = ('source_type',)
- search_fields = ('title', )
- model = models.ItemSource
-
-admin.site.register(models.ItemSource, ItemSourceAdmin)
-
-class WarehouseAdmin(HistorizedObjectAdmin):
- list_display = ('name', 'warehouse_type', 'town')
- list_filter = ('warehouse_type',)
- search_fields = ('name', 'town')
- model = models.Warehouse
-
-admin.site.register(models.Warehouse, WarehouseAdmin)
-
-class AdministrativeActAdmin(HistorizedObjectAdmin):
- list_display = ('operation', 'act_type', 'signature_date')
- list_filter = ('act_type',)
- search_fields = ('operation__name',)
- model = models.AdministrativeAct
-
-admin.site.register(models.AdministrativeAct, AdministrativeActAdmin)
-
-class ContainerTypeAdmin(admin.ModelAdmin):
- list_display = ('label', 'reference', 'length', 'width', 'height',
- 'volume')
- model = models.ContainerType
-
-admin.site.register(models.ContainerType, ContainerTypeAdmin)
-
-class ContainerAdmin(admin.ModelAdmin):
- list_display = ('reference', 'location', 'container_type',)
- list_filter = ("container_type",)
- model = models.Container
-
-admin.site.register(models.Container, ContainerAdmin)
-
-class TownAdmin(admin.ModelAdmin):
- list_display = ['name',]
- search_fields = ['name']
- if settings.COUNTRY == 'fr':
- list_display += ['numero_insee', 'departement', ]
- search_fields += ['numero_insee', 'departement__label', ]
- list_filter = ("departement",)
- model = models.Town
-
-admin.site.register(models.Town, TownAdmin)
-
-class AuthorAdmin(admin.ModelAdmin):
- list_display = ['person', 'author_type']
- list_filter = ("author_type",)
- model = models.Author
-
-admin.site.register(models.Author, AuthorAdmin)
-
-class PropertyAdmin(admin.ModelAdmin):
- list_display = ['item', 'person', 'start_date', 'end_date']
- search_fields = ('item__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)
-
-class PersonTypeAdmin(admin.ModelAdmin):
- model = models.PersonType
- filter_vertical = ('rights',)
-
-admin.site.register(models.PersonType, PersonTypeAdmin)
-
-basic_models = [models.IshtarUser, models.FileType, models.OperationType,
- models.DatingType, models.DatingQuality, models.SourceType,
- models.MaterialType, models.ParcelOwner, models.WarehouseType,
- models.ActType, models.AuthorType, models.OrganizationType,
- models.TreatmentType, models.RemainType, models.PermitType,
- models.Unit, models.ActivityType, models.IdentificationType]
-if settings.COUNTRY == 'fr':
- basic_models += [models.Arrondissement, models.Canton, models.SaisineType]
-
-for model in basic_models:
- admin.site.register(model)
diff --git a/ishtar/ishtar_base/backend.py b/ishtar/ishtar_base/backend.py
deleted file mode 100644
index f50edd708..000000000
--- a/ishtar/ishtar_base/backend.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/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.
-
-"""
-Permission backend to manage "own" objects
-"""
-
-from django.conf import settings
-from django.contrib.auth.models import User
-from django.core.exceptions import ObjectDoesNotExist
-
-import models
-
-class ObjectOwnPermBackend(object):
- supports_object_permissions = True
- supports_anonymous_user = True
-
- def authenticate(self, username, password):
- # managed by the default backend
- return None
-
- def has_perm(self, user_obj, perm, model=None, obj=None):
- if not user_obj.is_authenticated():
- return False
- if not model:
- # let it manage by the default backend
- return False
- try:
- ishtar_user = models.IshtarUser.objects.get(user_ptr=user_obj)
- except ObjectDoesNotExist:
- return False
- try:
- # only manage "own" permissions
- assert perm.split('.')[-1].split('_')[1] == 'own'
- except (IndexError, AssertionError):
- return False
- if ishtar_user.person.person_type \
- == models.PersonType.objects.get(txt_idx="administrator"):
- return True
- if obj is None:
- model_name = perm.split('_')[-1].capitalize()
- if not hasattr(models, model_name):
- return False
- model = getattr(models, model_name)
- return user_obj.has_perm(perm) and model.has_item_of(ishtar_user)
- return user_obj.has_perm(perm) and obj.is_own(user_obj)
diff --git a/ishtar/ishtar_base/context_processors.py b/ishtar/ishtar_base/context_processors.py
deleted file mode 100644
index 2dc06c6f8..000000000
--- a/ishtar/ishtar_base/context_processors.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/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.
-
-from django.utils.translation import ugettext, ugettext_lazy as _
-from django.contrib.sites.models import Site
-
-from ishtar import settings
-from menus import Menu
-import models
-
-def get_base_context(request):
- dct = {'URL_PATH':settings.URL_PATH}
- dct["APP_NAME"] = Site.objects.get_current().name
- dct["COUNTRY"] = settings.COUNTRY
- if 'MENU' not in request.session or \
- request.session['MENU'].user != request.user:
- menu = Menu(request.user)
- menu.init()
- request.session['MENU'] = menu
- if 'CURRENT_ACTION' in request.session:
- dct['CURRENT_ACTION'] = request.session['CURRENT_ACTION']
- dct['MENU'] = request.session['MENU']
- dct['JQUERY_URL'] = settings.JQUERY_URL
- dct['JQUERY_UI_URL'] = settings.JQUERY_UI_URL
- dct['current_menu'] = []
- for lbl, model in ((_(u"Archaeological file"), models.File),
- (_(u"Operation"), models.Operation),
- (_(u"Context record"), models.ContextRecord),
- (_(u"Archaeological item"), models.Item),
- ):
- model_name = model.__name__.lower()
- current = model_name in request.session and request.session[model_name]
- items = []
- for item in model.get_owns(request.user):
- items.append((item.pk, unicode(item), unicode(item.pk) == current))
- if items:
- dct['current_menu'].append((lbl, model_name, items))
- return dct
-
diff --git a/ishtar/ishtar_base/fixtures/initial_data.json b/ishtar/ishtar_base/fixtures/initial_data.json
deleted file mode 100644
index 3397a2cd5..000000000
--- a/ishtar/ishtar_base/fixtures/initial_data.json
+++ /dev/null
@@ -1,1863 +0,0 @@
-[
- {
- "pk": 1,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "sra",
- "label": "Service R\u00e9gional d'Arch\u00e9ologie"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "D\u00e9cret 2004\r\n\r\n\"Op\u00e9rateurs\" les personnes qui r\u00e9alisent les op\u00e9rations arch\u00e9ologiques.",
- "available": true,
- "txt_idx": "operator",
- "label": "Op\u00e9rateur d'arch\u00e9ologie pr\u00e9ventive"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "Laboratoire ayant sous sa responsabilit\u00e9 du mobilier arch\u00e9ologique de mani\u00e8re temporaire. C'est un type de d\u00e9p\u00f4t. C'est un lieu de traitement.",
- "available": true,
- "txt_idx": "restoration_laboratory",
- "label": "Laboratoire de restauration"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "Pour des entreprises, collectivit\u00e9s territoriales ou autres organisations",
- "available": true,
- "txt_idx": "general_contractor",
- "label": "Am\u00e9nageur"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "Cette organisation et ses membres travaillent b\u00e9n\u00e9volement",
- "available": true,
- "txt_idx": "volunteer",
- "label": "B\u00e9n\u00e9vole"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "les services qui d\u00e9livrent les autorisations requises pour les diff\u00e9rents projets (DDE, services\r\nurbanisme des collectivit\u00e9s, pr\u00e9fectures, Drire, etc.)",
- "available": true,
- "txt_idx": "planning_service",
- "label": "Service instructeur"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "museum",
- "label": "Mus\u00e9e"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.organizationtype",
- "fields": {
- "comment": "Laboratoire de recherche du CNRS. Peut-\u00eatre une UMR et donc int\u00e9gr\u00e9 des chercheurs de l'universit\u00e9. n'inclus pas les \"laboratoires\" priv\u00e9s",
- "available": true,
- "txt_idx": "research_laboratory",
- "label": "Laboratoire de recherche"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "administrator",
- "label": "Administrateur"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Article 13 D\u00e9cret 2004\r\n\r\nLe pr\u00e9fet de r\u00e9gion \u00e9dicte les prescriptions arch\u00e9ologiques, d\u00e9livre l'autorisation de fouille et d\u00e9signe le responsable scientifique de toute op\u00e9ration d'arch\u00e9ologie pr\u00e9ventive.\r\n\r\nLe responsable scientifique est l'interlocuteur du pr\u00e9fet de r\u00e9gion et le garant de la qualit\u00e9 scientifique de l'op\u00e9ration arch\u00e9ologique. A ce titre, il prend, dans le cadre de la mise en oeuvre du projet d'intervention de l'op\u00e9rateur, les d\u00e9cisions relatives \u00e0 la conduite scientifique de l'op\u00e9ration et \u00e0 l'\u00e9laboration du rapport dont il dirige la r\u00e9daction. Il peut \u00eatre diff\u00e9rent pour la r\u00e9alisation du diagnostic et pour la r\u00e9alisation de la fouille.",
- "available": true,
- "txt_idx": "head_scientist",
- "label": "Responsable scientifique"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Responsables de dossiers d'arch\u00e9ologie",
- "available": true,
- "txt_idx": "sra_agent",
- "label": "Agent scientifique SRA"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Acc\u00e8s pour les secr\u00e9taires d'un SRA",
- "available": true,
- "txt_idx": "secretarial_dept",
- "label": "Secr\u00e9tariat SRA"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Cette personne peut g\u00e9rer du mobilier qu'il n'a pas cr\u00e9\u00e9\r\n\r\n",
- "available": true,
- "txt_idx": "warehouse_manager",
- "label": "Gestionnaire de d\u00e9p\u00f4t"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Responsable de l'am\u00e9nagement",
- "available": true,
- "txt_idx": "general_contractor",
- "label": "Am\u00e9nageur"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.persontype",
- "fields": {
- "comment": "Un acc\u00e8s limit\u00e9 \u00e0 la base, uniquement en lecture. Apr\u00e8s enregistrement.",
- "available": true,
- "txt_idx": "public_access",
- "label": "Acc\u00e8s publique"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.authortype",
- "fields": {
- "comment": "Il y a plusieurs \u00e0 une m\u00eame source. Au m\u00eame niveau de responsabilit\u00e9.",
- "available": true,
- "txt_idx": "co_author",
- "label": "Co-auteur "
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.authortype",
- "fields": {
- "comment": "Cette personne est l'auteur principal de la source. Les autres auteurs sont des collaborateurs.",
- "available": true,
- "txt_idx": "main_author",
- "label": "Auteur principal"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.authortype",
- "fields": {
- "comment": "Cet auteur n'est pas l'auteur principal de la source mais un collaborateur. Il n'est pas auteur au m\u00eame niveau que l'auteur principal.",
- "available": true,
- "txt_idx": "associate_author",
- "label": "Collaborateur"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Photographie argentique sous une forme imprim\u00e9e",
- "available": true,
- "txt_idx": "photo_print",
- "label": "Epreuve de photographie argentique"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport de fouille arch\u00e9ologique",
- "available": true,
- "txt_idx": "final_archaeological_report",
- "label": "Rapport final d'op\u00e9ration (fouille)"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport li\u00e9 \u00e0 une autorisation de sondage.",
- "available": true,
- "txt_idx": "survey_report",
- "label": "Rapport de sondage"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport li\u00e9 \u00e0 un arr\u00eat\u00e9 de prescription de diagnostic arch\u00e9ologique.",
- "available": true,
- "txt_idx": "diagnostic_report",
- "label": "Rapport de diagnostic"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Source photographique num\u00e9rique",
- "available": true,
- "txt_idx": "digital_photo",
- "label": "Photographie num\u00e9rique"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport de laboratoire d'analyse",
- "available": true,
- "txt_idx": "lab_report",
- "label": "Rapport d'analyse"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport li\u00e9 \u00e0 la restauration ou la stabilisation d'un lot de mobilier ou d'un objet isol\u00e9",
- "available": true,
- "txt_idx": "restoration_report",
- "label": "Rapport de restauration"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport li\u00e9 \u00e0 une autorisation de prospection inventaire",
- "available": true,
- "txt_idx": "general_survey_report",
- "label": "Rapport de prospection inventaire"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.sourcetype",
- "fields": {
- "comment": "Rapport li\u00e9 \u00e0 une autorisation de prospection th\u00e9matique. Ce type de rapport passe d'ordinaire en CIRA.",
- "available": true,
- "txt_idx": "thematic_survey_report",
- "label": "Rapport de prospection th\u00e9matique"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.filetype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "preventive",
- "label": "Arch\u00e9ologie pr\u00e9ventive"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.filetype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "prog",
- "label": "Arch\u00e9ologie programm\u00e9e"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.permittype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "pc",
- "label": "PC"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.permittype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "pa",
- "label": "PA"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.permittype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "zac",
- "label": "Dossier de r\u00e9alisation de ZAC"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.permittype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "ei",
- "label": "Etude d'impact"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.permittype",
- "fields": {
- "comment": "Certificat d'urbanisme",
- "available": true,
- "txt_idx": "cu",
- "label": "CU"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.saisinetype",
- "fields": {
- "comment": " I. - Dans les cas mentionn\u00e9s aux 1\u00b0 \u00e0 5\u00b0 de l'article 4, le pr\u00e9fet de r\u00e9gion est saisi :\r\n\r\n1\u00b0 Pour les permis de construire, les permis d'am\u00e9nager et les permis de d\u00e9molir, par le pr\u00e9fet de d\u00e9partement qui lui adresse, d\u00e8s qu'il a re\u00e7u les \u00e9l\u00e9ments transmis par le maire en application des articles R. 423-7 \u00e0 R. 423-9 du code de l'urbanisme, les pi\u00e8ces pr\u00e9vues par le dernier alin\u00e9a de l'article R. 423-2, faisant notamment appara\u00eetre l'emplacement pr\u00e9vu des travaux sur le terrain d'assiette, leur superficie, leur impact sur le sous-sol ;\r\n\r\n2\u00b0 Pour les zones d'am\u00e9nagement concert\u00e9, par la personne publique ayant pris l'initiative de la cr\u00e9ation de la zone qui adresse au pr\u00e9fet de r\u00e9gion le dossier de r\u00e9alisation approuv\u00e9 pr\u00e9vu \u00e0 l'article R. 311-7 du code de l'urbanisme ;\r\n\r\n3\u00b0 Abrog\u00e9\r\n\r\n4\u00b0 Pour les am\u00e9nagements et ouvrages mentionn\u00e9s au 5\u00b0 de l'article 4 qui sont soumis \u00e0 une autorisation administrative autre qu'une autorisation d'urbanisme, par le service charg\u00e9 de recevoir la demande d'autorisation, qui adresse une copie du dossier de demande au pr\u00e9fet de r\u00e9gion ;\r\n\r\n5\u00b0 Pour les am\u00e9nagements et ouvrages mentionn\u00e9s au 5\u00b0 de l'article 4 qui ne sont pas soumis \u00e0 une autorisation administrative, par l'am\u00e9nageur. Celui-ci adresse au pr\u00e9fet de r\u00e9gion un dossier d\u00e9crivant les travaux projet\u00e9s, notamment leur emplacement pr\u00e9vu sur le terrain d'assiette, leur superficie, leur impact sur le sous-sol et indiquant la date \u00e0 laquelle ils ont \u00e9t\u00e9 arr\u00eat\u00e9s.\r\n\r\nII. - Pour les travaux sur des monuments historiques mentionn\u00e9s au 6\u00b0 de l'article 4, la saisine du pr\u00e9fet de r\u00e9gion au titre de l'autorisation exig\u00e9e par l'article L. 621-9 du code du patrimoine vaut saisine au titre du pr\u00e9sent d\u00e9cret.",
- "available": true,
- "txt_idx": "Article_8",
- "delay": 21,
- "label": "Article 8"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.saisinetype",
- "fields": {
- "comment": " Les am\u00e9nageurs peuvent, avant de d\u00e9poser une demande pour obtenir les autorisations requises par les lois et r\u00e8glements ou avant d'engager toute autre proc\u00e9dure, saisir le pr\u00e9fet de r\u00e9gion afin qu'il examine si leur projet est susceptible de donner lieu \u00e0 des prescriptions arch\u00e9ologiques.\r\n\r\nA cette fin, ils produisent un dossier qui comporte un plan parcellaire et les r\u00e9f\u00e9rences cadastrales, le descriptif du projet et son emplacement sur le terrain d'assiette ainsi que, le cas \u00e9ch\u00e9ant, une notice pr\u00e9cisant les modalit\u00e9s techniques envisag\u00e9es pour l'ex\u00e9cution des travaux.\r\n\r\nSi le pr\u00e9fet de r\u00e9gion constate que le projet est susceptible d'affecter des \u00e9l\u00e9ments du patrimoine arch\u00e9ologique, il informe le demandeur, dans le d\u00e9lai de deux mois \u00e0 compter de la r\u00e9ception de la demande, que le projet qu'il lui a pr\u00e9sent\u00e9 donnera lieu \u00e0 des prescriptions de diagnostic arch\u00e9ologique.",
- "available": true,
- "txt_idx": "Article_10",
- "delay": 60,
- "label": "Article 10"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.saisinetype",
- "fields": {
- "comment": " Si le pr\u00e9fet de r\u00e9gion a fait conna\u00eetre, en application de l'article 10, la n\u00e9cessit\u00e9 d'un diagnostic, l'am\u00e9nageur peut le saisir d'une demande anticip\u00e9e de prescription.\r\n\r\nLe pr\u00e9fet de r\u00e9gion prescrit alors, dans les conditions pr\u00e9vues par le pr\u00e9sent d\u00e9cret, la r\u00e9alisation d'un diagnostic arch\u00e9ologique et, si des \u00e9l\u00e9ments du patrimoine arch\u00e9ologique pr\u00e9sents sur le site sont d\u00e9j\u00e0 connus, prend les autres mesures pr\u00e9vues \u00e0 l'article 14.\r\n\r\nLa redevance d'arch\u00e9ologie pr\u00e9ventive correspondante est due par le demandeur, conform\u00e9ment au dernier alin\u00e9a de l'article L. 524-4 du code du patrimoine.",
- "available": true,
- "txt_idx": "Article_12",
- "delay": 30,
- "label": "Article 12"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.saisinetype",
- "fields": {
- "comment": "Article 6\r\n\r\n Lorsqu'il dispose d'informations lui indiquant qu'un projet qui ne lui est pas transmis en application de l'arr\u00eat\u00e9 mentionn\u00e9 \u00e0 l'article 5 est n\u00e9anmoins susceptible d'affecter des \u00e9l\u00e9ments du patrimoine arch\u00e9ologique, le pr\u00e9fet de r\u00e9gion peut demander au maire de lui communiquer au cours de l'instruction, selon le cas, le dossier de demande de permis de construire, de permis d'am\u00e9nager, de permis de d\u00e9molir ou le dossier de r\u00e9alisation de zone d'am\u00e9nagement concert\u00e9 qui correspond \u00e0 ce projet.\r\n\r\nIl peut, pour le m\u00eame motif, demander au maire de lui communiquer le dossier d'une d\u00e9claration pr\u00e9alable d\u00e9pos\u00e9e en application de l'article L. 421-4 du code de l'urbanisme.",
- "available": true,
- "txt_idx": "Article_6",
- "delay": 30,
- "label": "Auto-saisine"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "Une op\u00e9ration arch\u00e9ologique visant \u00e0 qualifier et quantifier la pr\u00e9sence de vestiges sur une surface donn\u00e9e.",
- "available": true,
- "txt_idx": "arch_diagnostic",
- "label": "Diagnostic arch\u00e9ologique"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "A pr\u00e9ciser",
- "available": true,
- "txt_idx": "prev_excavation",
- "label": "Fouille arch\u00e9ologique pr\u00e9ventive"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "prog_excavation",
- "label": "Fouille programm\u00e9e"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "Pas assez gros pour \u00eatre une fouille, mais porte n\u00e9anmoins atteinte au sous-sol.",
- "available": true,
- "txt_idx": "Sampling",
- "label": "Sondage"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "Une campagne de prospection sur un th\u00e8me particulier",
- "available": true,
- "txt_idx": "thematic_survey",
- "label": "Prospection th\u00e9matique"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.operationtype",
- "fields": {
- "comment": "Prospection visant \u00e0 d\u00e9tecter tout type de vestiges (ou presque) sur une surface donn\u00e9e. ",
- "available": true,
- "txt_idx": "inventory_survey",
- "label": "Prospection inventaire"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "villa",
- "label": "villa"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "enclosure",
- "label": "enclos"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "church",
- "label": "\u00e9glise"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "pit",
- "label": "fosse"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "cairn",
- "label": "cairn"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "ditch",
- "label": "foss\u00e9"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.remaintype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "post_hole",
- "label": "trous de poteaux"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": -10000,
- "order": 2000,
- "label": "Pal\u00e9olithique",
- "start_date": -450000,
- "txt_idx": "paleolithic"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "1100, 'Pal\u00e9olithique ancien', , )",
- "available": true,
- "parent": 1,
- "end_date": -150000,
- "order": 1100,
- "label": "Pal\u00e9olithique ancien",
- "start_date": -450000,
- "txt_idx": "ancien_paleolithic"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "1200, '', , ),",
- "available": true,
- "parent": 1,
- "end_date": -35000,
- "order": 1200,
- "label": "Pal\u00e9olithique moyen",
- "start_date": -150000,
- "txt_idx": "middle_paleolithic"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 1,
- "end_date": -12000,
- "order": 1300,
- "label": "Pal\u00e9olithique sup\u00e9rieur",
- "start_date": -35000,
- "txt_idx": "late_paleolithic"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 1,
- "end_date": -10000,
- "order": 1400,
- "label": "Pal\u00e9olithique sup\u00e9rieur final",
- "start_date": -12000,
- "txt_idx": "final_paleolithic"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": -5000,
- "order": 3000,
- "label": "M\u00e9solithique",
- "start_date": -10000,
- "txt_idx": "mesolithic"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 6,
- "end_date": -7000,
- "order": 2100,
- "label": "M\u00e9solithique ancien",
- "start_date": -10000,
- "txt_idx": "old_mesolithic"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": false,
- "parent": 6,
- "end_date": 0,
- "order": 2200,
- "label": "M\u00e9solithique moyen",
- "start_date": 0,
- "txt_idx": "middle_mesolithic"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 6,
- "end_date": -5000,
- "order": 2300,
- "label": "M\u00e9solithique r\u00e9cent",
- "start_date": -7000,
- "txt_idx": "recent_mesolithic"
- }
- },
- {
- "pk": 10,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": -2000,
- "order": 4000,
- "label": "N\u00e9olithique",
- "start_date": -5500,
- "txt_idx": "neolithic"
- }
- },
- {
- "pk": 11,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 10,
- "end_date": -4500,
- "order": 3100,
- "label": "N\u00e9olithique ancien",
- "start_date": -5500,
- "txt_idx": "old_neolithic"
- }
- },
- {
- "pk": 12,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 10,
- "end_date": -300,
- "order": 3200,
- "label": "N\u00e9olithique moyen",
- "start_date": -4500,
- "txt_idx": "middle_neolithic"
- }
- },
- {
- "pk": 13,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 10,
- "end_date": -2500,
- "order": 3300,
- "label": "N\u00e9olithique r\u00e9cent",
- "start_date": -3200,
- "txt_idx": "recent_neolithic"
- }
- },
- {
- "pk": 14,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 10,
- "end_date": -2000,
- "order": 3400,
- "label": "N\u00e9olithique final",
- "start_date": -2800,
- "txt_idx": "final_neolithic"
- }
- },
- {
- "pk": 15,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": -40,
- "order": 5000,
- "label": "Protohistoire",
- "start_date": -2000,
- "txt_idx": "protohistory"
- }
- },
- {
- "pk": 16,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 15,
- "end_date": -750,
- "order": 4100,
- "label": "\u00c2ge du Bronze",
- "start_date": -2000,
- "txt_idx": "bronze_age"
- }
- },
- {
- "pk": 17,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 15,
- "end_date": -40,
- "order": 4200,
- "label": "\u00c2ge du Fer",
- "start_date": -800,
- "txt_idx": "iron_age"
- }
- },
- {
- "pk": 18,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 16,
- "end_date": -1600,
- "order": 4110,
- "label": "\u00c2ge du Bronze ancien",
- "start_date": -2000,
- "txt_idx": "old_bronze_age"
- }
- },
- {
- "pk": 19,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 16,
- "end_date": -1200,
- "order": 4120,
- "label": "\u00c2ge du Bronze moyen",
- "start_date": -1600,
- "txt_idx": "middle_bronze_age"
- }
- },
- {
- "pk": 20,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 16,
- "end_date": -750,
- "order": 4130,
- "label": "\u00c2ge du Bronze final",
- "start_date": -1200,
- "txt_idx": "final_bronze_age"
- }
- },
- {
- "pk": 21,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 17,
- "end_date": -450,
- "order": 4210,
- "label": "Premier \u00c2ge du Fer",
- "start_date": -800,
- "txt_idx": "first_iron_age"
- }
- },
- {
- "pk": 22,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 17,
- "end_date": -40,
- "order": 4220,
- "label": "Deuxi\u00e8me \u00c2ge du Fer",
- "start_date": -500,
- "txt_idx": "second_iron_age"
- }
- },
- {
- "pk": 23,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": 476,
- "order": 6000,
- "label": "Gallo-romain",
- "start_date": -40,
- "txt_idx": "gallo-roman"
- }
- },
- {
- "pk": 24,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 23,
- "end_date": -27,
- "order": 5100,
- "label": "R\u00e9publique",
- "start_date": -40,
- "txt_idx": "republic"
- }
- },
- {
- "pk": 25,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 23,
- "end_date": 192,
- "order": 5200,
- "label": "Haut-empire",
- "start_date": -27,
- "txt_idx": "high-empire"
- }
- },
- {
- "pk": 26,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 23,
- "end_date": 476,
- "order": 5300,
- "label": "Bas-empire",
- "start_date": 192,
- "txt_idx": "low_empire"
- }
- },
- {
- "pk": 27,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": 1492,
- "order": 7000,
- "label": "Moyen-\u00e2ge",
- "start_date": 476,
- "txt_idx": "middle_age"
- }
- },
- {
- "pk": 28,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 27,
- "end_date": 987,
- "order": 6100,
- "label": "Haut moyen-\u00e2ge",
- "start_date": 476,
- "txt_idx": "476"
- }
- },
- {
- "pk": 29,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 27,
- "end_date": 1204,
- "order": 6200,
- "label": "Moyen-\u00e2ge classique",
- "start_date": 987,
- "txt_idx": "classic_middle_age"
- }
- },
- {
- "pk": 30,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 27,
- "end_date": 1492,
- "order": 6300,
- "label": "Bas moyen-\u00e2ge",
- "start_date": 1204,
- "txt_idx": "low_middle_age"
- }
- },
- {
- "pk": 31,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": 2011,
- "order": 8000,
- "label": "P\u00e9riode r\u00e9cente",
- "start_date": 1492,
- "txt_idx": "recent_times"
- }
- },
- {
- "pk": 32,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 31,
- "end_date": 1815,
- "order": 7100,
- "label": "Epoque moderne",
- "start_date": 1492,
- "txt_idx": "modern"
- }
- },
- {
- "pk": 33,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 31,
- "end_date": 2011,
- "order": 7200,
- "label": "Epoque contemporaine",
- "start_date": 1815,
- "txt_idx": "contemporan"
- }
- },
- {
- "pk": 34,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": 0,
- "order": 0,
- "label": "Epoque ind\u00e9termin\u00e9e",
- "start_date": 0,
- "txt_idx": "indetermined"
- }
- },
- {
- "pk": 35,
- "model": "ishtar_base.period",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "end_date": 0,
- "order": 10000,
- "label": "Non-renseign\u00e9",
- "start_date": 0,
- "txt_idx": "not_yet_documented"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.datingtype",
- "fields": {
- "comment": "Une \u00e9tude du mobilier est la source de datation",
- "available": true,
- "txt_idx": "from_artefact",
- "label": "D'apr\u00e8s \u00e9tude du mobilier"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.datingtype",
- "fields": {
- "comment": "D'apr\u00e8s une datation de type C14, OSL, TL, arch\u00e9omagn\u00e9tisme, etc, forunissant une date en BPcal avec une marge.",
- "available": true,
- "txt_idx": "from_absolute_dating",
- "label": "D'apr\u00e8s datation absolue"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.datingquality",
- "fields": {
- "comment": "datation a v\u00e9rifier",
- "available": true,
- "txt_idx": "estimated",
- "label": "Estim\u00e9e "
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.datingquality",
- "fields": {
- "comment": "Datation fond\u00e9e sur des faits",
- "available": true,
- "txt_idx": "sure",
- "label": "Aver\u00e9e"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "Cette unit\u00e9 n'a pas de volume",
- "available": true,
- "parent": null,
- "label": "N\u00e9gative",
- "order": 100,
- "txt_idx": "negative"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 1,
- "label": "Creusement",
- "order": 110,
- "txt_idx": "digging"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 1,
- "label": "D\u00e9rasement",
- "order": 120,
- "txt_idx": "partial_destruction"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "Couche",
- "order": 200,
- "txt_idx": "layer"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 4,
- "label": "Couche construite",
- "order": 210,
- "txt_idx": "builded_layer"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 4,
- "label": "Remblai",
- "order": 220,
- "txt_idx": "embankment"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "Alt\u00e9ration",
- "order": 300,
- "txt_idx": "alteration"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 7,
- "label": "Impact thermique",
- "order": 310,
- "txt_idx": "thermal_impact"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "Unit\u00e9 g\u00e9n\u00e9rale (d'ordinaire virtuelle) pouvant regrouper du mobilier trouver en dehors d'un contexte spatialis\u00e9 : mobilier trouver lors d'un d\u00e9capage, sous une semelle d'un fouilleur, dans les d\u00e9blais, etc.",
- "available": true,
- "parent": null,
- "label": "Hors contexte",
- "order": 1,
- "txt_idx": "not_in_context"
- }
- },
- {
- "pk": 10,
- "model": "ishtar_base.unit",
- "fields": {
- "comment": "Unit\u00e9 repr\u00e9sentant une partie d'un niveau d\u00e9coup\u00e9 en carr\u00e9s r\u00e9f\u00e9renc\u00e9s.",
- "available": true,
- "parent": null,
- "label": "Carr\u00e9",
- "order": 10,
- "txt_idx": "square"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.activitytype",
- "fields": {
- "comment": "Unit\u00e9 enregistrement qui n'est pas directement d'origine anthropique. ",
- "available": true,
- "txt_idx": "natural",
- "order": 1000,
- "label": "Naturelle"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.activitytype",
- "fields": {
- "comment": "Unit\u00e9 \u00e9labor\u00e9e par l'homme, comme une mur ou un sol am\u00e9nag\u00e9 par exemple",
- "available": true,
- "txt_idx": "construction",
- "order": 1100,
- "label": "Construction"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.activitytype",
- "fields": {
- "comment": "Unit\u00e9 r\u00e9sultant de l'arr\u00eat d'anthropisation",
- "available": true,
- "txt_idx": "desertion",
- "order": 1200,
- "label": "Abandon"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.activitytype",
- "fields": {
- "comment": "Unit\u00e9 li\u00e9e \u00e0 l'anthropisation elle-m\u00eame",
- "available": true,
- "txt_idx": "occupation",
- "order": 1300,
- "label": "Occupation"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "Niveau cultiv\u00e9 ou non, actuel.",
- "available": true,
- "txt_idx": "soil",
- "order": 1000,
- "label": "Terre v\u00e9g\u00e9tale"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "masonry",
- "order": 1100,
- "label": "Ma\u00e7onnerie"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "wall",
- "order": 1200,
- "label": "Mur"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "occupation_level",
- "order": 1300,
- "label": "Niveau d'occupation"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "desertion_level",
- "order": 1400,
- "label": "Niveau d'abandon"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "geological_level",
- "order": 1400,
- "label": "Niveau g\u00e9ologique"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "embankment",
- "order": 1500,
- "label": "Remblai"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "archaeological_soil",
- "order": 1600,
- "label": "Sol arch\u00e9ologique"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "foundation_level",
- "order": 1700,
- "label": "Radier"
- }
- },
- {
- "pk": 10,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "digging",
- "order": 1800,
- "label": "Creusement"
- }
- },
- {
- "pk": 11,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "colluvial_unit",
- "order": 1800,
- "label": "Colluvions"
- }
- },
- {
- "pk": 12,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "windthrow",
- "order": 1900,
- "label": "Chablis"
- }
- },
- {
- "pk": 13,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "filling",
- "order": 2000,
- "label": "Comblement"
- }
- },
- {
- "pk": 14,
- "model": "ishtar_base.identificationtype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "unknown",
- "order": 100,
- "label": "Ind\u00e9termin\u00e9"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "M\u00e9tal",
- "recommendation": "Hygrom\u00e9trie contr\u00f4l\u00e9e, variation de temp\u00e9rature faible",
- "txt_idx": "metal"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "Os",
- "recommendation": "Hygrom\u00e9trie contr\u00f4l\u00e9e, variations de temp\u00e9rature faible",
- "txt_idx": "bone"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 2,
- "label": "Os animal",
- "recommendation": "idem os",
- "txt_idx": "animal_bone"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 2,
- "label": "Os humain",
- "recommendation": "idem os",
- "txt_idx": "human_bone"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "Verre",
- "recommendation": "fragile, oxydation, etc.",
- "txt_idx": "glass"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "C\u00e9ramique",
- "recommendation": "a d\u00e9tailler",
- "txt_idx": "ceramic"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "Min\u00e9ral",
- "recommendation": "a d\u00e9tailler",
- "txt_idx": "mineral"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": null,
- "label": "\u00c9cofact",
- "recommendation": "on en veut pas !",
- "txt_idx": "ecofact"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.materialtype",
- "fields": {
- "comment": "",
- "available": true,
- "parent": 1,
- "label": "Bronze",
- "recommendation": "blah",
- "txt_idx": "bronze"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Le mobilier arch\u00e9ologique reste dans ce d\u00e9p\u00f4t le temps d'un traitement puis part ailleurs...",
- "available": true,
- "txt_idx": "restoration_laboratory",
- "label": "Laboratoire de restauration"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Ce d\u00e9p\u00f4t est un centre de conservation et d'\u00e9tude. Il est d'ordinaire en convention avec l'\u00e9tat.",
- "available": true,
- "txt_idx": "cce",
- "label": "CCE"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Ce d\u00e9p\u00f4t poss\u00e8de une convention avec l'\u00e9tat pour conserver du mobilier qui est sous sa garde.",
- "available": true,
- "txt_idx": "conventioned_warehouse",
- "label": "D\u00e9p\u00f4t conventionn\u00e9"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Mobilier pr\u00e9sent dans un lieu de mani\u00e8re ill\u00e9gale : pas de convention, voire de responsabilit\u00e9 exprim\u00e9e...",
- "available": true,
- "txt_idx": "illegal_warehouse",
- "label": "D\u00e9p\u00f4t non conventionn\u00e9"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Ce d\u00e9p\u00f4t est sous la responsabilit\u00e9 directe de l'Etat. Il peut en \u00eatre locataire ou propri\u00e9taire.",
- "available": true,
- "txt_idx": "state_warehouse",
- "label": "D\u00e9p\u00f4t de l'Etat"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Pour le stockage de documents papier, rapports la plus part du temps.",
- "available": true,
- "txt_idx": "library",
- "label": "Biblioth\u00e8que"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.warehousetype",
- "fields": {
- "comment": "Lieu de stockage de documents vari\u00e9s, photos, relev\u00e9s, jusqu'aux rapports.",
- "available": true,
- "txt_idx": "documentation_center",
- "label": "Centre de documentation"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Suite \u00e0 une demande d'avis, les SRA \u00e9met un courrier signalant sa volont\u00e9 de prescrire un diagnostic ou une fouille sur l'emprise du projet en objet.",
- "available": true,
- "txt_idx": "pos_advice_reply",
- "intented_to": "F",
- "label": "R\u00e9ponse positive \u00e0 une demande d'avis (art.10)"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Suite \u00e0 une demande d'avis, les SRA \u00e9met un courrier signalant sa volont\u00e9 de NE PAS prescrire un diagnostic ou une fouille sur l'emprise du projet en objet.",
- "available": true,
- "txt_idx": "neg_advice_reply",
- "intented_to": "F",
- "label": "R\u00e9ponse n\u00e9gative \u00e0 une demande d'avis (art.10)"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Suite \u00e0 une Saisine (art.8), envoi d'une r\u00e9ponse de non prescription",
- "available": true,
- "txt_idx": "reply_no_prescription",
- "intented_to": "F",
- "label": "R\u00e9ponse NON prescription \u00e0 une saisine"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Arr\u00eat\u00e9 donnant l'autorisation \u00e0 une responsable scientifique de fouiller sur un terrain donn\u00e9.",
- "available": true,
- "txt_idx": "prog_excav_autorization_order",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 d'autorisation de fouille programm\u00e9e"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Arr\u00eat\u00e9 qui donne l'autorisation \u00e0 un Am\u00e9nageur de faire ex\u00e9cuter par un Op\u00e9rateur agr\u00e9e sous la responsabilit\u00e9 d'un Responsable scientifique, une op\u00e9ration.",
- "available": true,
- "txt_idx": "excavation_autorization_order",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 d'autorisation de fouille pr\u00e9ventive"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Un arr\u00eat\u00e9 prescrivant la r\u00e9alisation d'une fouille sur une surface donn\u00e9e",
- "available": true,
- "txt_idx": "excavation_order",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 de prescription de fouille"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "Un arr\u00eat\u00e9 prescrivant la r\u00e9alisation d'un diagnostic sur une surface donn\u00e9e, SANS pr\u00e9cision du responsable scientifique, SANS pr\u00e9cision de l'op\u00e9rateur",
- "available": true,
- "txt_idx": "diagnostic_order",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 de diagnostic, sans RS, sans op\u00e9rateur"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "responsible_act",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 de d\u00e9signation de RS"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "D\u00e9signation de l'op\u00e9rateur pour un diagnostic : utile dans le cas o\u00f9 un service territorial ET l'INRAP sont en m\u00eame temps comp\u00e9tents pour un territoire donn\u00e9.",
- "available": true,
- "txt_idx": "operator_designation_act",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 de d\u00e9signation d'op\u00e9rateur"
- }
- },
- {
- "pk": 10,
- "model": "ishtar_base.acttype",
- "fields": {
- "comment": "",
- "available": true,
- "txt_idx": "thematic_survey_act",
- "intented_to": "O",
- "label": "Arr\u00eat\u00e9 d'autorisation de prospection th\u00e9matique"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "Type de caisse tr\u00e8s commun dans le nord de la France. Pas cher, pas trop gros donc pas trop lourd.\r\n\r\nR\u00e9f\u00e9rences pr\u00e9cises \u00e0 trouver !!!!!",
- "available": true,
- "reference": "Inconnue",
- "label": "Caisse \u00e0 pomme rouge",
- "volume": 18,
- "width": 20,
- "length": null,
- "height": 25,
- "txt_idx": "red_apple_bin"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "L'horrible caisse \u00e0 poisson ou du genre, a changer au plus vite",
- "available": true,
- "reference": "variable",
- "label": "Caisse en polystyr\u00e8ne",
- "volume": 0,
- "width": 0,
- "length": null,
- "height": 0,
- "txt_idx": "polystyren_bin"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "Caisse Alibert grise standard, a pr\u00e9ciser et d\u00e9cliner en fonction des mod\u00e8les.",
- "available": true,
- "reference": "a pr\u00e9ciser",
- "label": "Caisse Alibert standard",
- "volume": 0,
- "width": 0,
- "length": null,
- "height": 0,
- "txt_idx": "stand_alibert_bin"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "",
- "available": true,
- "reference": "Curver UNIBOX 29 L",
- "label": "Curver UNIBOX 29 L",
- "volume": 37,
- "width": 355,
- "length": null,
- "height": 245,
- "txt_idx": "curver_unibox_29"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "",
- "available": true,
- "reference": "Curver UNIBOX 48 L",
- "label": "Curver UNIBOX 48 L",
- "volume": 63,
- "width": 432,
- "length": null,
- "height": 280,
- "txt_idx": "curver_unibox_48"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.containertype",
- "fields": {
- "comment": "",
- "available": true,
- "reference": "Curver UNIBOX 20 lL",
- "label": "Curver UNIBOX 20 L",
- "volume": 25,
- "width": 350,
- "length": null,
- "height": 165,
- "txt_idx": "curver_unibox_20"
- }
- },
- {
- "pk": 1,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Le fait de mettre du mobilier dans un contenant. Que cela soit le conditionnement initial ou un re-conditionnement. ",
- "available": true,
- "txt_idx": "packaging",
- "virtual": false,
- "label": "Conditionnement"
- }
- },
- {
- "pk": 2,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Un lot mobilier ou un objet isol\u00e9 subit une radiographie (rayon X) qui produit un ou des films radio.",
- "available": true,
- "txt_idx": "regular_x_ray",
- "virtual": false,
- "label": "Radiographie argentique"
- }
- },
- {
- "pk": 3,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Un lot mobilier ou un objet isol\u00e9 subit une radiographie (rayon X) qui produit un ou des fichiers num\u00e9riques.",
- "available": true,
- "txt_idx": "digital_x_ray",
- "virtual": false,
- "label": "Radiographie num\u00e9rique"
- }
- },
- {
- "pk": 4,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "D\u00e9placement de mobilier, entre deux d\u00e9p\u00f4ts : le mobilier ne peut pas \u00eatre stocker ailleurs que dans un lieu consid\u00e9r\u00e9 comme un d\u00e9p\u00f4t.",
- "available": true,
- "txt_idx": "moving",
- "virtual": false,
- "label": "D\u00e9placement"
- }
- },
- {
- "pk": 5,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Regroupement d'un ensemble de mobilier. Exemple : ensemble des outils provenant d'une fouille, Mobilier datant d'un site, tessonier virtuel, etc.",
- "available": true,
- "txt_idx": "virtual_group",
- "virtual": true,
- "label": "Groupement virtuel"
- }
- },
- {
- "pk": 7,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Division d'un lot de mobilier en plusieurs lots",
- "available": true,
- "txt_idx": "split",
- "virtual": false,
- "label": "Division"
- }
- },
- {
- "pk": 6,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "R\u00e9union de plusieurs objets ou lots mobiliers en un seul. Ce type de traitement peut impliquer ou non un reconditionnement.\r\n\r\nExemple : Remontage d'une c\u00e9ramique \u00e0 partir de tessons d\u00e9j\u00e0 pr\u00e9sents dans un contenant (pas de reconditionnement), regroupement d'une partie de la faune (os) d'une op\u00e9ration et cr\u00e9ation d'une nouvelle caisse dans ce but (reconditionnement \u00e0 faire)",
- "available": true,
- "txt_idx": "physical_grouping",
- "virtual": false,
- "label": "Groupement"
- }
- },
- {
- "pk": 8,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Prise de vue \u00e0 l'aide d'un appareil photo num\u00e9rique",
- "available": true,
- "txt_idx": "digital_photography",
- "virtual": false,
- "label": "Photographie num\u00e9rique"
- }
- },
- {
- "pk": 9,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Photographie produisant un film (positif ou n\u00e9gatif)",
- "available": true,
- "txt_idx": "regular_photography",
- "virtual": false,
- "label": "Photographie argentique"
- }
- },
- {
- "pk": 10,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "Processus qui permet \u00e9liminer le sel qui impr\u00e8gne un objet arch\u00e9ologique ou lot d'objets.",
- "available": true,
- "txt_idx": "desalinisation",
- "virtual": false,
- "label": "D\u00e9salinisation"
- }
- },
- {
- "pk": 11,
- "model": "ishtar_base.treatmenttype",
- "fields": {
- "comment": "R\u00e9duction des oxydes d\u00e9velopp\u00e9s sur/dans un objet arch\u00e9ologique par l'usage de courant \u00e9lectrique.",
- "available": true,
- "txt_idx": "electrolysis",
- "virtual": false,
- "label": "Electrolyse"
- }
- }
-] \ No newline at end of file
diff --git a/ishtar/ishtar_base/forms.py b/ishtar/ishtar_base/forms.py
deleted file mode 100644
index 3d6f3f503..000000000
--- a/ishtar/ishtar_base/forms.py
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/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.
-
-"""
-Forms definition
-"""
-import datetime
-import re
-from itertools import groupby
-
-from django.core.urlresolvers import reverse
-from django.core import validators
-from django.core.exceptions import ObjectDoesNotExist
-from django.utils import formats
-from django.utils.functional import lazy
-from django.utils.translation import ugettext_lazy as _
-from django.shortcuts import render_to_response
-from django.template import Context, RequestContext, loader
-from django.db.models import Max
-from django import forms
-from django.core.mail import send_mail
-from django.forms.formsets import formset_factory, BaseFormSet, \
- DELETION_FIELD_NAME
-from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
-
-# from formwizard.forms import NamedUrlSessionFormWizard
-
-class NamedUrlSessionFormWizard(forms.Form):
- def __init__(self, form_list, condition_list={}, url_name=''):
- self.form_list = dict(form_list)
- self.condition_list = condition_list
- self.url_name = url_name
- super(NamedUrlSessionFormWizard, self).__init__(self)
-
-
- def rindex(self, idx):
- return self.url_name.rindex(idx)
-
-import models
-import widgets
-from ishtar import settings
-
-reverse_lazy = lazy(reverse, unicode)
-
-regexp_name = re.compile(r'^[\w\- ]+$', re.UNICODE)
-name_validator = validators.RegexValidator(regexp_name,
-_(u"Enter a valid name consisting of letters, spaces and hyphens."), 'invalid')
-
-class FloatField(forms.FloatField):
- """
- Allow the use of comma for separating float fields
- """
- def clean(self, value):
- if value:
- value = value.replace(',', '.').replace('%', '')
- return super(FloatField, self).clean(value)
-
-class FinalForm(forms.Form):
- final = True
- form_label = _(u"Confirm")
-
-class FormSet(BaseFormSet):
- def check_duplicate(self, key_names, error_msg=""):
- """Check for duplicate items in the formset"""
- if any(self.errors):
- return
- if not error_msg:
- error_msg = _("There are identical items.")
- items = []
- for i in range(0, self.total_form_count()):
- form = self.forms[i]
- if not form.is_valid():
- continue
- item = [key_name in form.cleaned_data and form.cleaned_data[key_name]
- for key_name in key_names]
- if not [v for v in item if v]:
- continue
- if item in items:
- raise forms.ValidationError, error_msg
- items.append(item)
-
- def add_fields(self, form, index):
- super(FormSet, self).add_fields(form, index)
- form.fields[DELETION_FIELD_NAME].label = ''
- form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget()
-
-'''
-class SearchWizard(NamedUrlSessionFormWizard):
- model = None
-
- def get_wizard_name(self):
- """
- As the class name can interfere when reused, use the url_name
- """
- return self.url_name
-
- def get_template(self, request, storage):
- templates = ['search.html']
- return templates
-
-def get_now():
- format = formats.get_format('DATE_INPUT_FORMATS')[0]
- value = datetime.datetime.now().strftime(format)
- return value
-
-class DeletionWizard(Wizard):
- def get_formated_datas(self, forms):
- datas = super(DeletionWizard, self).get_formated_datas(forms)
- self.current_obj = None
- for form in forms:
- if not hasattr(form, "cleaned_data"):
- continue
- for key in form.cleaned_data:
- if key == 'pk':
- model = form.associated_models['pk']
- self.current_obj = model.objects.get(pk=form.cleaned_data['pk'])
- if not self.current_obj:
- return datas
- res = {}
- for field in self.model._meta.fields + self.model._meta.many_to_many:
- if field.name not in self.fields:
- continue
- value = getattr(self.current_obj, field.name)
- if not value:
- continue
- if hasattr(value, 'all'):
- value = ", ".join([unicode(item) for item in value.all()])
- if not value:
- continue
- else:
- value = unicode(value)
- res[field.name] = (field.verbose_name, value, '')
- if not datas and self.fields:
- datas = [['', []]]
- for field in self.fields:
- if field in res:
- datas[0][1].append(res[field])
- return datas
-
- def done(self, request, storage, form_list, **kwargs):
- obj = self.get_current_object(request, storage)
- obj.delete()
- return render_to_response('wizard_delete_done.html', {},
- context_instance=RequestContext(request))
-
-class ClosingDateFormSelection(forms.Form):
- form_label = _("Closing date")
- end_date = forms.DateField(label=_(u"Closing date"),
- widget=widgets.JQueryDate)
-
-class ClosingWizard(Wizard):
- # "close" an item
- # to be define in the overloaded class
- model = None
- fields = []
-
- def get_formated_datas(self, forms):
- datas = super(ClosingWizard, self).get_formated_datas(forms)
- self.current_obj = None
- for form in forms:
- if not hasattr(form, "cleaned_data"):
- continue
- for key in form.cleaned_data:
- if key == 'pk':
- model = form.associated_models['pk']
- self.current_obj = model.objects.get(
- pk=form.cleaned_data['pk'])
- if not self.current_obj:
- return datas
- res = {}
- for field in self.model._meta.fields + self.model._meta.many_to_many:
- if field.name not in self.fields:
- continue
- value = getattr(self.current_obj, field.name)
- if not value:
- continue
- if hasattr(value, 'all'):
- value = ", ".join([unicode(item) for item in value.all()])
- if not value:
- continue
- else:
- value = unicode(value)
- res[field.name] = (field.verbose_name, value, '')
- if not datas and self.fields:
- datas = [['', []]]
- for field in self.fields:
- if field in res:
- datas[0][1].append(res[field])
- return datas
-
- def done(self, request, storage, form_list, **kwargs):
- obj = self.get_current_object(request, storage)
- for form in form_list:
- if form.is_valid():
- if 'end_date' in form.cleaned_data and hasattr(obj, 'end_date'):
- obj.end_date = form.cleaned_data['end_date']
- obj.save()
- return render_to_response('wizard_closing_done.html', {},
- context_instance=RequestContext(request))
-
-def get_form_selection(class_name, label, key, model, base_form, get_url,
- not_selected_error=_(u"You should select an item."), new=False,
- new_message=_(u"Add a new item")):
- """
- Generate a class selection form
- class_name -- name of the class
- label -- label of the form
- key -- model,
- base_form -- base form to select
- get_url -- url to get the item
- not_selected_error -- message displayed when no item is selected
- new -- can add new items
- new_message -- message of link to add new items
- """
- attrs = {'_main_key':key,
- '_not_selected_error':not_selected_error,
- 'form_label':label,
- 'associated_models':{key:model},
- 'currents':{key:model},}
- attrs[key] = forms.IntegerField(label="", required=False,
- validators=[models.valid_id(model)],
- widget=widgets.JQueryJqGrid(reverse_lazy(get_url), base_form(), model,
- new=new, new_message=new_message))
- def clean(self):
- cleaned_data = self.cleaned_data
- if self._main_key not in cleaned_data \
- or not cleaned_data[self._main_key]:
- raise forms.ValidationError(self._not_selected_error)
- return cleaned_data
- attrs['clean'] = clean
- return type(class_name, (forms.Form,), attrs)
-'''
diff --git a/ishtar/ishtar_base/forms_common.py b/ishtar/ishtar_base/forms_common.py
deleted file mode 100644
index 7ef1d4070..000000000
--- a/ishtar/ishtar_base/forms_common.py
+++ /dev/null
@@ -1,519 +0,0 @@
-#!/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.
-
-"""
-Administrative forms definitions: manage accounts and persons
-"""
-import datetime
-
-from django import forms
-from django.template import Context, RequestContext, loader
-from django.shortcuts import render_to_response
-from django.core import validators
-from django.core.mail import send_mail
-from django.core.exceptions import ObjectDoesNotExist
-from django.utils.safestring import mark_safe
-from django.forms.formsets import formset_factory, DELETION_FIELD_NAME
-from django.utils.translation import ugettext_lazy as _
-from django.contrib.auth.models import User
-from django.contrib.sites.models import Site
-
-from ishtar import settings
-
-import models
-import widgets
-from forms import FinalForm, FormSet, reverse_lazy, name_validator
-
-def get_town_field(label=_(u"Town"), required=True):
- help_text = _(u"<p>Type name, department code and/or postal code of the "
- u"town you would like to select. The search is insensitive to case.</p>\n"
- u"<p>Only the first twenty results are displayed but specifying the "
- u"department code is generally sufficient to get the appropriate result.</p>"
- u"\n<p class='example'>For instance type \"saint denis 93\" for getting "
- u"the french town Saint-Denis in the Seine-Saint-Denis department.</p>")
- # !FIXME hard_link, reverse_lazy doen't seem to work with formsets
- return forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-town', associated_model=models.Town),
- validators=[models.valid_id(models.Town)], label=label,
- help_text=mark_safe(help_text), required=required)
-
-def get_person_field(label=_(u"Person"), required=True, person_type=None):
- # !FIXME hard_link, reverse_lazy doen't seem to work with formsets
- widget = None
- url = "/" + settings.URL_PATH + 'autocomplete-person'
- if person_type:
- if isinstance(person_type, unicode) or isinstance(person_type, str):
- person_type = models.PersonType.objects.get(txt_idx=person_type)
- url += u"/" + unicode(person_type.pk)
- widget = widgets.JQueryAutoComplete(url, associated_model=models.Person)
- return forms.IntegerField(widget=widget, label=label, required=required,
- validators=[models.valid_id(models.Person)])
-
-def get_warehouse_field(label=_(u"Warehouse"), required=True):
- # !FIXME hard_link, reverse_lazy doen't seem to work with formsets
- url = "/" + settings.URL_PATH + 'autocomplete-warehouse'
- widget = widgets.JQueryAutoComplete(url, associated_model=models.Warehouse)
- return forms.IntegerField(widget=widget, label=label, required=required,
- validators=[models.valid_id(models.Warehouse)])
-
-class WarehouseForm(forms.Form):
- name = forms.CharField(label=_(u"Name"), max_length=40,
- validators=[name_validator])
- warehouse_type = forms.ChoiceField(label=_(u"Warehouse type"),
- choices=[])
- person_in_charge = forms.IntegerField(label=_(u"Person in charge"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-person'), associated_model=models.Person),
- validators=[models.valid_id(models.Person)],
- required=False)
- comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea,
- required=False)
- address = forms.CharField(label=_(u"Address"), widget=forms.Textarea,
- required=False)
- address_complement = forms.CharField(label=_(u"Address complement"),
- widget=forms.Textarea, required=False)
- postal_code = forms.CharField(label=_(u"Postal code"), max_length=10,
- required=False)
- town = forms.CharField(label=_(u"Town"), max_length=30, required=False)
- country = forms.CharField(label=_(u"Country"), max_length=30,
- required=False)
- phone = forms.CharField(label=_(u"Phone"), max_length=18, required=False)
- mobile_phone = forms.CharField(label=_(u"Town"), max_length=18,
- required=False)
-
- def __init__(self, *args, **kwargs):
- super(WarehouseForm, self).__init__(*args, **kwargs)
- self.fields['warehouse_type'].choices = \
- models.WarehouseType.get_types()
- self.fields['warehouse_type'].help_text = \
- models.WarehouseType.get_help()
-
- def save(self, user):
- dct = self.cleaned_data
- dct['history_modifier'] = user
- dct['warehouse_type'] = models.WarehouseType.objects.get(
- pk=dct['warehouse_type'])
- if 'person_in_charge' in dct and dct['person_in_charge']:
- dct['person_in_charge'] = models.Person.objects.get(
- pk=dct['person_in_charge'])
- new_item = models.Warehouse(**dct)
- new_item.save()
- return new_item
-
-class OrganizationForm(forms.Form):
- name = forms.CharField(label=_(u"Name"), max_length=40,
- validators=[name_validator])
- organization_type = forms.ChoiceField(label=_(u"Organization type"),
- choices=[])
- address = forms.CharField(label=_(u"Address"), widget=forms.Textarea,
- required=False)
- address_complement = forms.CharField(label=_(u"Address complement"),
- widget=forms.Textarea, required=False)
- postal_code = forms.CharField(label=_(u"Postal code"), max_length=10,
- required=False)
- town = forms.CharField(label=_(u"Town"), max_length=30, required=False)
- country = forms.CharField(label=_(u"Country"), max_length=30,
- required=False)
- phone = forms.CharField(label=_(u"Phone"), max_length=18, required=False)
- mobile_phone = forms.CharField(label=_(u"Town"), max_length=18,
- required=False)
-
- def __init__(self, *args, **kwargs):
- super(OrganizationForm, self).__init__(*args, **kwargs)
- self.fields['organization_type'].choices = \
- models.OrganizationType.get_types()
- self.fields['organization_type'].help_text = \
- models.OrganizationType.get_help()
-
- def save(self, user):
- dct = self.cleaned_data
- dct['history_modifier'] = user
- dct['organization_type'] = models.OrganizationType.objects.get(
- pk=dct['organization_type'])
- new_item = models.Organization(**dct)
- new_item.save()
- return new_item
-
-class PersonFormSelection(forms.Form):
- form_label = _(u"Person search")
- associated_models = {'pk':models.Person}
- currents = {'pk':models.Person}
- pk = forms.IntegerField(label=_("Person"),
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'),
- associated_model=models.Person),
- validators=[models.valid_id(models.Person)])
-
-class PersonForm(forms.Form):
- form_label = _("Identity")
- associated_models = {'attached_to':models.Organization,
- 'person_type':models.PersonType}
- title = forms.ChoiceField(label=_("Title"), choices=models.Person.TYPE)
- surname = forms.CharField(label=_(u"Surname"), max_length=20,
- validators=[name_validator])
- name = forms.CharField(label=_(u"Name"), max_length=30,
- validators=[name_validator])
- email = forms.CharField(label=_(u"Email"), max_length=40, required=False,
- validators=[validators.validate_email])
- person_type = forms.ChoiceField(label=_("Person type"),
- choices=[])
- attached_to = forms.IntegerField(label=_("Current organization"),
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-organization'),
- associated_model=models.Organization, new=True),
- validators=[models.valid_id(models.Organization)], required=False)
-
- def __init__(self, *args, **kwargs):
- super(PersonForm, self).__init__(*args, **kwargs)
- self.fields['person_type'].choices = models.PersonType.get_types()
- self.fields['person_type'].help_text = models.PersonType.get_help()
-
- def save(self, user):
- dct = self.cleaned_data
- dct['history_modifier'] = user
- dct['person_type'] = models.PersonType.objects.get(
- pk=dct['person_type'])
- if 'attached_to' in dct and dct['attached_to']:
- dct['attached_to'] = models.Organization.objects.get(
- pk=dct['attached_to'])
- new_item = models.Person(**dct)
- new_item.save()
- return new_item
-
-'''
-person_search_wizard = SearchWizard([
- ('general-person_search', PersonFormSelection)],
- url_name='person_search',)
-
-
-
-person_modification_wizard = PersonWizard([
- ('selec-person_modification', PersonFormSelection),
- ('identity-person_modification', PersonForm),
- ('final-person_modification', FinalForm)],
- url_name='person_modification',)
-
-class AccountWizard(Wizard):
- model = models.Person
- def get_formated_datas(self, forms):
- datas = super(AccountWizard, self).get_formated_datas(forms)
- for form in forms:
- if not hasattr(form, "cleaned_data"):
- continue
- for key in form.cleaned_data:
- if key == 'hidden_password' and form.cleaned_data[key]:
- datas[-1][1].append((_("New password"), "*"*8))
- return datas
-
- def done(self, request, storage, form_list, **kwargs):
- """
- Save the account
- """
- dct = {}
- for form in form_list:
- if not form.is_valid():
- return self.render(request, storage, form)
- associated_models = hasattr(form, 'associated_models') and \
- form.associated_models or {}
- if type(form.cleaned_data) == dict:
- for key in form.cleaned_data:
- if key == 'pk':
- continue
- value = form.cleaned_data[key]
- if key in associated_models and value:
- value = associated_models[key].objects.get(pk=value)
- dct[key] = value
- person = self.get_current_object(request, storage)
- if not person:
- return self.render(request, storage, form)
- for key in dct.keys():
- if key.startswith('hidden_password'):
- dct['password'] = dct.pop(key)
- try:
- account = models.IshtarUser.objects.get(person=person)
- account.username = dct['username']
- account.email = dct['email']
- except ObjectDoesNotExist:
- now = datetime.datetime.now()
- account = models.IshtarUser(person=person, username=dct['username'],
- email=dct['email'], first_name=person.surname,
- last_name=person.name, is_staff=False, is_active=True,
- is_superuser=False, last_login=now, date_joined=now)
- if dct['password']:
- account.set_password(dct['password'])
- account.save()
-
- if 'send_password' in dct and dct['send_password'] and \
- settings.ADMINS:
- site = Site.objects.get_current()
-
- app_name = site and ("Ishtar - " + site.name) \
- or "Ishtar"
- context = Context({'login':dct['username'],
- 'password':dct['password'],
- 'app_name':app_name,
- 'site': site and site.domain or ""
- })
- t = loader.get_template('account_activation_email.txt')
- msg = t.render(context)
- subject = _(u"[%(app_name)s] Account creation/modification") % {
- "app_name":app_name}
- send_mail(subject, msg, settings.ADMINS[0][1],
- [dct['email']], fail_silently=True)
- res = render_to_response('wizard_done.html', {},
- context_instance=RequestContext(request))
- return res
-
- def get_form(self, request, storage, step=None, data=None, files=None):
- """
- Display the "Send email" field if necessary
- """
- form = super(AccountWizard, self).get_form(request, storage, step, data,
- files)
- if not hasattr(form, 'is_hidden'):
- return form
- if self.session_get_value(request, storage,
- 'account-account_management', 'hidden_password'):
- form.is_hidden = False
- return form
-
-'''
-class AccountForm(forms.Form):
- form_label = _("Account")
- associated_models = {'pk':models.Person}
- currents = {'pk':models.Person}
- pk = forms.IntegerField(label=u"", widget=forms.HiddenInput, required=False)
- username = forms.CharField(label=_(u"Account"), max_length=30)
- email = forms.CharField(label=_(u"Email"), max_length=75,
- validators=[validators.validate_email])
- hidden_password = forms.CharField(label=_(u"New password"), max_length=128,
- widget=forms.PasswordInput, required=False,
- validators=[validators.MinLengthValidator(4)])
- hidden_password_confirm = forms.CharField(
- label=_(u"New password (confirmation)"), max_length=128,
- widget=forms.PasswordInput, required=False)
-
- def __init__(self, *args, **kwargs):
- if 'initial' in kwargs and 'pk' in kwargs['initial']:
- try:
- person = models.Person.objects.get(pk=kwargs['initial']['pk'])
- account = models.IshtarUser.objects.get(person=person)
- kwargs['initial'].update({'username':account.username,
- 'email':account.email})
- except ObjectDoesNotExist:
- pass
- return super(AccountForm, self).__init__(*args, **kwargs)
-
- def clean(self):
- cleaned_data = self.cleaned_data
- password = cleaned_data.get("hidden_password")
- if password and password != cleaned_data.get("hidden_password_confirm"):
- raise forms.ValidationError(_(u"Your password and confirmation "
- u"password do not match."))
- if not cleaned_data.get("pk"):
- models.is_unique(User, 'username')(cleaned_data.get("username"))
- if not password:
- raise forms.ValidationError(_(u"You must provide a correct \
-password."))
- # check username unicity
- usernames = models.IshtarUser.objects.filter(username=
- cleaned_data.get('username'))
- if cleaned_data.get('pk'):
- usernames.exclude(pk=cleaned_data.get('pk'))
- if usernames.count():
- raise forms.ValidationError(_(u"This username already exists."))
- return cleaned_data
-
-class FinalAccountForm(forms.Form):
- final = True
- form_label = _("Confirm")
- send_password = forms.BooleanField(label=_(u"Send the new password by "
- u"email?"), required=False)
-
- def __init__(self, *args, **kwargs):
- self.is_hidden = True
- return super(FinalAccountForm, self).__init__(*args, **kwargs)
-'''
-account_management_wizard = AccountWizard([
- ('selec-account_management', PersonFormSelection),
- ('account-account_management', AccountForm),
- ('final-account_management', FinalAccountForm)],
- url_name='account_management',)
-'''
-class TownForm(forms.Form):
- form_label = _("Towns")
- base_model = 'town'
- associated_models = {'town':models.Town}
- town = get_town_field(required=False)
-
-class TownFormSet(FormSet):
- def clean(self):
- """Checks that no towns are duplicated."""
- return self.check_duplicate(('town',),
- _("There are identical towns."))
-
-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,
- 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', 'section'):
- if not key in self.cleaned_data or not self.cleaned_data[key]:
- raise forms.ValidationError(_(u"Town section and parcel number "
- u"fields are required."))
- return self.cleaned_data
-
-
-class ParcelFormSet(FormSet):
- def clean(self):
- """Checks that no parcels are duplicated."""
- return self.check_duplicate(('town', 'parcel_number', 'year'),
- _(u"There are identical parcels."))
-
-ParcelFormSet = formset_factory(ParcelForm, can_delete=True,
- formset=ParcelFormSet)
-ParcelFormSet.form_label = _(u"Parcels")
-
-######################
-# Sources management #
-######################
-'''
-class SourceWizard(Wizard):
- model = None
- def get_extra_model(self, dct, request, storage, form_list):
- dct = super(SourceWizard, self).get_extra_model(dct, request, storage,
- form_list)
- if 'history_modifier' in dct:
- dct.pop('history_modifier')
- return dct
-'''
-class SourceForm(forms.Form):
- form_label = _(u"Documentation informations")
- associated_models = {'source_type':models.SourceType}
- title = forms.CharField(label=_(u"Title"),
- validators=[validators.MaxLengthValidator(200)])
- source_type = forms.ChoiceField(label=_(u"Source type"), choices=[])
- associated_url = forms.URLField(required=False,
- label=_(u"Numerical ressource (web address)"))
- receipt_date = forms.DateField(label=_(u"Receipt date"), required=False,
- widget=widgets.JQueryDate)
- creation_date = forms.DateField(label=_(u"Creation date"), required=False,
- widget=widgets.JQueryDate)
-
- def __init__(self, *args, **kwargs):
- super(SourceForm, self).__init__(*args, **kwargs)
- self.fields['source_type'].choices = models.SourceType.get_types()
-
-class SourceSelect(forms.Form):
- authors = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-author', associated_model=models.Author),
- validators=[models.valid_id(models.Author)], label=_(u"Author"),
- required=False)
-
- source_type = forms.ChoiceField(label=_("Source type"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(SourceSelect, self).__init__(*args, **kwargs)
- self.fields['source_type'].choices = models.SourceType.get_types()
- self.fields['source_type'].help_text = models.SourceType.get_help()
-
-class SourceDeletionForm(FinalForm):
- confirm_msg = " "
- confirm_end_msg = _(u"Would you like to delete this documentation?")
-
-######################
-# Authors management #
-######################
-
-class AuthorForm(forms.Form):
- form_label = _(u"Author")
- associated_models = {'person':models.Person,
- 'author_type':models.AuthorType}
- person = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-person', associated_model=models.Person, new=True),
- validators=[models.valid_id(models.Person)], label=_(u"Person"))
- author_type = forms.ChoiceField(label=_(u"Author type"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(AuthorForm, self).__init__(*args, **kwargs)
- self.fields['author_type'].choices = models.AuthorType.get_types()
-
- def save(self, user):
- dct = self.cleaned_data
- dct['author_type'] = models.AuthorType.objects.get(
- pk=dct['author_type'])
- dct['person'] = models.Person.objects.get(pk=dct['person'])
- new_item = models.Author(**dct)
- new_item.save()
- return new_item
-
-
-class AuthorFormSelection(forms.Form):
- form_label = _(u"Author selection")
- base_model = 'author'
- associated_models = {'author':models.Author}
- author = forms.IntegerField(
- widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
- 'autocomplete-author', associated_model=models.Author, new=True),
- validators=[models.valid_id(models.Author)], label=_(u"Author"))
-
-class AuthorFormSet(FormSet):
- def clean(self):
- """Checks that no author are duplicated."""
- return self.check_duplicate(('author',),
- _("There are identical authors."))
-
-AuthorFormset = formset_factory(AuthorFormSelection, can_delete=True,
- formset=AuthorFormSet)
-AuthorFormset.form_label = _("Authors")
-
diff --git a/ishtar/ishtar_base/forms_context_records.py b/ishtar/ishtar_base/forms_context_records.py
deleted file mode 100644
index 816782bd8..000000000
--- a/ishtar/ishtar_base/forms_context_records.py
+++ /dev/null
@@ -1,362 +0,0 @@
-#!/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 itertools import groupby
-
-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, get_form_selection
-from forms_common import get_town_field, SourceForm, SourceWizard, \
- SourceSelect, AuthorFormset
-from forms_operations import OperationSelect
-
-class RecordWizard(Wizard):
- model = models.ContextRecord
- edit = False
-
- def get_current_operation(self, request, storage):
- step = storage.get_current_step()
- if not step:
- return
- if step.endswith('_creation'): # an operation has been selected
- main_form_key = 'selec-' + self.url_name
- try:
- idx = int(self.session_get_value(request, storage,
- main_form_key, 'operation_id'))
- current_ope = models.Operation.objects.get(pk=idx)
- return current_ope
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- current_cr = self.get_current_object(request, storage)
- if current_cr:
- return current_cr.parcel.operation
-
- def get_template_context(self, request, storage, form=None):
- """
- Get the operation "reminder" on top of wizard forms
- """
- context = super(RecordWizard, self).get_template_context(request,
- storage, form)
- operation = self.get_current_operation(request, storage)
- if not operation:
- return context
- 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))))
- context['reminder'] = _("Current operation: ") + " - ".join(items)
- return context
-
- 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]
-
- general_form_key = 'general-' + self.url_name
- if step.startswith('general-'):
- if step.endswith('_creation'): # an operation has been selected
- main_form_key = 'selec-' + self.url_name
- try:
- idx = int(self.session_get_value(request, storage,
- main_form_key, 'operation_id'))
- current_obj = models.Operation.objects.get(pk=idx)
- data['operation'] = current_obj
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- else:
- current_object = self.get_current_object(request, storage)
- data['context_record'] = current_object
- form = super(RecordWizard, self).get_form(request, storage, step, data,
- files)
- return form
-
-class RecordModifWizard(RecordWizard):
- modification = True
- model = models.ContextRecord
-
-class RecordSelect(forms.Form):
- parcel__town = get_town_field()
- operation__year = forms.IntegerField(label=_(u"Year"))
- datings__period = forms.ChoiceField(label=_(u"Period"), choices=[])
- unit = forms.ChoiceField(label=_(u"Unit type"), choices=[])
- def __init__(self, *args, **kwargs):
- super(RecordSelect, self).__init__(*args, **kwargs)
- self.fields['datings__period'].choices = \
- models.Period.get_types()
- self.fields['datings__period'].help_text = \
- models.Period.get_help()
- self.fields['unit'].choices = models.Unit.get_types()
- self.fields['unit'].help_text = models.Unit.get_help()
-
-class RecordFormSelection(forms.Form):
- form_label = _("Context record search")
- 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,
- source_full=reverse_lazy('get-contextrecord-full')),
- 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 at least select one "
- u"context record."))
- return cleaned_data
-
-
-class RecordFormGeneral(forms.Form):
- form_label = _("General")
- associated_models = {'parcel':models.Parcel, 'unit':models.Unit}
- pk = forms.IntegerField(required=False, widget=forms.HiddenInput)
- operation_id = forms.IntegerField(widget=forms.HiddenInput)
- 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 (cm)"), required=False)
- width = forms.IntegerField(label=_(u"Width (cm)"), required=False)
- thickness = forms.IntegerField(label=_(u"Thickness (cm)"), required=False)
- depth = forms.IntegerField(label=_(u"Depth (cm)"), 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 'context_record' in kwargs['data']):
- if 'operation' in kwargs['data']:
- operation = kwargs['data']['operation']
- if 'context_record' in kwargs['data'] and \
- kwargs['data']['context_record']:
- operation = kwargs['data']['context_record'].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:
- self.fields['operation_id'].initial = operation.pk
- 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])
- )
-
- def clean(self):
- # manage unique context record ID
- cleaned_data = self.cleaned_data
- operation_id = cleaned_data.get("operation_id")
- label = cleaned_data.get("label")
- cr = models.ContextRecord.objects.filter(label=label,
- parcel__operation__pk=operation_id)
- if 'pk' in cleaned_data and cleaned_data['pk']:
- cr = cr.exclude(pk=cleaned_data['pk'])
- if cr.count():
- raise forms.ValidationError(_(u"This ID already exist for "
- u"this operation."))
- return cleaned_data
-
-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=[])
-
- def __init__(self, *args, **kwargs):
- super(DatingForm, self).__init__(*args, **kwargs)
- self.fields['dating_type'].choices = models.DatingType.get_types()
- self.fields['dating_type'].help_text = models.DatingType.get_help()
-
-
-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=_(u"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['activity'].help_text = models.ActivityType.get_help()
- self.fields['identification'].choices = \
- models.IdentificationType.get_types()
- self.fields['identification'].help_text = \
- models.IdentificationType.get_help()
-
-record_search_wizard = SearchWizard([
- ('general-record_search', RecordFormSelection)],
- url_name='record_search',)
-
-OperationRecordFormSelection = get_form_selection(
- 'OperationRecordFormSelection', _(u"Operation search"), 'operation_id',
- models.Operation, OperationSelect, 'get-operation',
- _(u"You should select an operation."))
-
-
-record_creation_wizard = RecordWizard([
- ('selec-record_creation', OperationRecordFormSelection),
- ('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',)
-
-#########################################
-# Source management for context records #
-#########################################
-
-class RecordSourceWizard(SourceWizard):
- model = models.ContextRecordSource
-
-SourceRecordFormSelection = get_form_selection(
- 'SourceRecordFormSelection', _(u"Context record search"),
- 'context_record', models.ContextRecord, RecordSelect, 'get-contextrecord',
- _(u"You should select a context record."))
-
-record_source_creation_wizard = RecordSourceWizard([
- ('selec-record_source_creation', SourceRecordFormSelection),
- ('source-record_source_creation', SourceForm),
- ('authors-record_source_creation', AuthorFormset),
- ('final-record_source_creation', FinalForm)],
- url_name='record_source_creation',)
-
-class RecordSourceSelect(SourceSelect):
- context_record__parcel__town = get_town_field(
- label=_(u"Town of the operation"))
- context_record__operation__year = forms.IntegerField(
- label=_(u"Year of the operation"))
- context_record__datings__period = forms.ChoiceField(
- label=_(u"Period of the context record"), choices=[])
- context_record__unit = forms.ChoiceField(
- label=_(u"Unit type of the context record"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(RecordSourceSelect, self).__init__(*args, **kwargs)
- self.fields['context_record__datings__period'].choices = \
- models.Period.get_types()
- self.fields['context_record__datings__period'].help_text = \
- models.Period.get_help()
- self.fields['context_record__unit'].choices = models.Unit.get_types()
- self.fields['context_record__unit'].help_text = models.Unit.get_help()
-
-
-RecordSourceFormSelection = get_form_selection(
- 'RecordSourceFormSelection', _(u"Documentation search"), 'pk',
- models.ContextRecordSource, RecordSourceSelect, 'get-contextrecordsource',
- _(u"You should select a document."))
-
-record_source_modification_wizard = RecordSourceWizard([
- ('selec-record_source_modification', RecordSourceFormSelection),
- ('source-record_source_modification', SourceForm),
- ('authors-record_source_modification', AuthorFormset),
- ('final-record_source_modification', FinalForm)],
- url_name='record_source_modification',)
-
-class RecordSourceDeletionWizard(DeletionWizard):
- model = models.ContextRecordSource
- fields = ['context_record', 'title', 'source_type', 'authors',]
-
-record_source_deletion_wizard = RecordSourceDeletionWizard([
- ('selec-record_source_deletion', RecordSourceFormSelection),
- ('final-record_source_deletion', RecordDeletionForm)],
- url_name='record_source_deletion',)
diff --git a/ishtar/ishtar_base/forms_files.py b/ishtar/ishtar_base/forms_files.py
deleted file mode 100644
index c4c460cee..000000000
--- a/ishtar/ishtar_base/forms_files.py
+++ /dev/null
@@ -1,387 +0,0 @@
-#!/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.
-
-"""
-Files forms definitions
-"""
-import datetime
-
-from django import forms
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.core import validators
-from django.core.exceptions import ObjectDoesNotExist
-from django.db.models import Max
-from django.utils.translation import ugettext_lazy as _
-
-from ishtar import settings
-
-import models
-import widgets
-from forms import Wizard, FinalForm, FormSet, ClosingWizard, \
- ClosingDateFormSelection, SearchWizard, formset_factory, get_now, \
- reverse_lazy
-from forms_common import TownFormset, ParcelFormSet, \
- get_town_field, get_person_field
-from forms_operations import OperationAdministrativeActWizard, \
-AdministrativeActOpeForm, AdministrativeActOpeFormSelection, \
-AdministrativeActDeletionWizard, FinalAdministrativeActDeleteForm, is_preventive
-
-class FileWizard(Wizard):
- model = models.File
- object_parcel_type = 'associated_file'
-
- def get_form(self, request, storage, step=None, data=None, files=None):
- """
- Manage towns
- """
- if data:
- data = data.copy()
- else:
- data = {}
- # manage the dynamic choice of towns
- if not step:
- step = self.determine_step(request, storage)
- form = self.get_form_list(request, storage)[step]
- town_form_key = 'towns-' + self.url_name
- if step.startswith('parcels-') and hasattr(form, 'management_form') \
- and self.session_has_key(request, storage, town_form_key):
- towns = []
- qdict = request.session[storage.prefix]['step_data'][town_form_key]
- for k in qdict.keys():
- if k.endswith("town") and qdict[k]:
- try:
- town = models.Town.objects.get(pk=int(qdict[k]))
- towns.append((town.pk, unicode(town)))
- except (ObjectDoesNotExist, ValueError):
- pass
- data['TOWNS'] = sorted(towns, key=lambda x:x[1])
- form = super(FileWizard, self).get_form(request, storage, step, data,
- files)
- return form
-
- def get_extra_model(self, dct, request, storage, form_list):
- dct = super(FileWizard, self).get_extra_model(dct, request, storage,
- form_list)
- if not dct['numeric_reference']:
- current_ref = models.File.objects.filter(year=dct['year']
- ).aggregate(Max('numeric_reference'))["numeric_reference__max"]
- dct['numeric_reference'] = current_ref and current_ref + 1 or 1
- return dct
-
- def done(self, request, storage, form_list, **kwargs):
- '''
- Save parcels
- '''
- r = super(FileWizard, self).done(request, storage, form_list,
- return_object=True, **kwargs)
- if type(r) not in (list, tuple) or len(r) != 2:
- return r
- obj, res = r
- obj.parcels.clear()
- for form in form_list:
- if not hasattr(form, 'prefix') \
- or not form.prefix.startswith('parcels-') \
- or not hasattr(form, 'forms'):
- continue
- for frm in form.forms:
- if not frm.is_valid():
- continue
- dct = frm.cleaned_data.copy()
- if 'parcel' in dct:
- try:
- parcel = models.Parcel.objects.get(pk=dct['parcel'])
- setattr(parcel, self.object_parcel_type, obj)
- parcel.save()
- except (ValueError, ObjectDoesNotExist):
- continue
- continue
- try:
- dct['town'] = models.Town.objects.get(pk=int(dct['town']))
- except (ValueError, ObjectDoesNotExist):
- continue
- dct['associated_file'], dct['operation'] = None, None
- dct[self.object_parcel_type] = obj
- if 'DELETE' in dct:
- dct.pop('DELETE')
- parcel = models.Parcel.objects.filter(**dct).count()
- if not parcel:
- dct['history_modifier'] = request.user
- parcel = models.Parcel(**dct)
- parcel.save()
- return res
-
-class FileSelect(forms.Form):
- towns = get_town_field()
- in_charge = get_person_field(label=_(u"Person in charge"),
- person_type='sra_agent')
- file_type = forms.ChoiceField(label=_("File type"),
- choices=models.FileType.get_types())
- saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[])
- year = forms.IntegerField(label=_("Year"))
-
- def __init__(self, *args, **kwargs):
- super(FileSelect, self).__init__(*args, **kwargs)
- self.fields['saisine_type'].choices = models.SaisineType.get_types()
- self.fields['saisine_type'].help_text = models.SaisineType.get_help()
-
-class FileFormSelection(forms.Form):
- form_label = _("Archaeological file search")
- associated_models = {'pk':models.File}
- currents = {'pk':models.File}
- pk = forms.IntegerField(label="", required=False,
- widget=widgets.JQueryJqGrid(reverse_lazy('get-file'),
- FileSelect(), models.File, source_full=reverse_lazy('get-file-full')),
- validators=[models.valid_id(models.File)])
-
- def clean(self):
- cleaned_data = self.cleaned_data
- if 'pk' not in cleaned_data or not cleaned_data['pk']:
- raise forms.ValidationError(_(u"You should select a file."))
- return cleaned_data
-
-class FileFormGeneral(forms.Form):
- form_label = _("General")
- associated_models = {'in_charge':models.Person,
- 'related_file':models.File,
- 'file_type':models.FileType}
- in_charge = forms.IntegerField(label=_("Person in charge"),
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person',
- args=[models.PersonType.objects.get(txt_idx='sra_agent').pk]),
- associated_model=models.Person, new=True),
- validators=[models.valid_id(models.Person)])
- year = forms.IntegerField(label=_("Year"),
- initial=lambda:datetime.datetime.now().year,
- validators=[validators.MinValueValidator(1900),
- validators.MaxValueValidator(2100)])
- numeric_reference = forms.IntegerField(label=_("Numeric reference"),
- widget=forms.HiddenInput, required=False)
- internal_reference = forms.CharField(label=_(u"Internal reference"),
- max_length=60,
- validators=[models.is_unique(models.File, 'internal_reference')])
- creation_date = forms.DateField(label=_(u"Creation date"),
- initial=get_now, widget=widgets.JQueryDate)
- file_type = forms.ChoiceField(label=_("File type"),
- choices=models.FileType.get_types())
- related_file = forms.IntegerField(label=_("Related file"), required=False,
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-file'),
- associated_model=models.File),
- validators=[models.valid_id(models.File)])
- comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea,
- required=False)
-
-class FileFormGeneralRO(FileFormGeneral):
- year = forms.IntegerField(label=_(u"Year"),
- widget=forms.TextInput(attrs={'readonly':True}))
- numeric_reference = forms.IntegerField(label=_(u"Numeric reference"),
- widget=forms.TextInput(attrs={'readonly':True}))
- internal_reference = forms.CharField(label=_(u"Internal reference"),
- widget=forms.TextInput(attrs={'readonly':True},))
-
-class FileFormAddress(forms.Form):
- form_label = _(u"Address")
- associated_models = {'town':models.Town}
- total_surface = forms.IntegerField(required=False,
- widget=widgets.AreaWidget,
- label=_(u"Total surface (m²)"),
- validators=[validators.MinValueValidator(0),
- validators.MaxValueValidator(999999999)])
- address = forms.CharField(label=_(u"Main address"), widget=forms.Textarea)
- address_complement = forms.CharField(label=_(u"Main address - complement"),
- required=False)
- postal_code = forms.CharField(label=_(u"Main address - postal code"),
- max_length=10)
-
-class FileFormPreventive(forms.Form):
- form_label = _(u"Preventive informations")
- associated_models = {'general_contractor':models.Person,
- 'saisine_type':models.SaisineType,
- 'permit_type':models.PermitType,
- 'town_planning_service':models.Organization}
- general_contractor = forms.IntegerField(label=_(u"General contractor"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-person',
- args=[models.PersonType.objects.get(txt_idx='general_contractor').pk]),
- associated_model=models.Person, new=True),
- validators=[models.valid_id(models.Person)])
- town_planning_service = forms.IntegerField(required=False,
- label=_(u"Town planning service"),
- widget=widgets.JQueryAutoComplete(
- reverse_lazy('autocomplete-organization',
- args=[models.OrganizationType.objects.get(txt_idx='planning_service').pk]),
- associated_model=models.Organization, new=True),
- validators=[models.valid_id(models.Organization)])
- permit_type = forms.ChoiceField(label=_(u"Permit type"), required=False,
- choices=models.PermitType.get_types())
- permit_reference = forms.CharField(label=_(u"Permit reference"),
- required=False, validators=[validators.MaxLengthValidator(60)])
- total_developed_surface = forms.IntegerField(widget=widgets.AreaWidget,
- label=_(u"Total developed surface (m²)"),
- required=False, validators=[validators.MinValueValidator(0),
- validators.MaxValueValidator(999999999)])
- if settings.COUNTRY == 'fr':
- saisine_type = forms.ChoiceField(label=_(u"Saisine type"),
- choices=[])
- reception_date = forms.DateField(label=_(u"Reception date"),
- initial=get_now, widget=widgets.JQueryDate)
- def __init__(self, *args, **kwargs):
- super(FileFormPreventive, self).__init__(*args, **kwargs)
- self.fields['saisine_type'].choices = models.SaisineType.get_types()
- self.fields['saisine_type'].help_text = models.SaisineType.get_help()
-
-file_search_wizard = SearchWizard([('general-file_search', FileFormSelection)],
- url_name='file_search',)
-
-file_creation_wizard = FileWizard([
- ('general-file_creation', FileFormGeneral),
- ('address-file_creation', FileFormAddress),
- ('towns-file_creation', TownFormset),
- ('parcels-file_creation', ParcelFormSet),
- ('preventive-file_creation', FileFormPreventive),
- ('final-file_creation', FinalForm)],
- condition_list={
-'preventive-file_creation':is_preventive('general-file_creation',
- models.FileType, type_key='file_type')
- },
- url_name='file_creation',)
-
-class FileModificationWizard(FileWizard):
- modification = True
-
-file_modification_wizard = FileModificationWizard([
- ('selec-file_modification', FileFormSelection),
- ('general-file_modification', FileFormGeneralRO),
- ('adress-file_modification', FileFormAddress),
- ('towns-file_modification', TownFormset),
- ('parcels-file_modification', ParcelFormSet),
- ('preventive-file_modification', FileFormPreventive),
- ('final-file_modification', FinalForm)],
- condition_list={
-'preventive-file_modification':is_preventive('general-file_modification',
- models.FileType, type_key='file_type')
- },
- url_name='file_modification',)
-
-class FileClosingWizard(ClosingWizard):
- model = models.File
- fields = ['year', 'numeric_reference', 'internal_reference',
- 'file_type', 'in_charge', 'general_contractor', 'creation_date',
- 'reception_date', 'total_surface', 'total_developed_surface',
- 'address', 'address_complement', 'postal_code', 'comment']
- if settings.COUNTRY == 'fr':
- fields += ['saisine_type', 'reference_number']
- fields += ['towns']
-
-class FinalFileClosingForm(FinalForm):
- confirm_msg = " "
- confirm_end_msg = _(u"Would you like to close this archaeological file?")
-
-file_closing_wizard = FileClosingWizard([
- ('selec-file_closing', FileFormSelection),
- ('date-file_closing', ClosingDateFormSelection),
- ('final-file_closing', FinalFileClosingForm)],
- url_name='file_closing',)
-
-class FileDeletionWizard(FileClosingWizard):
- def get_formated_datas(self, forms):
- datas = super(FileDeletionWizard, self).get_formated_datas(forms)
- datas.append((_("Associated operations"), []))
- for operation in models.Operation.objects.filter(
- associated_file=self.current_obj).all():
- if operation.end_date:
- datas[-1][1].append(('', unicode(operation)))
- return datas
-
- def done(self, request, storage, form_list, **kwargs):
- obj = self.get_current_object(request, storage)
- for operation in models.Operation.objects.filter(
- associated_file=obj).all():
- operation.delete()
- obj.delete()
- return render_to_response('wizard_done.html', {},
- context_instance=RequestContext(request))
-
-
-class FinalFileDeleteForm(FinalForm):
- confirm_msg = " "
- confirm_end_msg = _(u"Would you like to delete this archaelogical file ?")
-
-file_deletion_wizard = FileDeletionWizard([
- ('selec-file_deletion', FileFormSelection),
- ('final-file_deletion', FinalFileDeleteForm)],
- url_name='file_deletion',)
-
-class FileAdministrativeActWizard(OperationAdministrativeActWizard):
- model = models.File
-
-class FileEditAdministrativeActWizard(FileAdministrativeActWizard):
- model = models.AdministrativeAct
- edit = True
- def get_associated_item(self, request, storage, dct):
- return self.get_current_object(request, storage).associated_file
-
-class AdministrativeActFileSelect(forms.Form):
- associated_file__towns = get_town_field()
- act_type = forms.ChoiceField(label=_("Act type"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(AdministrativeActFileSelect, self).__init__(*args, **kwargs)
- self.fields['act_type'].choices = models.ActType.get_types(
- dct={'intented_to':'F'})
- self.fields['act_type'].help_text = models.ActType.get_help(
- dct={'intented_to':'F'})
-
-class AdministrativeActFileFormSelection(AdministrativeActOpeFormSelection):
- pk = forms.IntegerField(label="", required=False,
- widget=widgets.JQueryJqGrid(reverse_lazy('get-administrativeactfile'),
- AdministrativeActFileSelect(), models.AdministrativeAct,
- table_cols='TABLE_COLS_FILE'),
- validators=[models.valid_id(models.AdministrativeAct)])
-
-class AdministrativeActFileForm(AdministrativeActOpeForm):
- act_type = forms.ChoiceField(label=_(u"Act type"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(AdministrativeActFileForm, self).__init__(*args, **kwargs)
- self.fields['act_type'].choices = models.ActType.get_types(
- dct={'intented_to':'F'})
- self.fields['act_type'].help_text = models.ActType.get_help(
- dct={'intented_to':'F'})
-
-file_administrativeactfile_wizard = FileAdministrativeActWizard([
- ('selec-file_administrativeactfile', FileFormSelection),
- ('administrativeact-file_administrativeactfile', AdministrativeActFileForm),
- ('final-file_administrativeactfile', FinalForm)],
- url_name='file_administrativeactfile',)
-
-file_administrativeactfile_modification_wizard = FileEditAdministrativeActWizard([
- ('selec-file_administrativeactfile_modification',
- AdministrativeActFileFormSelection),
- ('administrativeact-file_administrativeactfile_modification',
- AdministrativeActFileForm),
- ('final-file_administrativeactfile_modification', FinalForm)],
- url_name='file_administrativeactfile_modification',)
-
-file_administrativeactfile_deletion_wizard = AdministrativeActDeletionWizard([
- ('selec-file_administrativeactfile_deletion',
- AdministrativeActFileFormSelection),
- ('final-file_administrativeactfile_deletion',
- FinalAdministrativeActDeleteForm)],
- url_name='file_administrativeactfile_deletion',)
-
diff --git a/ishtar/ishtar_base/forms_items.py b/ishtar/ishtar_base/forms_items.py
deleted file mode 100644
index b763d94b2..000000000
--- a/ishtar/ishtar_base/forms_items.py
+++ /dev/null
@@ -1,525 +0,0 @@
-#!/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_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"<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_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',)
-"""
diff --git a/ishtar/ishtar_base/forms_main.py b/ishtar/ishtar_base/forms_main.py
deleted file mode 100644
index 29253f284..000000000
--- a/ishtar/ishtar_base/forms_main.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (C) 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.
-
-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/ishtar_base/forms_operations.py b/ishtar/ishtar_base/forms_operations.py
deleted file mode 100644
index e163b5869..000000000
--- a/ishtar/ishtar_base/forms_operations.py
+++ /dev/null
@@ -1,754 +0,0 @@
-#!/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.shortcuts import render_to_response
-from django.template import RequestContext
-from django.core import validators
-from django.core.exceptions import ObjectDoesNotExist
-from django.db.models import Max
-from django.utils.translation import ugettext_lazy as _
-
-from ishtar import settings
-
-import models
-import widgets
-from forms import Wizard, FinalForm, FormSet, SearchWizard, ClosingWizard, \
- ClosingDateFormSelection, DeletionWizard, formset_factory, get_now, \
- reverse_lazy, get_form_selection
-from forms_common import TownForm, TownFormSet, TownFormset, ParcelFormSet, \
- ParcelForm, AuthorFormset, SourceForm, SourceWizard, SourceSelect, \
- SourceDeletionForm, get_town_field
-
-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:
- typ = int(request.session[storage.prefix]['step_data']\
- [form_name][form_name+'-'+type_key])
- return model.is_preventive(typ, 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
- # 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:
- town_form_key = step.startswith('parcelsgeneral') \
- and 'townsgeneral-' or 'towns-'
- town_form_key += self.url_name
- town_ids = self.session_get_value(request, storage,
- town_form_key, 'town', multi=True) or []
- towns = []
- 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_formated_datas(self, forms):
- """
- Show a specific warning if no archaelogical file is provided
- """
- datas = super(OperationWizard, self).get_formated_datas(forms)
- # if the general town form is used the advertissement is pertinent
- has_no_af = [form.prefix for form in forms
- if form.prefix == 'townsgeneral-operation'] and True
- if has_no_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):
- common_name = forms.CharField(label=_(u"Name"), max_length=30)
- towns = get_town_field()
- operation_type = forms.ChoiceField(label=_(u"Operation type"),
- choices=[])
- remains = forms.ChoiceField(label=_(u"Remains"),
- choices=models.RemainType.get_types())
- year = forms.IntegerField(label=_("Year"))
- end_date = forms.NullBooleanField(label=_(u"Is open?"))
-
- def __init__(self, *args, **kwargs):
- super(OperationSelect, self).__init__(*args, **kwargs)
- self.fields['operation_type'].choices = models.OperationType.get_types()
- self.fields['operation_type'].help_text = models.OperationType.get_help()
-
-class OperationFormSelection(forms.Form):
- form_label = _(u"Operation search")
- 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,
- source_full=reverse_lazy('get-operation-full')),
- 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 OperationCodeInput(forms.TextInput):
- """Manage auto complete whene changing year in form"""
- def render(self, *args, **kwargs):
- name, value = args
- base_name = '-'.join(name.split('-')[:-1])
- rendered = super(OperationCodeInput, self).render(*args, **kwargs)
- js = u"""\n <script type="text/javascript"><!--//
- function initialyse_operation_code () {
- // if the form is in creation mode
- if(!$("#id_%(base_name)s-pk").val()){
- $("#id_%(base_name)s-year").change(function() {
- var year = $("#id_%(base_name)s-year").val();
- var url = "%(url)s" + year;
- $.getJSON(url, function(data) {
- $("#id_%(name)s").val(data.id);
- });
- });
- }
- }
- $(document).ready(initialyse_operation_code());
- //--></script>\n""" % {'base_name':base_name, 'name':name,
- 'url':reverse_lazy('get_available_operation_code')}
- return rendered + js
-
-class OperationFormGeneral(forms.Form):
- form_label = _(u"General")
- associated_models = {'in_charge':models.Person,
- 'associated_file':models.File,
- 'operation_type':models.OperationType}
- currents = {'associated_file':models.File}
- pk = forms.IntegerField(required=False, widget=forms.HiddenInput)
- 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, new=True),
- validators=[models.valid_id(models.Person)], required=False)
- associated_file = forms.IntegerField(label=_(u"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=_(u"Operation type"),
- choices=[])
- start_date = forms.DateField(label=_(u"Start date"), required=False,
- widget=widgets.JQueryDate)
- excavation_end_date = forms.DateField(label=_(u"Excavation end date"),
- required=False, widget=widgets.JQueryDate)
- surface = forms.IntegerField(required=False, widget=widgets.AreaWidget,
- label=_(u"Total surface (m²)"),
- validators=[validators.MinValueValidator(0),
- validators.MaxValueValidator(999999999)])
- year = forms.IntegerField(label=_(u"Year"),
- initial=lambda:datetime.datetime.now().year,
- validators=[validators.MinValueValidator(1900),
- validators.MaxValueValidator(2100)])
- operation_code = forms.IntegerField(label=_(u"Operation code"),
- initial=models.Operation.get_available_operation_code,
- widget=OperationCodeInput)
- common_name = forms.CharField(label=_(u"Generic name"), required=False,
- max_length=120, widget=forms.Textarea)
- operator_reference = forms.CharField(label=_(u"Operator reference"),
- required=False, max_length=20)
- 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)])
- comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea,
- required=False)
-
- def __init__(self, *args, **kwargs):
- super(OperationFormGeneral, self).__init__(*args, **kwargs)
- self.fields['operation_type'].choices = models.OperationType.get_types()
- self.fields['operation_type'].help_text = models.OperationType.get_help()
-
- def clean(self):
- cleaned_data = self.cleaned_data
- # verify the logic between start date and excavation end date
- if cleaned_data['excavation_end_date']:
- if not self.cleaned_data['start_date']:
- raise forms.ValidationError(_(u"If you want to set an "
- u"excavation end date you have to provide a start date."))
- if cleaned_data['excavation_end_date'] < cleaned_data['start_date']:
- raise forms.ValidationError(_(u"The excavation end date "\
- u"cannot be before the start date."))
- year = self.cleaned_data.get("year")
- operation_code = cleaned_data.get("operation_code")
- ops = models.Operation.objects.filter(year=year,
- operation_code=operation_code)
- # manage unique operation ID
- if 'pk' in cleaned_data and cleaned_data['pk']:
- ops = ops.exclude(pk=cleaned_data['pk'])
- if ops.count():
- max_val = models.Operation.objects.filter(year=year).aggregate(
- Max('operation_code'))["operation_code__max"]
- raise forms.ValidationError(_(u"Operation code already exist for "
- u"year: %(year)d - use a value bigger than %(last_val)d") % {
- 'year':year, 'last_val':max_val})
- return self.cleaned_data
-
-class OperationFormPreventive(forms.Form):
- form_label = _(u"Preventive informations - excavation")
- cost = forms.IntegerField(label=_(u"Cost (€)"), required=False)
- scheduled_man_days = forms.IntegerField(label=_(u"Scheduled man-days"),
- required=False)
- optional_man_days = forms.IntegerField(label=_(u"Optional man-days"),
- required=False)
- effective_man_days = forms.IntegerField(label=_(u"Effective man-days"),
- 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 = _(u"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")
- base_model = 'remain'
- 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 self.check_duplicate(['remain_type'],
- _(u"There are identical remain types"))
-
-RemainFormset = formset_factory(RemainForm, can_delete=True,
- formset=RemainFormSet)
-RemainFormset.form_label = _("Remain types")
-
-class PeriodForm(forms.Form):
- form_label = _("Periods")
- base_model = 'period'
- 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 self.check_duplicate(['period'],
- _(u"There are identical periods"))
-
-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),
- ('preventive-operation_creation', OperationFormPreventive),
- ('preventivediag-operation_creation', OperationFormPreventiveDiag),
- ('townsgeneral-operation_creation', TownFormset),
- ('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',)
-
-class OperationModificationWizard(OperationWizard):
- modification = True
-
-operation_modification_wizard = OperationModificationWizard([
- ('selec-operation_modification', OperationFormSelection),
- ('general-operation_modification', OperationFormGeneral),
- ('preventive-operation_modification', OperationFormPreventive),
- ('preventivediag-operation_modification', OperationFormPreventiveDiag),
- ('towns-operation_modification', SelectedTownFormset),
- ('townsgeneral-operation_modification', TownFormset),
- ('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 OperationClosingWizard(ClosingWizard):
- model = models.Operation
- fields = ['year', 'operation_code', 'operation_type', 'associated_file',
-'in_charge', 'start_date', 'excavation_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', ClosingDateFormSelection),
- ('final-operation_closing', FinalOperationClosingForm)],
- url_name='operation_closing',)
-
-class OperationDeletionWizard(DeletionWizard):
- model = models.Operation
- fields = OperationClosingWizard.fields
-
-class OperationDeletionForm(FinalForm):
- confirm_msg = " "
- confirm_end_msg = _(u"Would you like to delete this operation?")
-
-operation_deletion_wizard = OperationDeletionWizard([
- ('selec-operation_deletion', OperationFormSelection),
- ('final-operation_deletion', OperationDeletionForm)],
- url_name='operation_deletion',)
-
-####################################
-# Source management for operations #
-####################################
-
-class OperationSourceWizard(SourceWizard):
- model = models.OperationSource
- def get_form_initial(self, request, storage, step):
- initial = super(OperationSourceWizard, self).get_form_initial(request,
- storage, step)
- # put default index and operation_id field in the main source form
- general_form_key = 'selec-' + self.url_name
- if step.startswith('source-') \
- and self.session_has_key(request, storage, general_form_key):
- gen_storage = request.session[storage.prefix]['step_data']\
- [general_form_key]
- if general_form_key+"-operation" in gen_storage:
- operation_id = int(gen_storage[general_form_key+"-operation"])
- elif general_form_key+"-pk" in gen_storage:
- pk = int(gen_storage[general_form_key+"-pk"])
- try:
- source = models.OperationSource.objects.get(pk=pk)
- operation_id = source.operation.pk
- except ObjectDoesNotExist:
- pass
- if operation_id:
- initial['hidden_operation_id'] = operation_id
- if 'index' not in initial:
- max_val = models.OperationSource.objects.filter(
- operation__pk=operation_id).aggregate(
- Max('index'))["index__max"]
- initial['index'] = max_val and (max_val + 1) or 1
- return initial
-
-class OperationSourceForm(SourceForm):
- pk = forms.IntegerField(required=False, widget=forms.HiddenInput)
- index = forms.IntegerField(label=_(u"Index"))
- hidden_operation_id = forms.IntegerField(label="", widget=forms.HiddenInput)
-
- def __init__(self, *args, **kwargs):
- super(OperationSourceForm, self).__init__(*args, **kwargs)
- keyOrder = self.fields.keyOrder
- keyOrder.pop(keyOrder.index('index'))
- keyOrder.insert(keyOrder.index('source_type') + 1, 'index')
-
- def clean(self):
- # manage unique operation ID
- cleaned_data = self.cleaned_data
- operation_id = cleaned_data.get("hidden_operation_id")
- index = cleaned_data.get("index")
- srcs = models.OperationSource.objects.filter(index=index,
- operation__pk=operation_id)
- if 'pk' in cleaned_data and cleaned_data['pk']:
- srcs = srcs.exclude(pk=cleaned_data['pk'])
- if srcs.count():
- max_val = models.OperationSource.objects.filter(
- operation__pk=operation_id
- ).aggregate(Max('index'))["index__max"]
- operation = models.Operation.objects.get(pk=operation_id)
- raise forms.ValidationError(_(u"Index already exist for "
-"operation: %(operation)s - use a value bigger than %(last_val)d") % {
- "operation":unicode(operation), 'last_val':max_val})
- return cleaned_data
-
-SourceOperationFormSelection = get_form_selection(
- 'SourceOperationFormSelection', _(u"Operation search"), 'operation',
- models.Operation, OperationSelect, 'get-operation',
- _(u"You should select an operation."))
-
-operation_source_creation_wizard = OperationSourceWizard([
- ('selec-operation_source_creation', SourceOperationFormSelection),
- ('source-operation_source_creation',OperationSourceForm),
- ('authors-operation_source_creation', AuthorFormset),
- ('final-operation_source_creation', FinalForm)],
- url_name='operation_source_creation',)
-
-class OperationSourceSelect(SourceSelect):
- operation__towns = get_town_field(label=_(u"Operation's town"))
- operation__operation_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', OperationSourceForm),
- ('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',)
-
-################################################
-# Administrative act management for operations #
-################################################
-
-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 = get_town_field()
- act_type = forms.ChoiceField(label=_("Act type"), choices=[])
-
- def __init__(self, *args, **kwargs):
- super(AdministrativeActOpeSelect, self).__init__(*args, **kwargs)
- self.fields['act_type'].choices = models.ActType.get_types(
- dct={'intented_to':'O'})
- self.fields['act_type'].help_text = models.ActType.get_help(
- dct={'intented_to':'O'})
-
-class AdministrativeActOpeFormSelection(forms.Form):
- form_label = _("Administrative act search")
- 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=[])
- signatory = forms.IntegerField(label=_("Signatory"),
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'),
- associated_model=models.Person, new=True),
- 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)
-
- def __init__(self, *args, **kwargs):
- super(AdministrativeActOpeForm, self).__init__(*args, **kwargs)
- self.fields['act_type'].choices = models.ActType.get_types(
- dct={'intented_to':'O'})
- self.fields['act_type'].help_text = models.ActType.get_help(
- dct={'intented_to':'O'})
-
-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',)
diff --git a/ishtar/ishtar_base/management/__init__.py b/ishtar/ishtar_base/management/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/ishtar/ishtar_base/management/__init__.py
+++ /dev/null
diff --git a/ishtar/ishtar_base/management/commands/__init__.py b/ishtar/ishtar_base/management/commands/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/ishtar/ishtar_base/management/commands/__init__.py
+++ /dev/null
diff --git a/ishtar/ishtar_base/management/commands/generate_rights.py b/ishtar/ishtar_base/management/commands/generate_rights.py
deleted file mode 100644
index 75b1cf807..000000000
--- a/ishtar/ishtar_base/management/commands/generate_rights.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (C) 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.
-
-import sys
-
-from django.core.management.base import BaseCommand, CommandError
-from django.core.exceptions import ObjectDoesNotExist
-
-import ishtar_base.forms_main as ishtar_forms
-import ishtar_base.models as models
-
-class Command(BaseCommand):
- args = ''
- help = 'Regenerate rights for current forms'
-
- def handle(self, *args, **options):
- wizards = []
- wizard_steps = {}
- for attr in dir(ishtar_forms):
- if not attr.endswith('_wizard'):
- continue
- wizard = getattr(ishtar_forms, attr)
- url_name = wizard.url_name
- try:
- wizard_obj = models.Wizard.objects.get(url_name=url_name)
- except ObjectDoesNotExist:
- wizard_obj = models.Wizard.objects.create(url_name=url_name)
- wizard_obj.save()
- #self.stdout.write('* Wizard "%s" added\n' % url_name)
- sys.stdout.write('* Wizard "%s" added\n' % url_name)
- wizard_steps[url_name] = []
- for idx, step_url_name in enumerate(wizard.form_list.keys()):
- form = wizard.form_list[step_url_name]
- if issubclass(form, ishtar_forms.FinalForm):
- break # don't reference the final form
- step_values = {'name':unicode(form.form_label),
- 'order':idx}
- try:
- step_obj = models.WizardStep.objects.get(wizard=wizard_obj,
- url_name=step_url_name)
- for k in step_values:
- setattr(step_obj, k, step_values[k])
- step_obj.save()
- except ObjectDoesNotExist:
- step_values.update({'wizard':wizard_obj,
- 'url_name':step_url_name})
- step_obj = models.WizardStep.objects.create(**step_values)
- step_obj.save()
- #self.stdout.write('* Wizard step "%s" added\n' \
- # % unicode(form.form_label))
- sys.stdout.write('* Wizard step "%s" added\n' \
- % unicode(form.form_label))
- wizard_steps[url_name].append(step_url_name)
- #self.stdout.write('Successfully regeneration of wizard rights\n')
- sys.stdout.write('Successfully regeneration of wizard rights\n')
diff --git a/ishtar/ishtar_base/menus.py b/ishtar/ishtar_base/menus.py
deleted file mode 100644
index 79355a6be..000000000
--- a/ishtar/ishtar_base/menus.py
+++ /dev/null
@@ -1,331 +0,0 @@
-#!/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.
-
-"""
-Menus
-"""
-
-from django.utils.translation import ugettext_lazy as _
-
-import models
-
-class SectionItem:
- def __init__(self, idx, label, childs=[]):
- self.idx = idx
- self.label = label
- self.childs = childs
- self.available = False
- self.items = {}
-
- def can_be_available(self, user):
- for child in self.childs:
- if child.can_be_available(user):
- return True
- return False
-
- def is_available(self, user, obj=None):
- for child in self.childs:
- if child.is_available(user, obj):
- return True
- return False
-
- def set_items(self, user, items):
- if user:
- self.available = self.can_be_available(user)
- for child in self.childs:
- child.set_items(user, items)
- items[child.idx] = child
-
-class MenuItem:
- def __init__(self, idx, label, model=None, access_controls=[]):
- self.idx = idx
- self.label = label
- self.model = model
- self.access_controls = access_controls
- self.available = False
-
- def can_be_available(self, user):
- if not self.access_controls:
- return True
- for access_control in self.access_controls:
- access_control = self.model._meta.app_label + '.' + access_control
- if user.has_perm(access_control, self.model):
- return True
- # manage by person type
- if hasattr(user, 'ishtaruser'):
- person_type = user.ishtaruser.person.person_type
- if person_type.rights.filter(wizard__url_name=self.idx).count():
- return True
- return False
-
- def is_available(self, user, obj=None):
- if not self.access_controls:
- return True
- for access_control in self.access_controls:
- access_control = self.model._meta.app_label + '.' + access_control
- if user.has_perm(access_control, self.model, obj):
- return True
- # manage by person type
- if hasattr(user, 'ishtaruser'):
- person_type = user.ishtaruser.person.person_type
- if person_type.rights.filter(wizard__url_name=self.idx).count():
- return True
- return False
-
- def set_items(self, user, items):
- if user:
- self.available = self.can_be_available(user)
-
-class Menu:
- def __init__(self, user):
- self.user = user
- self.initialized = False
- self.childs = [
- SectionItem('administration', _(u"Administration"),
- childs=[SectionItem('person', _(u"Person"),
- childs=[
- MenuItem('person_creation', _(u"Creation"),
- model=models.Person,
- access_controls=['add_person', 'add_own_person']),
- MenuItem('person_modification', _(u"Modification"),
- model=models.Person,
- access_controls=['change_person', 'change_own_person']),
- ]),
- MenuItem('account_management', _(u"Account management"),
- model=models.IshtarUser,
- access_controls=['add_ishtaruser',]),
- ]),
- SectionItem('file_management', _(u"Archaeological file"),
- childs=[
- MenuItem('file_search', _(u"Search"),
- model=models.File,
- access_controls=['view_file', 'view_own_file']),
- MenuItem('file_creation', _(u"Creation"),
- model=models.File,
- access_controls=['add_file', 'add_own_file']),
- MenuItem('file_modification', _(u"Modification"),
- model=models.File,
- access_controls=['change_file', 'change_own_file']),
- MenuItem('file_closing', _(u"Closing"),
- model=models.File,
- access_controls=['change_file',
- 'change_own_file']),
- MenuItem('file_deletion', _(u"Deletion"),
- model=models.File,
- access_controls=['delete_file', 'delete_own_file']),
- SectionItem('admin_act_files', _(u"Administrative act"),
- childs=[
- MenuItem('file_administrativeactfile',
- _(u"Add"),
- model=models.Operation,
- access_controls=['change_file', 'change_own_file']),
- MenuItem('file_administrativeactfile_modification',
- _(u"Modification"),
- model=models.AdministrativeAct,
- access_controls=['change_file', 'change_own_file']),
- MenuItem('file_administrativeactfile_deletion',
- _(u"Deletion"),
- model=models.AdministrativeAct,
- access_controls=['delete_file', 'delete_own_file']),
- ],),
- ]),
- SectionItem('operation_management', _(u"Operation"),
- childs=[
- MenuItem('operation_search', _(u"Search"),
- model=models.Operation,
- access_controls=['view_operation',
- 'view_own_operation']),
- MenuItem('operation_creation', _(u"Creation"),
- model=models.Operation,
- access_controls=['add_operation',
- 'add_own_operation']),
- MenuItem('operation_modification', _(u"Modification"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_closing', _(u"Closing"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_deletion', _(u"Deletion"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- SectionItem('admin_act_operations',
- _(u"Administrative act"),
- childs=[
- MenuItem('operation_administrativeactop',
- _(u"Add"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_administrativeactop_modification',
- _(u"Modification"),
- model=models.AdministrativeAct,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_administrativeactop_deletion',
- _(u"Deletion"),
- model=models.AdministrativeAct,
- access_controls=['operation_deletion',
- 'delete_own_operation']),
- ],),
- ]),
- SectionItem('record_management', _(u"Context record"),
- childs=[
- MenuItem('record_search', _(u"Search"),
- model=models.ContextRecord,
- access_controls=['view_contextrecord',
- 'view_own_contextrecord']),
- MenuItem('record_creation', _(u"Creation"),
- model=models.ContextRecord,
- access_controls=['add_contextrecord',
- 'add_own_contextrecord']),
- MenuItem('record_modification', _(u"Modification"),
- model=models.ContextRecord,
- access_controls=['change_contextrecord',
- 'change_own_contextrecord']),
- MenuItem('record_deletion', _(u"Deletion"),
- model=models.ContextRecord,
- access_controls=['delete_contextrecord',
- 'delete_own_contextrecord']),
- ]),
- SectionItem('item_management', _(u"Item"),
- childs=[
- MenuItem('item_search', _(u"Search"),
- model=models.Item,
- access_controls=['view_item',
- 'view_own_item']),
- MenuItem('item_creation', _(u"Creation"),
- model=models.Item,
- access_controls=['add_item',
- 'add_own_item']),
- MenuItem('item_modification', _(u"Modification"),
- model=models.Item,
- 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('source_management', _(u"Documentation"),
- childs=[
- SectionItem('admin_add_sources', _(u"Add"),
- childs=[
- MenuItem('operation_source_creation',
- _(u"Related to an operation"),
- model=models.OperationSource,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('record_source_creation',
- _(u"Related to a context record"),
- model=models.ContextRecordSource,
- access_controls=['change_contextrecord',
- 'change_own_contextrecord']),
- MenuItem('item_source_creation',
- _(u"Related to an archaelogical item"),
- model=models.ItemSource,
- access_controls=['change_item',
- 'change_own_item']),
- ]),
- SectionItem('admin_mod_sources', _(u"Modify"),
- childs=[
- MenuItem('operation_source_modification',
- _(u"Related to an operation"),
- model=models.OperationSource,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('record_source_modification',
- _(u"Related to a context record"),
- model=models.ContextRecordSource,
- access_controls=['change_contextrecord',
- 'change_own_contextrecord']),
- MenuItem('item_source_modification',
- _(u"Related to an archaelogical item"),
- model=models.ItemSource,
- access_controls=['change_item',
- 'change_own_item']),
- ]),
- SectionItem('admin_del_sources', _(u"Deletion"),
- childs=[
- MenuItem('operation_source_deletion',
- _(u"Related to an operation"),
- model=models.OperationSource,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('record_source_deletion',
- _(u"Related to a context record"),
- model=models.ContextRecordSource,
- access_controls=['change_contextrecord',
- 'change_own_contextrecord']),
- MenuItem('item_source_deletion',
- _(u"Related to an archaelogical item"),
- model=models.ItemSource,
- access_controls=['change_item',
- 'change_own_item']),
- ]),
- ]),
- #SectionItem('warehouse', _(u"Warehouse"),
- # childs=[
- # MenuItem('warehouse_inventory', _(u"Inventory"),
- # model=models.Warehouse,
- # access_controls=['change_warehouse',]),
- # MenuItem('warehouse_recording', _(u"Recording"),
- # model=models.Treatment,
- # access_controls=['add_treatment', 'add_own_treatment']),
- # MenuItem('warehouse_lend', _(u"Lending"),
- # model=models.Treatment,
- # access_controls=['add_treatment', 'add_own_treatment']),
- # ]),
- SectionItem('dashboard', _(u"Dashboard"),
- childs=[
- MenuItem('dashboard_main', _(u"General informations"),
- model=models.File,
- access_controls=['change_file', 'change_own_file']),
- MenuItem('dashboard_file', _(u"Archaeological files"),
- model=models.File,
- access_controls=['change_file', 'change_own_file']),
- MenuItem('dashboard_operation', _(u"Operations"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- #MenuItem('dashboard_treatment', _(u"Treatments"),
- # model=models.Treatment,
- # access_controls=['change_treatment',]),
- #MenuItem('dashboard_warehouse', _(u"Warehouses"),
- # model=models.Warehouse,
- # access_controls=['change_warehouse',]),
- ]),
- ]
- self.items = {}
-
- def init(self):
- if self.initialized:
- return
- self.items = {}
- for main_menu in self.childs:
- main_menu.set_items(self.user, self.items)
- self.initialized = True
-
-menu = Menu(None)
-menu.init()
diff --git a/ishtar/ishtar_base/models.py b/ishtar/ishtar_base/models.py
deleted file mode 100644
index 41979129b..000000000
--- a/ishtar/ishtar_base/models.py
+++ /dev/null
@@ -1,2163 +0,0 @@
-#!/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.
-
-"""
-Models description
-"""
-import datetime
-
-from django.core.exceptions import ObjectDoesNotExist, ValidationError
-from django.core.validators import validate_slug
-from django.utils.translation import ugettext_lazy as _, ugettext
-from django.utils.safestring import SafeUnicode, mark_safe
-from django.core.urlresolvers import reverse, NoReverseMatch
-from django.db.utils import DatabaseError
-from django.db.models import Q, Max, Count, Sum, Avg
-from django.db.models.signals import m2m_changed, post_save
-
-from django.contrib.auth.models import User
-from django.contrib.gis.db import models
-from django.contrib import admin
-
-from simple_history.models import HistoricalRecords as BaseHistoricalRecords
-
-from ishtar import settings
-
-JOINT = u" - "
-
-# HistoricalRecords enhancement: don't save identical versions
-class HistoricalRecords(BaseHistoricalRecords):
- def create_historical_record(self, instance, type):
- manager = getattr(instance, self.manager_name)
- attrs = {}
- for field in instance._meta.fields:
- attrs[field.attname] = getattr(instance, field.attname)
- history = instance.history.all()
- if not history:
- manager.create(history_type=type, **attrs)
- return
- old_instance = history[0]
- for field in instance._meta.fields:
- if getattr(old_instance, field.attname) != attrs[field.attname]:
- manager.create(history_type=type, **attrs)
- return
-
-# valid ID validator for models
-def valid_id(cls):
- def func(value):
- try:
- cls.objects.get(pk=value)
- except ObjectDoesNotExist:
- raise ValidationError(_(u"Not a valid item."))
- return func
-
-def valid_ids(cls):
- def func(value):
- if "," in value:
- value = value.split(",")
- for v in value:
- try:
- cls.objects.get(pk=v)
- except ObjectDoesNotExist:
- raise ValidationError(
- _(u"An item selected is not a valid item."))
- return func
-
-# unique validator for models
-def is_unique(cls, field):
- def func(value):
- query = {field:value}
- try:
- assert cls.objects.filter(**query).count() == 0
- except AssertionError:
- raise ValidationError(_(u"This item already exist."))
- return func
-
-class OwnPerms:
- """
- Manage special permissions for object's owner
- """
- @classmethod
- def get_query_owns(cls, user):
- """
- Query object to get own items
- """
- return None # implement for each object
-
- def is_own(self, user):
- """
- Check if the current object is owned by the user
- """
- query = self.get_query_owns(user)
- if not query:
- return False
- query = query & Q(pk=self.pk)
- return cls.objects.filter(query).count()
-
- @classmethod
- def has_item_of(cls, user):
- """
- Check if the user own some items
- """
- query = cls.get_query_owns(user)
- if not query:
- return False
- return cls.objects.filter(query).count()
-
- @classmethod
- def get_owns(cls, user):
- """
- Get Own items
- """
- if isinstance(user, User):
- user = IshtarUser.objects.get(user_ptr=user)
- if user.is_anonymous():
- return []
- query = cls.get_query_owns(user)
- if not query:
- return []
- return cls.objects.filter(query).order_by(*cls._meta.ordering).all()
-
-class GeneralType(models.Model):
- """
- Abstract class for "types"
- """
- label = models.CharField(_(u"Label"), max_length=100)
- txt_idx = models.CharField(_(u"Textual ID"),
- validators=[validate_slug], max_length=30, unique=True)
- comment = models.TextField(_(u"Comment"), blank=True, null=True)
- available = models.BooleanField(_(u"Available"))
- HELP_TEXT = u""
-
- class Meta:
- abstract = True
-
- def __unicode__(self):
- return self.label
-
- @classmethod
- def get_help(cls, dct={}, exclude=[]):
- help_text = cls.HELP_TEXT
- c_rank = -1
- help_items = u"\n"
- for item in cls.get_types(dct=dct, instances=True, exclude=exclude):
- if hasattr(item, '__iter__'):
- # TODO: manage multiple levels
- continue
- if not item.comment:
- continue
- if c_rank > item.rank:
- help_items += u"</dl>\n"
- elif c_rank < item.rank:
- help_items += u"<dl>\n"
- c_rank = item.rank
- help_items += u"<dt>%s</dt><dd>%s</dd>" % (item.label,
- u"<br/>".join(item.comment.split('\n')))
- c_rank += 1
- if c_rank:
- help_items += c_rank*u"</dl>"
- if help_text or help_items != u'\n':
- return mark_safe(help_text + help_items)
- return u""
-
- @classmethod
- def get_types(cls, dct={}, instances=False, exclude=[]):
- base_dct = dct.copy()
- if hasattr(cls, 'parent'):
- return cls._get_parent_types(base_dct, instances, exclude=exclude)
- return cls._get_types(base_dct, instances, exclude=exclude)
-
- @classmethod
- def _get_types(cls, dct={}, instances=False, exclude=[]):
- dct['available'] = True
- if not instances:
- yield ('', '--')
- items = cls.objects.filter(**dct)
- if exclude:
- items = items.exclude(txt_idx__in=exclude)
- for item in items.all():
- if instances:
- item.rank = 0
- yield item
- else:
- yield (item.pk, _(unicode(item)))
-
- PREFIX = "&rsaquo; "
-
- @classmethod
- def _get_childs(cls, item, dct, prefix=0, instances=False, exclude=[]):
- prefix += 1
- dct['parent'] = item
- childs = cls.objects.filter(**dct)
- if exclude:
- childs = childs.exclude(txt_idx__in=exclude)
- if hasattr(cls, 'order'):
- childs = childs.order_by('order')
- for child in childs.all():
- if instances:
- child.rank = prefix
- yield child
- else:
- yield (child.pk, SafeUnicode(prefix*cls.PREFIX + \
- unicode(_(unicode(child))) ))
- for sub_child in cls._get_childs(child, dct, prefix, instances,
- exclude=exclude):
- yield sub_child
-
- @classmethod
- def _get_parent_types(cls, dct={}, instances=False, exclude=[]):
- dct['available'] = True
- if not instances:
- yield ('', '--')
- dct['parent'] = None
- items = cls.objects.filter(**dct)
- if exclude:
- items = items.exclude(txt_idx__in=exclude)
- if hasattr(cls, 'order'):
- items = items.order_by('order')
- for item in items.all():
- if instances:
- item.rank = 0
- yield item
- else:
- yield (item.pk, unicode(item))
- for child in cls._get_childs(item, dct, instances, exclude=exclude):
- yield child
-
-class HistoryError(Exception):
- def __init__(self, value):
- self.value = value
- def __str__(self):
- return repr(self.value)
-
-class BaseHistorizedItem(models.Model):
- history_modifier = models.ForeignKey(User, related_name='+',
- verbose_name=_(u"Last editor"))
- class Meta:
- abstract = True
-
- def save(self, *args, **kwargs):
- assert hasattr(self, 'history_modifier') == True
- super(BaseHistorizedItem, self).save(*args, **kwargs)
- return True
-
- def get_previous(self, step=None, date=None, strict=True):
- """
- Get a "step" previous state of the item
- """
- assert step or date
- historized = self.history.all()
- item = None
- if step:
- assert len(historized) > step
- item = historized[step]
- else:
- for step, item in enumerate(historized):
- if item.history_date == date:
- break
- # ended with no match
- if item.history_date != date:
- return
- item._step = step
- if len(historized) != (step + 1):
- item._previous = historized[step + 1].history_date
- else:
- item._previous = None
- if step > 0:
- item._next = historized[step - 1].history_date
- else:
- item._next = None
- item.history_date = historized[step].history_date
- model = self.__class__
- for k in model._meta.get_all_field_names():
- field = model._meta.get_field_by_name(k)[0]
- if hasattr(field, 'rel') and field.rel:
- if not hasattr(item, k+'_id'):
- setattr(item, k, getattr(self, k))
- continue
- val = getattr(item, k+'_id')
- if not val:
- setattr(item, k, None)
- continue
- try:
- val = field.rel.to.objects.get(pk=val)
- setattr(item, k, val)
- except ObjectDoesNotExist:
- if strict:
- raise HistoryError(u"The class %s has no pk %d" % (
- unicode(field.rel.to), val))
- setattr(item, k, None)
- item.pk = self.pk
- return item
-
- def rollback(self, date):
- """
- Rollback to a previous state
- """
- to_del, new_item = [], None
- for item in self.history.all():
- to_del.append(item)
- if item.history_date == date:
- new_item = item
- break
- if not new_item:
- raise HistoryError(u"The date to rollback to doesn't exist.")
- try:
- for f in self._meta.fields:
- k = f.name
- if k != 'id' and hasattr(self, k):
- if not hasattr(new_item, k):
- k = k + "_id"
- setattr(self, k, getattr(new_item, k))
- self.save()
- except:
- raise HistoryError(u"The rollback has failed.")
- # clean the obsolete history
- for historized_item in to_del:
- historized_item.delete()
-
- def values(self):
- values = {}
- for f in self._meta.fields:
- k = f.name
- if k != 'id':
- values[k] = getattr(self, k)
- return values
-
- def get_show_url(self):
- try:
- return reverse('show-'+self.__class__.__name__.lower(),
- args=[self.pk, ''])
- except NoReverseMatch:
- return
-
-class LightHistorizedItem(BaseHistorizedItem):
- history_date = models.DateTimeField(default=datetime.datetime.now)
- class Meta:
- abstract = True
-
- def save(self, *args, **kwargs):
- super(LightHistorizedItem, self).save(*args, **kwargs)
- return True
-
-class Wizard(models.Model):
- url_name = models.CharField(_(u"URL name"), max_length=128, unique=True)
- class Meta:
- verbose_name = _(u"Wizard")
- ordering = ['url_name']
-
- def __unicode__(self):
- return unicode(self.url_name)
-
-class WizardStep(models.Model):
- order = models.IntegerField(_(u"Order"))
- wizard = models.ForeignKey(Wizard, verbose_name=_(u"Wizard"))
- url_name = models.CharField(_(u"URL name"), max_length=128)
- name = models.CharField(_(u"Label"), max_length=128)
- class Meta:
- verbose_name = _(u"Wizard step")
- ordering = ['wizard', 'order']
-
- def __unicode__(self):
- return u"%s » %s" % (unicode(self.wizard), unicode(self.name))
-
-class UserDashboard:
- def __init__(self):
- types = IshtarUser.objects.values('person__person_type',
- 'person__person_type__label')
- self.types = types.annotate(number=Count('pk'))\
- .order_by('person__person_type')
-
-class FileDashboard:
- def __init__(self):
- main_dashboard = Dashboard(File)
-
- self.total_number = main_dashboard.total_number
-
- types = File.objects.values('file_type', 'file_type__label')
- self.types = types.annotate(number=Count('pk')).order_by('file_type')
-
- by_year = File.objects.extra(
- {'date':"date_trunc('year', creation_date)"})
- self.by_year = by_year.values('date')\
- .annotate(number=Count('pk')).order_by('-date')
-
- now = datetime.date.today()
- limit = datetime.date(now.year, now.month, 1) - datetime.timedelta(365)
- by_month = File.objects.filter(creation_date__gt=limit).extra(
- {'date':"date_trunc('month', creation_date)"})
- self.by_month = by_month.values('date')\
- .annotate(number=Count('pk')).order_by('-date')
-
- # research
- self.research = {}
- prog_type = FileType.objects.get(txt_idx='prog')
- researchs = File.objects.filter(file_type=prog_type)
- self.research['total_number'] = researchs.count()
- by_year = researchs.extra({'date':"date_trunc('year', creation_date)"})
- self.research['by_year'] = by_year.values('date')\
- .annotate(number=Count('pk'))\
- .order_by('-date')
- by_month = researchs.filter(creation_date__gt=limit)\
- .extra({'date':"date_trunc('month', creation_date)"})
- self.research['by_month'] = by_month.values('date')\
- .annotate(number=Count('pk'))\
- .order_by('-date')
-
- self.research['by_dpt'] = FileByDepartment.objects\
- .filter(file__file_type=prog_type,
- department__isnull=False)\
- .values('department__label')\
- .annotate(number=Count('file'))\
- .order_by('department__label')
- FileTown = File.towns.through
- self.research['towns'] = FileTown.objects\
- .filter(file__file_type=prog_type)\
- .values('town__name')\
- .annotate(number=Count('file'))\
- .order_by('-number','town__name')[:10]
-
- # rescue
- rescue_type = FileType.objects.get(txt_idx='preventive')
- rescues = File.objects.filter(file_type=rescue_type)
- self.rescue = {}
- self.rescue['total_number'] = rescues.count()
- self.rescue['saisine'] = rescues.values('saisine_type__label')\
- .annotate(number=Count('pk'))\
- .order_by('saisine_type__label')
- self.rescue['administrative_act'] = AdministrativeAct.objects\
- .filter(associated_file__isnull=False)\
- .values('act_type__label')\
- .annotate(number=Count('pk'))\
- .order_by('act_type__pk')
-
- by_year = rescues.extra({'date':"date_trunc('year', creation_date)"})
- self.rescue['by_year'] = by_year.values('date')\
- .annotate(number=Count('pk'))\
- .order_by('-date')
- by_month = rescues.filter(creation_date__gt=limit)\
- .extra({'date':"date_trunc('month', creation_date)"})
- self.rescue['by_month'] = by_month.values('date')\
- .annotate(number=Count('pk'))\
- .order_by('-date')
-
- self.rescue['by_dpt'] = FileByDepartment.objects\
- .filter(file__file_type=rescue_type,
- department__isnull=False)\
- .values('department__label')\
- .annotate(number=Count('file'))\
- .order_by('department__label')
- self.rescue['towns'] = FileTown.objects\
- .filter(file__file_type=rescue_type)\
- .values('town__name')\
- .annotate(number=Count('file'))\
- .order_by('-number','town__name')[:10]
-
- self.rescue['with_associated_operation'] = rescues\
- .filter(operations__isnull=False).count()
-
- self.rescue['with_associated_operation_percent'] = round(
- float(self.rescue['with_associated_operation'])\
- /self.rescue['total_number']*100, 2)
-
- by_year_operationnal = rescues.filter(operations__isnull=False)\
- .extra({'date':"date_trunc('year', creation_date)"})
- by_year_operationnal = by_year_operationnal.values('date')\
- .annotate(number=Count('pk'))\
- .order_by('-date')
- percents, idx = [], 0
- for dct in self.rescue['by_year']:
- if idx > len(by_year_operationnal):
- break
- if by_year_operationnal[idx]['date'] != dct['date'] or\
- not dct['number']:
- continue
- val = round(float(by_year_operationnal[idx]['number'])/\
- dct['number']*100, 2)
- percents.append({'date':dct['date'], 'number':val})
- self.rescue['operational_by_year'] = percents
-
- self.rescue['surface_by_town'] = FileTown.objects\
- .filter(file__file_type=rescue_type)\
- .values('town__name')\
- .annotate(number=Sum('file__total_surface'))\
- .order_by('-number','town__name')[:10]
- self.rescue['surface_by_dpt'] = FileByDepartment.objects\
- .filter(file__file_type=rescue_type,
- department__isnull=False)\
- .values('department__label')\
- .annotate(number=Sum('file__total_surface'))\
- .order_by('department__label')
-
-class OperationDashboard:
- def __init__(self):
- main_dashboard = Dashboard(Operation)
-
- self.total_number = main_dashboard.total_number
-
- self.filters_keys = ['recorded', 'effective', 'active', 'field',
- 'documented', 'closed', 'documented_closed']
- filters = {
- 'recorded':{},
- 'effective':{'in_charge__isnull':False},
- 'active':{'in_charge__isnull':False, 'end_date__isnull':True},
- 'field':{'excavation_end_date__isnull':True},
- 'documented':{'source__isnull':False},
- 'documented_closed':{'source__isnull':False,
- 'end_date__isnull':False},
- 'closed':{'end_date__isnull':False}
- }
- filters_label = {
- 'recorded':_(u"Recorded"),
- 'effective':_(u"Effective"),
- 'active':_(u"Active"),
- 'field':_(u"Field completed"),
- 'documented':_(u"Associated report"),
- 'closed':_(u"Closed"),
- 'documented_closed':_(u"Documented and closed"),
- }
- self.filters_label = [filters_label[k] for k in self.filters_keys]
- self.total = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- nb = Operation.objects.filter(**fltr).count()
- self.total.append((lbl, nb))
-
- self.surface_by_type = Operation.objects\
- .values('operation_type__label')\
- .annotate(number=Sum('surface'))\
- .order_by('-number','operation_type__label')
-
- self.by_type = []
- self.types = OperationType.objects.filter(available=True).all()
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- type_res = Operation.objects.filter(**fltr).\
- values('operation_type', 'operation_type__label').\
- annotate(number=Count('pk')).\
- order_by('operation_type')
- types_dct = {}
- for typ in type_res.all():
- types_dct[typ['operation_type']] = typ["number"]
- types = []
- for typ in self.types:
- if typ.pk in types_dct:
- types.append(types_dct[typ.pk])
- else:
- types.append(0)
- self.by_type.append((lbl, types))
-
- self.by_year = []
- self.years = [res['year'] for res in Operation.objects.values('year')\
- .order_by('-year').distinct()]
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- year_res = Operation.objects.filter(**fltr).\
- values('year').\
- annotate(number=Count('pk')).\
- order_by('year')
- years_dct = {}
- for yr in year_res.all():
- years_dct[yr['year']] = yr["number"]
- years = []
- for yr in self.years:
- if yr in years_dct:
- years.append(years_dct[yr])
- else:
- years.append(0)
- self.by_year.append((lbl, years))
-
- self.by_realisation_year = []
- self.realisation_years = [res['date'] for res in \
- Operation.objects.extra(
- {'date':"date_trunc('year', start_date)"}).values('date')\
- .filter(start_date__isnull=False).order_by('-date').distinct()]
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- year_res = Operation.objects.filter(**fltr).extra(
- {'date':"date_trunc('year', start_date)"}).values('date').\
- values('date').filter(start_date__isnull=False).\
- annotate(number=Count('pk')).\
- order_by('-date')
- years_dct = {}
- for yr in year_res.all():
- years_dct[yr['date']] = yr["number"]
- years = []
- for yr in self.realisation_years:
- if yr in years_dct:
- years.append(years_dct[yr])
- else:
- years.append(0)
- self.by_realisation_year.append((lbl, years))
-
- self.effective = []
- for typ in self.types:
- year_res = Operation.objects.filter(**{'in_charge__isnull':False,
- 'operation_type':typ}).\
- values('year').\
- annotate(number=Count('pk')).\
- order_by('-year').distinct()
- years_dct = {}
- for yr in year_res.all():
- years_dct[yr['year']] = yr["number"]
- years = []
- for yr in self.years:
- if yr in years_dct:
- years.append(years_dct[yr])
- else:
- years.append(0)
- self.effective.append((typ, years))
-
- # TODO: by date
- now = datetime.date.today()
- limit = datetime.date(now.year, now.month, 1) - datetime.timedelta(365)
- by_realisation_month = Operation.objects.filter(start_date__gt=limit,
- start_date__isnull=False).extra(
- {'date':"date_trunc('month', start_date)"})
- self.last_months = []
- date = datetime.datetime(now.year, now.month, 1)
- for mt_idx in xrange(12):
- self.last_months.append(date)
- if date.month > 1:
- date = datetime.datetime(date.year, date.month - 1, 1)
- else:
- date = datetime.datetime(date.year - 1, 12, 1)
- self.by_realisation_month = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- month_res = by_realisation_month.filter(**fltr).\
- annotate(number=Count('pk')).\
- order_by('-date')
- month_dct = {}
- for mt in month_res.all():
- month_dct[mt.date] = mt.number
- date = datetime.date(now.year, now.month, 1)
- months = []
- for date in self.last_months:
- if date in month_dct:
- months.append(month_dct[date])
- else:
- months.append(0)
- self.by_realisation_month.append((lbl, months))
-
- # survey and excavations
- self.survey, self.excavation = {}, {}
- for dct_res, ope_types in ((self.survey, ('arch_diagnostic',)),
- (self.excavation, ('prev_excavation',
- 'prog_excavation'))):
- dct_res['total'] = []
- operation_type = {'operation_type__txt_idx__in':ope_types}
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- fltr.update(operation_type)
- nb = Operation.objects.filter(**fltr).count()
- dct_res['total'].append((lbl, nb))
-
- dct_res['by_year'] = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- fltr.update(operation_type)
- year_res = Operation.objects.filter(**fltr).\
- values('year').\
- annotate(number=Count('pk')).\
- order_by('year')
- years_dct = {}
- for yr in year_res.all():
- years_dct[yr['year']] = yr["number"]
- years = []
- for yr in self.years:
- if yr in years_dct:
- years.append(years_dct[yr])
- else:
- years.append(0)
- dct_res['by_year'].append((lbl, years))
-
- dct_res['by_realisation_year'] = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- fltr.update(operation_type)
- year_res = Operation.objects.filter(**fltr).extra(
- {'date':"date_trunc('year', start_date)"}).values('date').\
- filter(start_date__isnull=False).\
- annotate(number=Count('pk')).\
- order_by('-date')
- years_dct = {}
- for yr in year_res.all():
- years_dct[yr['date']] = yr["number"]
- years = []
- for yr in self.realisation_years:
- if yr in years_dct:
- years.append(years_dct[yr])
- else:
- years.append(0)
- dct_res['by_realisation_year'].append((lbl, years))
-
- current_year_ope = Operation.objects.filter(**operation_type)\
- .filter(year=datetime.date.today().year)
- current_realisation_year_ope = Operation.objects\
- .filter(**operation_type)\
- .filter(start_date__year=datetime.date.today().year)
- res_keys = [('area_realised', current_realisation_year_ope)]
- if dct_res == self.survey:
- res_keys.append(('area',
- current_year_ope))
- for res_key, base_ope in res_keys:
- dct_res[res_key] = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- area_res = base_ope.filter(**fltr)\
- .annotate(number=Sum('surface')).all()
- val = 0
- if area_res:
- val = area_res[0].number
- dct_res[res_key].append(val)
- # TODO...
- res_keys = [('manday_realised', current_realisation_year_ope)]
- if dct_res == self.survey:
- res_keys.append(('manday',
- current_year_ope))
- for res_key, base_ope in res_keys:
- dct_res[res_key] = []
- for fltr_key in self.filters_keys:
- dct_res[res_key].append('-')
- # TODO...
- res_keys = [('mandayhect_realised', current_realisation_year_ope)]
- if dct_res == self.survey:
- res_keys.append(('mandayhect',
- current_year_ope))
- for res_key, base_ope in res_keys:
- dct_res[res_key] = []
- for fltr_key in self.filters_keys:
- dct_res[res_key].append('-')
- # TODO...
- dct_res['mandayhect_real_effective'] = '-'
- if dct_res == self.survey:
- dct_res['mandayhect_effective'] = '-'
-
-
- res_keys = [('org_realised', current_realisation_year_ope)]
- if dct_res == self.survey:
- res_keys.append(('org', current_year_ope))
- for res_key, base_ope in res_keys:
- org_res = base_ope.filter(in_charge__attached_to__isnull=False)\
- .values('in_charge__attached_to',
- 'in_charge__attached_to__name')\
- .annotate(area=Sum('surface'))\
- .order_by('in_charge__attached_to__name').all()
- # TODO: man-days, man-days/hectare
- dct_res[res_key] = org_res
-
-
- year_ope = Operation.objects.filter(**operation_type)
- res_keys = ['org_by_year']
- if dct_res == self.survey:
- res_keys.append('org_by_year_realised')
- q = year_ope.values('in_charge__attached_to',
- 'in_charge__attached_to__name').\
- filter(in_charge__attached_to__isnull=False).\
- order_by('in_charge__attached_to__name').distinct()
- org_list = [(org['in_charge__attached_to'],
- org['in_charge__attached_to__name']) for org in q]
- org_list_dct = dict(org_list)
- for res_key in res_keys:
- dct_res[res_key] = []
- years = self.years
- if res_key == 'org_by_year_realised':
- years = self.realisation_years
- for org_id, org_label in org_list:
- org_res = year_ope.filter(in_charge__attached_to__pk=org_id)
- key_date = ''
- if res_key == 'org_by_year':
- org_res = org_res.values('year')
- key_date = 'year'
- else:
- org_res = org_res.extra(
- {'date':"date_trunc('year', start_date)"}).values('date').\
- filter(start_date__isnull=False)
- key_date = 'date'
- org_res = org_res.annotate(area=Sum('surface'),
- cost=Sum('cost'))
- years_dct = {}
- for yr in org_res.all():
- area = yr['area'] if yr['area'] else 0
- cost = yr['cost'] if yr['cost'] else 0
- years_dct[yr[key_date]] = (area, cost)
- r_years = []
- for yr in years:
- if yr in years_dct:
- r_years.append(years_dct[yr])
- else:
- r_years.append((0, 0))
- dct_res[res_key].append((org_label, r_years))
- area_means, area_sums = [], []
- cost_means, cost_sums = [], []
- for idx, year in enumerate(years):
- vals = [r_years[idx] for lbl, r_years in dct_res[res_key]]
- sum_area = sum([a for a, c in vals])
- sum_cost = sum([c for a, c in vals])
- area_means.append(sum_area/len(vals))
- area_sums.append(sum_area)
- cost_means.append(sum_cost/len(vals))
- cost_sums.append(sum_cost)
- dct_res[res_key+'_area_mean'] = area_means
- dct_res[res_key+'_area_sum'] = area_sums
- dct_res[res_key+'_cost_mean'] = cost_means
- dct_res[res_key+'_cost_mean'] = cost_sums
-
- if dct_res == self.survey:
- self.survey['effective'] = []
- for yr in self.years:
- year_res = Operation.objects.filter(in_charge__isnull=False,
- year=yr).\
- annotate(number=Sum('surface'),
- mean=Avg('surface'))
- nb = year_res[0].number if year_res.count() else 0
- nb = nb if nb else 0
- mean = year_res[0].mean if year_res.count() else 0
- mean = mean if mean else 0
- self.survey['effective'].append((nb, mean))
-
- # TODO:Man-Days/hectare by Year
-
- # CHECK: month of realisation or month?
- dct_res['by_month'] = []
- for fltr_key in self.filters_keys:
- fltr, lbl = filters[fltr_key], filters_label[fltr_key]
- fltr.update(operation_type)
- month_res = by_realisation_month.filter(**fltr).\
- annotate(number=Count('pk')).\
- order_by('-date')
- month_dct = {}
- for mt in month_res.all():
- month_dct[mt.date] = mt.number
- date = datetime.date(now.year, now.month, 1)
- months = []
- for date in self.last_months:
- if date in month_dct:
- months.append(month_dct[date])
- else:
- months.append(0)
- dct_res['by_month'].append((lbl, months))
-
- operation_type = {'operation_type__txt_idx__in':ope_types}
- self.departments = [(fd['department__pk'], fd['department__label'])
- for fd in OperationByDepartment.objects\
- .filter(department__isnull=False)\
- .values('department__label', 'department__pk')\
- .order_by('department__label').distinct()]
- dct_res['by_dpt'] = []
- for dpt_id, dpt_label in self.departments:
- vals = OperationByDepartment.objects\
- .filter(department__pk=dpt_id,
- operation__operation_type__txt_idx__in=ope_types)\
- .values('department__pk', 'operation__year')\
- .annotate(number=Count('operation'))\
- .order_by('operation__year')
- dct_years = {}
- for v in vals:
- dct_years[v['operation__year']] = v['number']
- years = []
- for y in self.years:
- if y in dct_years:
- years.append(dct_years[y])
- else:
- years.append(0)
- years.append(sum(years))
- dct_res['by_dpt'].append((dpt_label, years))
- dct_res['effective_by_dpt'] = []
- for dpt_id, dpt_label in self.departments:
- vals = OperationByDepartment.objects\
- .filter(department__pk=dpt_id,
- operation__in_charge__isnull=False,
- operation__operation_type__txt_idx__in=ope_types)\
- .values('department__pk', 'operation__year')\
- .annotate(number=Count('operation'),
- area=Sum('operation__surface'),
- fnap=Sum('operation__fnap_cost'),
- cost=Sum('operation__cost'))\
- .order_by('operation__year')
- dct_years = {}
- for v in vals:
- values = []
- for value in (v['number'], v['area'], v['cost'], v['fnap']):
- values.append(value if value else 0)
- dct_years[v['operation__year']] = values
- years = []
- for y in self.years:
- if y in dct_years:
- years.append(dct_years[y])
- else:
- years.append((0, 0, 0, 0))
- nbs, areas, costs, fnaps = zip(*years)
- years.append((sum(nbs), sum(areas), sum(costs), sum(fnaps)))
- dct_res['effective_by_dpt'].append((dpt_label, years))
-
- OperationTown = Operation.towns.through
- query = OperationTown.objects\
- .filter(operation__in_charge__isnull=False,
- operation__operation_type__txt_idx__in=ope_types)\
- .values('town__name', 'town__departement__number')\
- .annotate(nb=Count('operation'))\
- .order_by('-nb', 'town__name')[:10]
- dct_res['towns'] = []
- for r in query:
- dct_res['towns'].append((u"%s (%s)" % (r['town__name'],
- r['town__departement__number']),
- r['nb']))
-
- if dct_res == self.survey:
- query = OperationTown.objects\
- .filter(operation__in_charge__isnull=False,
- operation__operation_type__txt_idx__in=ope_types,
- operation__surface__isnull=False)\
- .values('town__name', 'town__departement__number')\
- .annotate(nb=Sum('operation__surface'))\
- .order_by('-nb', 'town__name')[:10]
- dct_res['towns_surface'] = []
- for r in query:
- dct_res['towns_surface'].append((u"%s (%s)" % (
- r['town__name'], r['town__departement__number']),
- r['nb']))
- else:
- query = OperationTown.objects\
- .filter(operation__in_charge__isnull=False,
- operation__operation_type__txt_idx__in=ope_types,
- operation__cost__isnull=False)\
- .values('town__name', 'town__departement__number')\
- .annotate(nb=Sum('operation__cost'))\
- .order_by('-nb', 'town__name')[:10]
- dct_res['towns_cost'] = []
- for r in query:
- dct_res['towns_cost'].append((u"%s (%s)" % (r['town__name'],
- r['town__departement__number']),
- r['nb']))
-
-class Dashboard:
- def __init__(self, model):
- self.model = model
- self.total_number = model.get_total_number()
- history_model = self.model.history.model
- # last edited - created
- self.recents, self.lasts = [], []
- for last_lst, modif_type in ((self.lasts, '+'), (self.recents, '~')):
- last_ids = history_model.objects.values('id')\
- .annotate(hd=Max('history_date'))
- last_ids = last_ids.filter(history_type=modif_type)
- if self.model == Item:
- last_ids = last_ids.filter(downstream_treatment_id__isnull=True)
- if modif_type == '+':
- last_ids = last_ids.filter(upstream_treatment_id__isnull=True)
- last_ids = last_ids.order_by('-hd').distinct().all()[:5]
- for idx in last_ids:
- try:
- obj = self.model.objects.get(pk=idx['id'])
- except:
- # deleted object are always referenced in history
- continue
- obj.history_date = idx['hd']
- last_lst.append(obj)
- # years
- self.years = model.get_years()
- self.years.sort()
- if not self.total_number or not self.years:
- return
- self.values = [('year', _(u"Year"), reversed(self.years))]
- # numbers
- self.numbers = [model.get_by_year(year).count() for year in self.years]
- self.values += [('number', _(u"Number"), reversed(self.numbers))]
- # calculate
- self.average = self.get_average()
- self.variance = self.get_variance()
- self.standard_deviation = self.get_standard_deviation()
- self.median = self.get_median()
- self.mode = self.get_mode()
- # by operation
- if not hasattr(model, 'get_by_operation'):
- return
- operations = model.get_operations()
- operation_numbers = [model.get_by_operation(op).count()
- for op in operations]
- # calculate
- self.operation_average = self.get_average(operation_numbers)
- self.operation_variance = self.get_variance(operation_numbers)
- self.operation_standard_deviation = self.get_standard_deviation(
- operation_numbers)
- self.operation_median = self.get_median(operation_numbers)
- operation_mode_pk = self.get_mode(dict(zip(operations,
- operation_numbers)))
- if operation_mode_pk:
- self.operation_mode = unicode(Operation.objects.get(
- pk=operation_mode_pk))
-
- def get_average(self, vals=[]):
- if not vals:
- vals = self.numbers
- return sum(vals)/len(vals)
-
- def get_variance(self, vals=[]):
- if not vals:
- vals = self.numbers
- avrg = self.get_average(vals)
- return self.get_average([(x-avrg)**2 for x in vals])
-
- def get_standard_deviation(self, vals=[]):
- if not vals:
- vals = self.numbers
- return round(self.get_variance(vals)**0.5, 3)
-
- def get_median(self, vals=[]):
- if not vals:
- vals = self.numbers
- len_vals = len(vals)
- vals.sort()
- if (len_vals % 2) == 1:
- return vals[len_vals/2]
- else:
- return (vals[len_vals/2-1] + vals[len_vals/2])/2.0
-
- def get_mode(self, vals={}):
- if not vals:
- vals = dict(zip(self.years, self.numbers))
- mx = max(vals.values())
- for v in vals:
- if vals[v] == mx:
- return v
-
-class Departement(models.Model):
- label = models.CharField(_(u"Label"), max_length=30)
- number = models.CharField(_(u"Number"), unique=True, max_length=3)
-
- class Meta:
- verbose_name = _(u"Departement")
- verbose_name_plural = _(u"Departements")
- ordering = ['number']
-
- def __unicode__(self):
- return unicode(self.number) + JOINT + self.label
-
-class Address(BaseHistorizedItem):
- address = models.TextField(_(u"Address"), null=True, blank=True)
- address_complement = models.TextField(_(u"Address complement"), null=True,
- blank=True)
- postal_code = models.CharField(_(u"Postal code"), max_length=10, null=True,
- blank=True)
- town = models.CharField(_(u"Town"), max_length=30, null=True, blank=True)
- country = models.CharField(_(u"Country"), max_length=30, null=True,
- blank=True)
- phone = models.CharField(_(u"Phone"), max_length=18, null=True, blank=True)
- mobile_phone = models.CharField(_(u"Mobile phone"), max_length=18,
- null=True, blank=True)
- history = HistoricalRecords()
-
- class Meta:
- abstract = True
-
-class OrganizationType(GeneralType):
- class Meta:
- verbose_name = _(u"Organization type")
- verbose_name_plural = _(u"Organization types")
-
-class Organization(Address, OwnPerms):
- name = models.CharField(_(u"Name"), max_length=100)
- organization_type = models.ForeignKey(OrganizationType,
- verbose_name=_(u"Type"))
- history = HistoricalRecords()
- class Meta:
- verbose_name = _(u"Organization")
- verbose_name_plural = _(u"Organizations")
- permissions = (
- ("view_own_organization", ugettext(u"Can view own Organization")),
- ("add_own_organization", ugettext(u"Can add own Organization")),
- ("change_own_organization", ugettext(u"Can change own Organization")),
- ("delete_own_organization", ugettext(u"Can delete own Organization")),
- )
-
- def __unicode__(self):
- return self.name
-
-class PersonType(GeneralType):
- rights = models.ManyToManyField(WizardStep, verbose_name=_(u"Rights"))
- class Meta:
- verbose_name = _(u"Person type")
- verbose_name_plural = _(u"Person types")
-
-class Person(Address, OwnPerms) :
- TYPE = (('Mr', _(u'Mr')),
- ('Ms', _(u'Miss')),
- ('Md', _(u'Mrs')),
- ('Dr', _(u'Doctor')),
- )
- title = models.CharField(_(u"Title"), max_length=2, choices=TYPE)
- surname = models.CharField(_(u"Surname"), max_length=20)
- name = models.CharField(_(u"Name"), max_length=30)
- email = models.CharField(_(u"Email"), max_length=40, blank=True, null=True)
- person_type = models.ForeignKey(PersonType, verbose_name=_(u"Type"))
- attached_to = models.ForeignKey('Organization',
- verbose_name=_(u"Is attached to"), blank=True, null=True)
-
- class Meta:
- verbose_name = _(u"Person")
- verbose_name_plural = _(u"Persons")
- permissions = (
- ("view_person", ugettext(u"Can view Person")),
- ("view_own_person", ugettext(u"Can view own Person")),
- ("add_own_person", ugettext(u"Can add own Person")),
- ("change_own_person", ugettext(u"Can change own Person")),
- ("delete_own_person", ugettext(u"Can delete own Person")),
- )
-
- def __unicode__(self):
- lbl = u"%s %s" % (self.name, self.surname)
- lbl += JOINT
- if self.attached_to:
- lbl += unicode(self.attached_to)
- elif self.email:
- lbl += self.email
- return lbl
-
- def full_label(self):
- return u" ".join([unicode(getattr(self, attr))
- for attr in ('title', 'surname', 'name', 'attached_to')
- if getattr(self, attr)])
-
-class IshtarUser(User):
- person = models.ForeignKey(Person, verbose_name=_(u"Person"), unique=True)
-
- class Meta:
- verbose_name = _(u"Ishtar user")
- verbose_name_plural = _(u"Ishtar users")
-
-class AuthorType(GeneralType):
- class Meta:
- verbose_name = _(u"Author type")
- verbose_name_plural = _(u"Author types")
-
-class Author(models.Model):
- person = models.ForeignKey(Person, verbose_name=_(u"Person"))
- author_type = models.ForeignKey(AuthorType, verbose_name=_(u"Author type"))
-
- class Meta:
- verbose_name = _(u"Author")
- verbose_name_plural = _(u"Authors")
-
- def __unicode__(self):
- return unicode(self.person) + JOINT + unicode(self.author_type)
-
-class SourceType(GeneralType):
- class Meta:
- verbose_name = _(u"Source type")
- verbose_name_plural = _(u"Source types")
-
-class Source(models.Model):
- title = models.CharField(_(u"Title"), max_length=200)
- source_type = models.ForeignKey(SourceType, verbose_name=_(u"Type"))
- authors = models.ManyToManyField(Author, verbose_name=_(u"Authors"))
- associated_url = models.URLField(verify_exists=False, blank=True, null=True,
- verbose_name=_(u"Numerical ressource (web address)"))
- receipt_date = models.DateField(blank=True, null=True,
- verbose_name=_(u"Receipt date"))
- creation_date = models.DateField(blank=True, null=True,
- verbose_name=_(u"Creation date"))
- TABLE_COLS = ['title', 'source_type', 'authors',]
-
- class Meta:
- abstract = True
-
- def __unicode__(self):
- return self.title
-
-class FileType(GeneralType):
- class Meta:
- verbose_name = _(u"Archaeological file type")
- verbose_name_plural = _(u"Archaeological file types")
-
- @classmethod
- def is_preventive(cls, file_type_id, key=''):
- key = key or 'preventive'
- try:
- preventive = FileType.objects.get(txt_idx=key).pk
- return file_type_id == preventive
- except ObjectDoesNotExist:
- return False
-
-class PermitType(GeneralType):
- class Meta:
- verbose_name = _(u"Permit type")
- verbose_name_plural = _(u"Permit types")
-
-if settings.COUNTRY == 'fr':
- class SaisineType(GeneralType):
- delay = models.IntegerField(_(u"Delay (in days)"))
- class Meta:
- verbose_name = u"Type Saisine"
- verbose_name_plural = u"Types Saisine"
-
-class File(BaseHistorizedItem, OwnPerms):
- TABLE_COLS = ['numeric_reference', 'year', 'internal_reference',
- 'file_type', 'saisine_type', 'towns', ]
- year = models.IntegerField(_(u"Year"),
- default=lambda:datetime.datetime.now().year)
- numeric_reference = models.IntegerField(_(u"Numeric reference"))
- internal_reference = models.CharField(_(u"Internal reference"),
- max_length=60, unique=True)
- file_type = models.ForeignKey(FileType, verbose_name=_(u"File type"))
- in_charge = models.ForeignKey(Person, related_name='+',
- verbose_name=_(u"Person in charge"))
- general_contractor = models.ForeignKey(Person, related_name='+',
- verbose_name=_(u"General contractor"), blank=True, null=True)
- town_planning_service = models.ForeignKey(Organization, related_name='+',
- verbose_name=_(u"Town planning service"), blank=True, null=True)
- permit_type = models.ForeignKey(PermitType, verbose_name=_(u"Permit type"),
- blank=True, null=True)
- permit_reference = models.CharField(_(u"Permit reference"),
- max_length=60, blank=True, null=True)
- end_date = models.DateField(_(u"Closing date"), null=True, blank=True)
- towns = models.ManyToManyField("Town", verbose_name=_(u"Towns"),
- related_name='file')
- creation_date = models.DateField(_(u"Creation date"),
- default=datetime.date.today)
- reception_date = models.DateField(_(u'Reception date'), blank=True,
- null=True)
- related_file = models.ForeignKey("File", verbose_name=_(u"Related file"),
- blank=True, null=True)
- if settings.COUNTRY == 'fr':
- saisine_type = models.ForeignKey(SaisineType, blank=True, null=True,
- verbose_name= u"Type de saisine")
- reference_number = models.IntegerField(_(u"Reference number"),
- blank=True, null=True)
- total_surface = models.IntegerField(_(u"Total surface (m²)"),
- blank=True, null=True)
- total_developed_surface = models.IntegerField(
- _(u"Total developed surface (m²)"), blank=True, null=True)
- address = models.TextField(_(u"Main address"), null=True, blank=True)
- address_complement = models.TextField(_(u"Main address - complement"),
- null=True, blank=True)
- postal_code = models.CharField(_(u"Main address - postal code"),
- max_length=10, null=True, blank=True)
- comment = models.TextField(_(u"Comment"), null=True, blank=True)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Archaeological file")
- verbose_name_plural = _(u"Archaeological files")
- permissions = (
- ("view_own_file", ugettext(u"Can view own Archaelogical file")),
- ("add_own_file", ugettext(u"Can add own Archaelogical file")),
- ("change_own_file", ugettext(u"Can change own Archaelogical file")),
- ("delete_own_file", ugettext(u"Can delete own Archaelogical file")),
- )
- ordering = ['-year', '-numeric_reference']
-
- @classmethod
- def get_years(cls):
- return [res['year'] for res in list(cls.objects.values('year').annotate(
- Count("id")).order_by())]
-
- @classmethod
- def get_by_year(cls, year):
- return cls.objects.filter(year=year)
-
- @classmethod
- def get_total_number(cls):
- return cls.objects.count()
-
- def __unicode__(self):
- items = [unicode(_('Intercommunal'))]
- if self.towns.count() == 1:
- items[0] = unicode(self.towns.all()[0])
- items.append("-".join((unicode(self.year),
- unicode(self.numeric_reference))))
- items += [unicode(getattr(self, k))[:36]
- for k in ['internal_reference',] if getattr(self, k)]
- return JOINT.join(items)
-
- @classmethod
- def get_query_owns(cls, user):
- return Q(history_modifier=user) & Q(end_date__isnull=True)
-
- def is_active(self):
- return not bool(self.end_date)
-
- def closing(self):
- if self.is_active():
- return
- for item in self.history.all():
- if not item.end_date:
- break
- return {'date':item.history_date,
- 'user':IshtarUser.objects.get(pk=item.history_modifier_id)}
-
- def total_surface_ha(self):
- if self.total_surface:
- return self.total_surface/10000.0
-
- def total_developed_surface_ha(self):
- if self.total_developed_surface:
- return self.total_developed_surface/10000.0
-
- def operation_acts(self):
- acts = []
- for ope in self.operations.all():
- for act in ope.administrative_act.all():
- acts.append(act)
- return acts
-
- def is_preventive(self):
- return FileType.is_preventive(self.file_type.pk)
-
-class FileByDepartment(models.Model):
- '''
- Database view: don't forget to create it
-
- create view file_department (id, department_id, file_id) as
- select town."id", town."departement_id", file_towns."file_id"
- from ishtar_base_town town
- inner join ishtar_base_file_towns file_towns on
- file_towns."town_id"=town."id" order by town."departement_id";
- CREATE RULE file_department_delete
- AS ON DELETE TO file_department DO INSTEAD();
- '''
- file = models.ForeignKey(File, verbose_name=_(u"File"))
- department = models.ForeignKey(Departement, verbose_name=_(u"Department"),
- blank=True, null=True)
- class Meta:
- managed = False
- db_table = 'file_department'
-
-class OperationType(GeneralType):
- class Meta:
- verbose_name = _(u"Operation type")
- verbose_name_plural = _(u"Operation types")
-
- @classmethod
- def is_preventive(cls, ope_type_id, key=''):
- key = key or 'prev_excavation'
- try:
- preventive = OperationType.objects.get(txt_idx=key).pk
- return ope_type_id == preventive
- except ObjectDoesNotExist:
- return False
-
-class RemainType(GeneralType):
- class Meta:
- verbose_name = _(u"Remain type")
- verbose_name_plural = _(u"Remain types")
-
-class Operation(BaseHistorizedItem, OwnPerms):
- TABLE_COLS = ['year_index', 'operation_type', 'remains', 'towns',
- 'associated_file', 'start_date', 'excavation_end_date']
- start_date = models.DateField(_(u"Start date"), null=True, blank=True)
- excavation_end_date = models.DateField(_(u"Excavation end date"), null=True,
- blank=True)
- end_date = models.DateField(_(u"Closing date"), null=True, blank=True)
- in_charge = models.ForeignKey('Person', related_name='+', null=True,
- blank=True, verbose_name=_(u"In charge"))
- year = models.IntegerField(_(u"Year"))
- operation_code = models.IntegerField(_(u"Operation code"))
- associated_file = models.ForeignKey(File, related_name='operations',
- verbose_name=_(u"File"), blank=True, null=True)
- operation_type = models.ForeignKey(OperationType, related_name='+',
- verbose_name=_(u"Operation type"))
- surface = models.IntegerField(_(u"Surface (m²)"), blank=True, null=True)
- remains = models.ManyToManyField("RemainType", verbose_name=_(u'Remains'))
- towns = models.ManyToManyField("Town", verbose_name=_(u"Towns"))
- cost = models.IntegerField(_(u"Cost (€)"), blank=True, null=True)
- periods = models.ManyToManyField('Period', verbose_name=_(u"Periods"))
- scheduled_man_days = models.IntegerField(_(u"Scheduled man-days"),
- blank=True, null=True)
- optional_man_days = models.IntegerField(_(u"Optional man-days"),
- blank=True, null=True)
- effective_man_days = models.IntegerField(_(u"Effective man-days"),
- blank=True, null=True)
- if settings.COUNTRY == 'fr':
- code_patriarche = models.IntegerField(u"Code PATRIARCHE", null=True,
- blank=True)
- TABLE_COLS = ['code_patriarche'] + TABLE_COLS
- code_dracar = models.CharField(u"Code DRACAR", max_length=10, null=True,
- blank=True)
- fnap_financing = models.FloatField(u"Financement FNAP (%)",
- blank=True, null=True)
- fnap_cost = models.IntegerField(u"Financement FNAP (€)",
- blank=True, null=True)
- zoning_prescription = models.NullBooleanField(
- _(u"Prescription on zoning"), blank=True, null=True)
- large_area_prescription = models.NullBooleanField(
- _(u"Prescription on large area"), blank=True, null=True)
- geoarchaeological_context_prescription = models.NullBooleanField(
- _(u"Prescription on geoarchaeological context"), blank=True, null=True)
- operator_reference = models.CharField(_(u"Operator reference"),
- max_length=20, null=True, blank=True)
- common_name = models.CharField(_(u"Generic name"), max_length=120, null=True,
- blank=True)
- comment = models.TextField(_(u"Comment"), null=True, blank=True)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Operation")
- verbose_name_plural = _(u"Operations")
- permissions = (
- ("view_own_operation", ugettext(u"Can view own Operation")),
- ("add_own_operation", ugettext(u"Can add own Operation")),
- ("change_own_operation", ugettext(u"Can change own Operation")),
- ("delete_own_operation", ugettext(u"Can delete own Operation")),
- )
-
- def __unicode__(self):
- items = [unicode(_('Intercommunal'))]
- if self.towns.count() == 1:
- items[0] = unicode(self.towns.all()[0])
- items.append("-".join((unicode(self.year),
- unicode(self.operation_code))))
- return JOINT.join(items)
-
- @classmethod
- def get_available_operation_code(cls, year=None):
- if not year:
- year = datetime.date.today().year
- max_val = cls.objects.filter(year=year).aggregate(
- Max('operation_code'))["operation_code__max"]
- return (max_val + 1) if max_val else 1
-
- @classmethod
- def get_years(cls):
- return [res['year'] for res in list(cls.objects.values('year').annotate(
- Count("id")).order_by())]
-
- @classmethod
- def get_by_year(cls, year):
- return cls.objects.filter(year=year)
-
- @classmethod
- def get_total_number(cls):
- return cls.objects.count()
-
- year_index_lbl = _(u"Operation code")
- @property
- def year_index(self):
- lbl = unicode(self.operation_code)
- lbl = u"%d-%s%s" % (self.year, (3-len(lbl))*"0", lbl)
- return lbl
-
- def clean(self):
- objs = self.__class__.objects.filter(year=self.year,
- operation_code=self.operation_code)
- if self.pk:
- objs = objs.exclude(pk=self.pk)
- if objs.count():
- raise ValidationError(_(u"This operation code already exists for "
- u"this year"))
-
- def is_own(self, person):
- return False
-
- @property
- def surface_ha(self):
- if self.surface:
- return self.surface/10000.0
-
- @property
- def cost_by_m2(self):
- if not self.surface or not self.cost:
- return
- return round(float(self.cost)/self.surface, 2)
-
- @property
- def cost_by_m2(self):
- if not self.surface or not self.cost:
- return
- return round(float(self.cost)/self.surface, 2)
-
- @classmethod
- def get_query_owns(cls, user):
- return Q(in_charge=user.person)|Q(history_modifier=user)\
- & Q(end_date__isnull=True)
-
- def is_active(self):
- return not bool(self.end_date)
-
- def closing(self):
- if self.is_active():
- return
- for item in self.history.all():
- if not item.end_date:
- break
- return {'date':item.history_date,
- 'user':IshtarUser.objects.get(pk=item.history_modifier_id)}
-
-def operation_post_save(sender, **kwargs):
- if not kwargs['instance']:
- return
- operation = kwargs['instance']
- if operation.fnap_financing and operation.cost:
- fnap_cost = int(float(operation.cost)/100*operation.fnap_financing)
- if not operation.fnap_cost or operation.fnap_cost != fnap_cost:
- operation.fnap_cost = fnap_cost
- operation.save()
- elif operation.fnap_cost and operation.cost:
- fnap_percent = float(operation.fnap_cost)*100/operation.cost
- operation.fnap_financing = fnap_percent
- operation.save()
-post_save.connect(operation_post_save, sender=Operation)
-
-class OperationByDepartment(models.Model):
- '''
- Database view: don't forget to create it
-
- create view operation_department (id, department_id, operation_id) as
- select town."id", town."departement_id", operation_towns."operation_id"
- from ishtar_base_town town
- inner join ishtar_base_operation_towns operation_towns on
- operation_towns."town_id"=town."id" order by town."departement_id";
- CREATE RULE operation_department_delete
- AS ON DELETE TO operation_department DO INSTEAD();
- '''
- operation = models.ForeignKey(Operation, verbose_name=_(u"Operation"))
- department = models.ForeignKey(Departement, verbose_name=_(u"Department"),
- blank=True, null=True)
- class Meta:
- managed = False
- db_table = 'operation_department'
-
-class OperationSource(Source):
- class Meta:
- verbose_name = _(u"Operation documentation")
- verbose_name_plural = _(u"Operation documentations")
- operation = models.ForeignKey(Operation, verbose_name=_(u"Operation"),
- related_name="source")
- index = models.IntegerField(verbose_name=_(u"Index"))
- TABLE_COLS = ['operation.year', 'operation.operation_code'] + \
- Source.TABLE_COLS
-
-class Parcel(LightHistorizedItem):
- associated_file = models.ForeignKey(File, related_name='parcels',
- blank=True, null=True, verbose_name=_(u"File"))
- operation = models.ForeignKey(Operation, related_name='parcels', blank=True,
- null=True, verbose_name=_(u"Operation"))
- year = models.IntegerField(_(u"Year"), blank=True, null=True)
- town = models.ForeignKey("Town", related_name='parcels',
- verbose_name=_(u"Town"))
- section = models.CharField(_(u"Section"), max_length=4)
- parcel_number = models.CharField(_(u"Parcel number"), max_length=6)
-
- class Meta:
- verbose_name = _(u"Parcel")
- verbose_name_plural = _(u"Parcels")
-
- def short_label(self):
- return JOINT.join([unicode(item) for item in [self.section,
- self.parcel_number] if item])
-
- def __unicode__(self):
- return self.short_label()
-
- def long_label(self):
- items = [unicode(self.operation or self.associated_file)]
- items += [unicode(item) for item in [self.section, self.parcel_number]
- if item]
- return JOINT.join(items)
-
-class Period(GeneralType) :
- order = models.IntegerField(_(u"Order"))
- start_date = models.IntegerField(_(u"Start date"))
- end_date = models.IntegerField(_(u"End date"))
- parent = models.ForeignKey("Period", verbose_name=_(u"Parent period"),
- blank=True, null=True)
-
- class Meta:
- verbose_name = _(u"Type Period")
- verbose_name_plural = _(u"Types Period")
-
- def __unicode__(self):
- return self.label
-
-class DatingType(GeneralType):
- class Meta:
- verbose_name = _(u"Dating type")
- verbose_name_plural = _(u"Dating types")
-
-class DatingQuality(GeneralType):
- class Meta:
- verbose_name = _(u"Dating quality")
- verbose_name_plural = _(u"Dating qualities")
-
-class Dating(models.Model):
- period = models.ForeignKey(Period, verbose_name=_(u"Period"))
- start_date = models.IntegerField(_(u"Start date"), blank=True, null=True)
- end_date = models.IntegerField(_(u"End date"), blank=True, null=True)
- dating_type = models.ForeignKey(DatingType, verbose_name=_(u"Dating type"),
- blank=True, null=True)
- quality = models.ForeignKey(DatingQuality, verbose_name=_(u"Quality"),
- blank=True, null=True)
-
- class Meta:
- verbose_name = _(u"Dating")
- verbose_name_plural = _(u"Datings")
-
- def __unicode__(self):
- start_date = self.start_date and unicode(self.start_date) or u""
- end_date = self.end_date and unicode(self.end_date) or u""
- if not start_date and not end_date:
- return unicode(self.period)
- return u"%s (%s-%s)" % (self.period, start_date, end_date)
-
-class Unit(GeneralType):
- order = models.IntegerField(_(u"Order"))
- parent = models.ForeignKey("Unit", verbose_name=_(u"Parent unit"),
- blank=True, null=True)
-
- class Meta:
- verbose_name = _(u"Type Unit")
- verbose_name_plural = _(u"Types Unit")
-
- def __unicode__(self):
- return self.label
-
-class ActivityType(GeneralType):
- order = models.IntegerField(_(u"Order"))
-
- class Meta:
- verbose_name = _(u"Type Activity")
- verbose_name_plural = _(u"Types Activity")
-
- def __unicode__(self):
- return self.label
-
-class IdentificationType(GeneralType):
- order = models.IntegerField(_(u"Order"))
- class Meta:
- verbose_name = _(u"Type Identification")
- verbose_name_plural = _(u"Types Identification")
-
- def __unicode__(self):
- return self.label
-
-class ContextRecord(BaseHistorizedItem, OwnPerms):
- TABLE_COLS = ['parcel.town', 'operation.year',
- 'operation.operation_code',
- 'label', 'unit']
- if settings.COUNTRY == 'fr':
- TABLE_COLS.insert(1, 'parcel.operation.code_patriarche')
- parcel = models.ForeignKey(Parcel, verbose_name=_(u"Parcel"),
- related_name='context_record')
- operation = models.ForeignKey(Operation, verbose_name=_(u"Operation"),
- related_name='context_record')
- label = models.CharField(_(u"ID"), max_length=200)
- description = models.TextField(_(u"Description"), blank=True, null=True)
- length = models.IntegerField(_(u"Length (cm)"), blank=True, null=True)
- width = models.IntegerField(_(u"Width (cm)"), blank=True, null=True)
- thickness = models.IntegerField(_(u"Thickness (cm)"), blank=True, null=True)
- depth = models.IntegerField(_(u"Depth (cm)"), blank=True, null=True)
- location = models.CharField(_(u"Location"), blank=True, null=True,
- max_length=200,
- help_text=_(u"A short description of the location of the context record"))
- datings = models.ManyToManyField(Dating)
- unit = models.ForeignKey(Unit, verbose_name=_(u"Unit"), related_name='+',
- blank=True, null=True)
- has_furniture = models.NullBooleanField(u"Has furniture?", blank=True,
- null=True)
- filling = models.TextField(_(u"Filling"), blank=True, null=True)
- interpretation = models.TextField(_(u"Interpretation"), blank=True,
- null=True)
- taq = models.IntegerField(_(u"TAQ"), blank=True, null=True,
- help_text=_(u"\"Terminus Ante Quem\" the context record can't have been "
- "created after this date"))
- taq_estimated = models.IntegerField(_(u"Estimated TAQ"), blank=True,
- null=True, help_text=_(u"Estimation of a \"Terminus Ante Quem\""))
- tpq = models.IntegerField(_(u"TPQ"), blank=True, null=True,
- help_text=_(u"\"Terminus Post Quem\" the context record can't have been "
- " created before this date"))
- tpq_estimated = models.IntegerField(_(u"Estimated TPQ"), blank=True,
- null=True, help_text=_(u"Estimation of a \"Terminus Post Quem\""))
- identification = models.ForeignKey(IdentificationType, blank=True,
- null=True, verbose_name=_(u"Identification"),)
- activity = models.ForeignKey(ActivityType,blank=True, null=True,
- verbose_name=_(u"Activity"),)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Context Record")
- verbose_name_plural = _(u"Context Record")
- permissions = (
- ("view_own_contextrecord", ugettext(u"Can view own Context Record")),
- ("add_own_contextrecord", ugettext(u"Can add own Context Record")),
- ("change_own_contextrecord", ugettext(u"Can change own Context Record")),
- ("delete_own_contextrecord", ugettext(u"Can delete own Context Record")),
- )
-
- def __unicode__(self):
- return self.short_label()
-
- def short_label(self):
- return JOINT.join([unicode(item) for item in [self.parcel,
- self.label] if item])
-
- def full_label(self):
- if not self.parcel.operation:
- return unicode(self)
- return self._real_label() or self._temp_label()
-
- def _real_label(self):
- if not self.parcel.operation.code_patriarche:
- return
- return JOINT.join((self.parcel.operation.code_patriarche,
- self.label))
-
- def _temp_label(self):
- if self.parcel.operation.code_patriarche:
- return
- return JOINT.join([unicode(lbl) for lbl in [self.parcel.operation.year,
- self.parcel.operation.operation_code,
- self.label] if lbl])
-
- @classmethod
- def get_years(cls):
- years = set()
- for res in list(cls.objects.values('operation__start_date')):
- yr = res['operation__start_date'].year
- years.add(yr)
- return list(years)
-
- @classmethod
- def get_by_year(cls, year):
- return cls.objects.filter(operation__start_date__year=year)
-
- @classmethod
- def get_operations(cls):
- return [dct['operation__pk']
- for dct in cls.objects.values('operation__pk').distinct()]
-
- @classmethod
- def get_by_operation(cls, operation_id):
- return cls.objects.filter(operation__pk=operation_id)
-
- @classmethod
- def get_total_number(cls):
- return cls.objects.filter(operation__start_date__isnull=False).count()
-
-class ContextRecordSource(Source):
- class Meta:
- verbose_name = _(u"Context record documentation")
- verbose_name_plural = _(u"Context record documentations")
- context_record = models.ForeignKey(ContextRecord,
- verbose_name=_(u"Context record"), related_name="source")
-
-class MaterialType(GeneralType):
- recommendation = models.TextField(_(u"Recommendation"))
- parent = models.ForeignKey("MaterialType", blank=True, null=True,
- verbose_name=_(u"Parent material"))
-
- class Meta:
- verbose_name = _(u"Material type")
- verbose_name_plural = _(u"Material types")
-
-class BaseItem(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"))
- is_isolated = models.NullBooleanField(_(u"Is isolated?"), blank=True,
- null=True)
- index = models.IntegerField(u"Index", default=0)
- material_index = models.IntegerField(u"Material index", default=0)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Base item")
- verbose_name_plural = _(u"Base items")
- 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")),
- )
-
- 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 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 '']
- ope = self.context_record.operation
- items += [ope.code_patriarche or \
- (unicode(ope.year) + "-" + unicode(ope.operation_code))]
- items += [self.context_record.label, unicode(self.material_index)]
- return JOINT.join(items)
-
- 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
- return JOINT.join([unicode(it) for it in (
- self.context_record.parcel.operation.code_patriarche,
- self.context_record.label,
- lbl) if it])
-
- def _temp_label(self):
- if self.context_record.parcel.operation.code_patriarche:
- return
- item = self.get_last_item()
- lbl = item.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):
- 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']
- 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')
- order = models.IntegerField(_(u"Order"))
- label = models.CharField(_(u"ID"), max_length=60)
- description = models.TextField(_(u"Description"), blank=True, null=True)
- material_type = models.ForeignKey(MaterialType,
- 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)
- 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,
- related_name='upstream_treatment', verbose_name=_("Downstream treatment"))
- dating = models.ForeignKey(Dating, verbose_name=_(u"Dating"))
- container = models.ForeignKey('Container', verbose_name=_(u"Container"),
- blank=True, null=True, related_name='items')
- 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()
- if not bi:
- continue
- bi = bi[0]
- yr = bi.context_record.operation.start_date.year
- years.add(yr)
- return list(years)
-
- @classmethod
- def get_by_year(cls, year):
- return cls.objects.filter(downstream_treatment__isnull=True,
- base_items__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()
- if not bi:
- continue
- bi = bi[0]
- pk = bi.context_record.operation.pk
- operations.add(pk)
- return list(operations)
-
- @classmethod
- def get_by_operation(cls, operation_id):
- return cls.objects.filter(downstream_treatment__isnull=True,
- base_items__context_record__operation__pk=operation_id)
-
- @classmethod
- def get_total_number(cls):
- return cls.objects.filter(downstream_treatment__isnull=True).count()
-
- def duplicate(self, user):
- dct = dict([(attr, getattr(self, attr)) for attr in ('order', 'label',
- 'description', 'material_type', 'volume', 'weight',
- 'item_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)
- return new
-
- class Meta:
- verbose_name = _(u"Item")
- verbose_name_plural = _(u"Items")
- 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")),
- )
-
- def __unicode__(self):
- return self.label
-
- 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(
- Max('material_index'))
- base_item.material_index = idx and \
- idx['material_index__max'] + 1 or 1
- base_item.save()
- super(Item, self).save(*args, **kwargs)
-
-class ItemSource(Source):
- class Meta:
- verbose_name = _(u"Item documentation")
- verbose_name_plural = _(u"Item documentations")
- item = models.ForeignKey(Item, verbose_name=_(u"Item"),
- related_name="source")
-
-class ParcelOwner(LightHistorizedItem):
- owner = models.ForeignKey(Person, verbose_name=_(u"Owner"))
- parcel = models.ForeignKey(Parcel, verbose_name=_(u"Parcel"))
- start_date = models.DateField(_(u"Start date"))
- end_date = models.DateField(_(u"End date"))
-
- class Meta:
- verbose_name = _(u"Parcel owner")
- verbose_name_plural = _(u"Parcel owners")
-
- def __unicode__(self):
- return self.owner + JOINT + self.parcel
-
-class WarehouseType(GeneralType):
- class Meta:
- verbose_name = _(u"Warehouse type")
- verbose_name_plural = _(u"Warehouse types")
-
-class Warehouse(Address, OwnPerms):
- name = models.CharField(_(u"Name"), max_length=40)
- warehouse_type = models.ForeignKey(WarehouseType,
- verbose_name=_(u"Warehouse type"))
- person_in_charge = models.ForeignKey(Person,
- verbose_name=_(u"Person in charge"), null=True, blank=True)
- comment = models.TextField(_(u"Comment"), null=True, blank=True)
-
- class Meta:
- verbose_name = _(u"Warehouse")
- verbose_name_plural = _(u"Warehouses")
- permissions = (
- ("view_own_warehouse", ugettext(u"Can view own Warehouse")),
- ("add_own_warehouse", ugettext(u"Can add own Warehouse")),
- ("change_own_warehouse", ugettext(u"Can change own Warehouse")),
- ("delete_own_warehouse", ugettext(u"Can delete own Warehouse")),
- )
-
- def __unicode__(self):
- return u"%s (%s)" % (self.name, unicode(self.warehouse_type))
-
-class ActType(GeneralType):
- TYPE = (('F', _(u'Archaelogical file')),
- ('O', _(u'Operation')),
- )
- intented_to = models.CharField(_(u"Intended to"), max_length=1,
- choices=TYPE)
- class Meta:
- verbose_name = _(u"Act type")
- verbose_name_plural = _(u"Act types")
-
-class AdministrativeAct(BaseHistorizedItem, OwnPerms):
- TABLE_COLS = ['act_type', 'associated_file', 'operation',
- 'associated_file.towns', 'operation.towns']
- TABLE_COLS_FILE = ['act_type', 'associated_file', 'associated_file.towns',]
- TABLE_COLS_OPE = ['act_type', 'operation', 'operation.towns']
- act_type = models.ForeignKey(ActType, verbose_name=_(u"Act type"))
- in_charge = models.ForeignKey(Person, blank=True, null=True,
- related_name='+', verbose_name=_(u"Person in charge of the operation"))
- operator = models.ForeignKey(Organization, blank=True, null=True,
- verbose_name=_(u"Archaeological preventive operator"))
- scientific = models.ForeignKey(Person, blank=True, null=True,
-related_name='+', verbose_name=_(u"Person in charge of the scientific part"))
- signatory = models.ForeignKey(Person, blank=True, null=True,
- related_name='+', verbose_name=_(u"Signatory"))
- operation = models.ForeignKey(Operation, blank=True, null=True,
- related_name='administrative_act', verbose_name=_(u"Operation"))
- associated_file = models.ForeignKey(File, blank=True, null=True,
- related_name='administrative_act', verbose_name=_(u"Archaelogical file"))
- signature_date = models.DateField(_(u"Signature date"), blank=True,
- null=True)
- act_object = models.CharField(_(u"Object"), max_length=200)
- if settings.COUNTRY == 'fr':
- ref_sra = models.CharField(u"Référence SRA", max_length=15)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Administrative act")
- verbose_name_plural = _(u"Administrative acts")
- permissions = (
-("view_own_administrativeact", ugettext(u"Can view own Administrative act")),
-("add_own_administrativeact", ugettext(u"Can add own Administrative act")),
-("change_own_administrativeact", ugettext(u"Can change own Administrative act")),
-("delete_own_administrativeact", ugettext(u"Can delete own Administrative act")),
- )
-
- def __unicode__(self):
- return JOINT.join([unicode(item)
- for item in [self.operation, self.associated_file, self.act_object]
- if item])
-
-class ContainerType(GeneralType):
- length = models.IntegerField(_(u"Length (mm)"), blank=True, null=True)
- width = models.IntegerField(_(u"Width (mm)"), blank=True, null=True)
- height = models.IntegerField(_(u"Height (mm)"), blank=True, null=True)
- volume = models.IntegerField(_(u"Volume (l)"), blank=True, null=True)
- reference = models.CharField(_(u"Reference"), max_length=30)
-
- class Meta:
- verbose_name = _(u"Container type")
- verbose_name_plural = _(u"Container types")
-
-class Container(LightHistorizedItem):
- TABLE_COLS = ['reference', 'container_type', 'location',]
- location = models.ForeignKey(Warehouse, verbose_name=_(u"Warehouse"))
- container_type = models.ForeignKey(ContainerType,
- verbose_name=_("Container type"))
- reference = models.CharField(_(u"Reference"), max_length=40)
- comment = models.TextField(_(u"Comment"))
-
- class Meta:
- verbose_name = _(u"Container")
- verbose_name_plural = _(u"Containers")
-
- def __unicode__(self):
- lbl = u" - ".join((self.reference, unicode(self.container_type),
- unicode(self.location)))
- return lbl
-
-if settings.COUNTRY == 'fr':
- class Arrondissement(models.Model):
- name = models.CharField(u"Nom", max_length=30)
- department = models.ForeignKey(Departement, verbose_name=u"Département")
-
- def __unicode__(self):
- return JOINT.join((self.name, unicode(self.department)))
-
- class Canton(models.Model):
- name = models.CharField(u"Nom", max_length=30)
- arrondissement = models.ForeignKey(Arrondissement,
- verbose_name=u"Arrondissement")
- def __unicode__(self):
- return JOINT.join((self.name, unicode(self.arrondissement)))
-
-class Town(models.Model):
- name = models.CharField(_(u"Name"), max_length=100)
- surface = models.IntegerField(_(u"Surface (m²)"), blank=True, null=True)
- center = models.PointField(_(u"Localisation"), srid=settings.SRID,
- blank=True, null=True)
- if settings.COUNTRY == 'fr':
- numero_insee = models.CharField(u"Numéro INSEE", max_length=6,
- unique=True)
- departement = models.ForeignKey(Departement, verbose_name=u"Département",
- null=True, blank=True)
- canton = models.ForeignKey(Canton, verbose_name=u"Canton", null=True,
- blank=True)
- objects = models.GeoManager()
-
- class Meta:
- verbose_name = _(u"Town")
- verbose_name_plural = _(u"Towns")
- if settings.COUNTRY == 'fr':
- ordering = ['numero_insee']
-
- def __unicode__(self):
- if settings.COUNTRY == "fr":
- return u"%s (%s)" % (self.name, self.numero_insee)
- return self.name
-
-class TreatmentType(GeneralType):
- virtual = models.BooleanField(_(u"Virtual"))
- class Meta:
- verbose_name = _(u"Treatment type")
- verbose_name_plural = _(u"Treatment types")
-
-class Treatment(BaseHistorizedItem, OwnPerms):
- container = models.ForeignKey(Container, verbose_name=_(u"Container"),
- blank=True, null=True)
- description = models.TextField(_(u"Description"), blank=True, null=True)
- treatment_type = models.ForeignKey(TreatmentType,
- verbose_name=_(u"Treatment type"))
- location = models.ForeignKey(Warehouse, verbose_name=_(u"Location"),
- blank=True, null=True)
- person = models.ForeignKey(Person, verbose_name=_(u"Person"),
- blank=True, null=True)
- start_date = models.DateField(_(u"Start date"), blank=True, null=True)
- end_date = models.DateField(_(u"End date"), blank=True, null=True)
- history = HistoricalRecords()
-
- class Meta:
- verbose_name = _(u"Treatment")
- verbose_name_plural = _(u"Treatments")
- permissions = (
- ("view_own_treatment", ugettext(u"Can view own Treatment")),
- ("add_own_treatment", ugettext(u"Can add own Treatment")),
- ("change_own_treatment", ugettext(u"Can change own Treatment")),
- ("delete_own_treatment", ugettext(u"Can delete own Treatment")),
- )
-
- def __unicode__(self):
- lbl = unicode(self.treatment_type)
- if self.person:
- lbl += u" %s %s" % (_(u"by"), unicode(self.person))
- return lbl
-
-class TreatmentSource(Source):
- class Meta:
- verbose_name = _(u"Treatment documentation")
- verbose_name_plural = _(u"Treament documentations")
- treatment = models.ForeignKey(Treatment, verbose_name=_(u"Treatment"),
- related_name="source")
-
-class Property(LightHistorizedItem):
- item = models.ForeignKey(Item, verbose_name=_(u"Item"))
- administrative_act = models.ForeignKey(AdministrativeAct,
- verbose_name=_(u"Administrative act"))
- person = models.ForeignKey(Person, verbose_name=_(u"Person"))
- start_date = models.DateField(_(u"Start date"))
- end_date = models.DateField(_(u"End date"))
-
- class Meta:
- verbose_name = _(u"Property")
- verbose_name_plural = _(u"Properties")
-
- def __unicode__(self):
- return self.person + JOINT + self.item
-
diff --git a/ishtar/ishtar_base/templatetags/__init__.py b/ishtar/ishtar_base/templatetags/__init__.py
deleted file mode 100644
index 792d60054..000000000
--- a/ishtar/ishtar_base/templatetags/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/ishtar/ishtar_base/templatetags/range.py b/ishtar/ishtar_base/templatetags/range.py
deleted file mode 100644
index 3b3a9097b..000000000
--- a/ishtar/ishtar_base/templatetags/range.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from django.template import Library
-
-register = Library()
-
-@register.filter
-def get_range(value):
- return [val+1 for val in xrange(value)]
diff --git a/ishtar/ishtar_base/templatetags/table_form.py b/ishtar/ishtar_base/templatetags/table_form.py
deleted file mode 100644
index 7adb54d65..000000000
--- a/ishtar/ishtar_base/templatetags/table_form.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from django.template import Library
-
-register = Library()
-
-@register.inclusion_tag('form_snippet.html')
-def table_form(form):
- return {'form': form}
diff --git a/ishtar/ishtar_base/tests.py b/ishtar/ishtar_base/tests.py
deleted file mode 100644
index 5a433b381..000000000
--- a/ishtar/ishtar_base/tests.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/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.
-
-"""
-Unit tests
-"""
-import json
-
-from django.test import TestCase
-
-import models
-
-class FileTest(TestCase):
- fixtures = ['user.json', 'person_type-fr.json', 'organization_type-fr.json',
- 'treatment_type-fr.json']
- model = models.File
-
- def setUp(self):
- self.extra_models, self.model_list = {}, []
- user = models.IshtarUser.objects.get(pk=1)
- person_type = models.PersonType(label=u'Test person type',
- txt_idx='test_person', available=True)
- person_type.save()
- self.extra_models['person_type'] = person_type
- self.model_list.append(person_type)
-
- person = models.Person(title='Mr', surname='Surname', name='Name',
- person_type=person_type, history_modifier=user)
- person.save()
- self.extra_models['person'] = person
- self.model_list.append(person)
-
- file_type = models.FileType(label=u'Test file type',
- txt_idx='test_file', available=True)
- file_type.save()
- self.extra_models['file_type'] = file_type
- self.model_list.append(file_type)
-
- dct = {'year':2010, 'numeric_reference':1000, 'file_type':file_type,
- 'internal_reference':u'UNIT_testÉ ?', 'in_charge':person,
- 'history_modifier':user, 'total_surface':10000}
- self.item = self.model(**dct)
- self.item.save()
-
- def tearDown(self):
- self.item.delete()
- for item in reversed(self.model_list):
- item.delete()
-
- def testAddAndGetHistorized(self):
- """
- Test correct new version and correct access to history
- """
- nb_hist = self.item.history.count()
- self.assertTrue(self.item.history.count() >= 1)
- base_label = self.item.internal_reference
- self.item.internal_reference = u"Unité_Test"
- self.item.save()
- self.failUnlessEqual(self.item.history.count(), nb_hist+1)
- self.failUnlessEqual(self.item.history.all()[1].internal_reference,
- base_label)
-
- def testIntelligentHistorisation(self):
- """
- Test that to identical version are not recorded twice in the history
- """
- nb_hist = self.item.history.count()
- self.item.internal_reference = u"Unité_Test"
- self.item.save()
- self.failUnlessEqual(self.item.history.count(), nb_hist+1)
- nb_hist = self.item.history.count()
- self.item.save()
- self.failUnlessEqual(self.item.history.count(), nb_hist)
-
- def testRollbackFile(self):
- nb_hist = self.item.history.count()
- initial_values = self.item.values()
- backup_date = self.item.history.all()[0].history_date
- self.item.internal_reference = u"Unité_Test"
- self.item.save()
- self.item.rollback(backup_date)
- self.failUnlessEqual(self.item.history.count(), nb_hist)
- new_values = self.item.values()
- for k in initial_values.keys():
- self.assertTrue(k in new_values)
- self.assertEqual(new_values[k], initial_values[k])
-
- def testRESTGetFile(self):
- response = self.client.post('/get-file/',
- {'numeric_reference':self.item.numeric_reference})
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content)
- self.assertTrue('records' in data)
- self.assertTrue(data['records'] == 1)
-
- def testRESTGetOldFile(self):
- initial_ref = self.item.internal_reference
- new_ref = u"Unité_Test_old_file"
- new_ref = initial_ref != new_ref and new_ref or new_ref + u"extra"
- self.item.internal_reference = new_ref
- self.item.save()
- response = self.client.post('/get-file/',
- {'numeric_reference':self.item.numeric_reference, 'old':1})
- self.assertEqual(response.status_code, 200)
- data = json.loads(response.content)
- self.assertTrue('records' in data)
- self.assertTrue(data['records'] == 1)
- self.assertEqual(data['rows'][0]['internal_reference'], initial_ref)
-
diff --git a/ishtar/ishtar_base/urls.py b/ishtar/ishtar_base/urls.py
deleted file mode 100644
index a5b1f5efa..000000000
--- a/ishtar/ishtar_base/urls.py
+++ /dev/null
@@ -1,223 +0,0 @@
-#!/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.
-
-from django.conf.urls.defaults import *
-
-from menus import menu
-#import forms_main as ishtar_forms
-
-import views
-
-urlpatterns, actions = [], []
-
-
-# forms
-urlpatterns = patterns('',
- # General
- url(r'person_creation/(?P<step>.+)$',
- views.person_creation_wizard, name='person_creation_step'),
- url(r'person_creation/$',
- views.person_creation_wizard, name='person_creation'),
- )
-"""
- url(r'person_modification/(?P<step>.+)$',
- ishtar_forms.person_modification_wizard, name='person_modification'),
- url(r'account_management/(?P<step>.+)$',
- ishtar_forms.account_management_wizard, name='account_management'),
- # Archaelogical files
- url(r'file_search/(?P<step>.+)$',
- ishtar_forms.file_search_wizard, name='file_search'),
- url(r'file_creation/(?P<step>.+)$',
- ishtar_forms.file_creation_wizard, name='file_creation'),
- url(r'file_modification/(?P<step>.+)$',
- ishtar_forms.file_modification_wizard, name='file_modification'),
- url(r'file_closing/(?P<step>.+)$',
- ishtar_forms.file_closing_wizard, name='file_closing'),
- url(r'file_deletion/(?P<step>.+)$',
- ishtar_forms.file_deletion_wizard, name='file_deletion'),
- url(r'file_administrativeactfile/(?P<step>.+)$',
- ishtar_forms.file_administrativeactfile_wizard,
- name='file_administrativeactfile'),
- url(r'file_administrativeactfile_modification/(?P<step>.+)$',
- ishtar_forms.file_administrativeactfile_modification_wizard,
- name='file_administrativeactfile_modification'),
- url(r'file_administrativeactfile_deletion/(?P<step>.+)$',
- ishtar_forms.file_administrativeactfile_deletion_wizard,
- name='file_administrativeactfile_deletion'),
- # Operations
- url(r'operation_search/(?P<step>.+)$',
- ishtar_forms.operation_search_wizard, name='operation_search'),
- url(r'operation_creation/(?P<step>.+)$',
- ishtar_forms.operation_creation_wizard, name='operation_creation'),
- url(r'operation_modification/(?P<step>.+)$',
- ishtar_forms.operation_modification_wizard,
- name='operation_modification'),
- url(r'operation_closing/(?P<step>.+)$',
- ishtar_forms.operation_closing_wizard, name='operation_closing'),
- url(r'operation_deletion/(?P<step>.+)$',
- ishtar_forms.operation_deletion_wizard, name='operation_deletion'),
- url(r'operation_administrativeactop/(?P<step>.+)$',
- ishtar_forms.operation_administrativeactop_wizard,
- name='operation_administrativeactop'),
- url(r'operation_administrativeactop_modification/(?P<step>.+)$',
- ishtar_forms.operation_administrativeactop_modification_wizard,
- name='operation_administrativeactop_modification'),
- url(r'operation_administrativeactop_deletion/(?P<step>.+)$',
- ishtar_forms.operation_administrativeactop_deletion_wizard,
- name='operation_administrativeactop_deletion'),
- url(r'operation_source_creation/(?P<step>.+)$',
- ishtar_forms.operation_source_creation_wizard,
- name='operation_source_creation'),
- url(r'operation_source_modification/(?P<step>.+)$',
- ishtar_forms.operation_source_modification_wizard,
- name='operation_source_modification'),
- url(r'operation_source_deletion/(?P<step>.+)$',
- ishtar_forms.operation_source_deletion_wizard,
- name='operation_source_deletion'),
- # Context records
- url(r'record_search/(?P<step>.+)$',
- ishtar_forms.record_search_wizard, name='record_search'),
- url(r'record_creation/(?P<step>.+)$',
- ishtar_forms.record_creation_wizard, name='record_creation'),
- url(r'record_modification/(?P<step>.+)$',
- ishtar_forms.record_modification_wizard, name='record_modification'),
- url(r'record_deletion/(?P<step>.+)$',
- ishtar_forms.record_deletion_wizard, name='record_deletion'),
- url(r'record_source_creation/(?P<step>.+)$',
- ishtar_forms.record_source_creation_wizard,
- name='record_source_creation'),
- url(r'record_source_modification/(?P<step>.+)$',
- ishtar_forms.record_source_modification_wizard,
- name='record_source_modification'),
- url(r'record_source_deletion/(?P<step>.+)$',
- ishtar_forms.record_source_deletion_wizard,
- name='record_source_deletion'),
- # Finds
- url(r'item_search/(?P<step>.+)$',
- ishtar_forms.item_search_wizard, name='item_search'),
- url(r'item_creation/(?P<step>.+)$',
- ishtar_forms.item_creation_wizard, name='item_creation'),
- url(r'item_modification/(?P<step>.+)$',
- ishtar_forms.item_modification_wizard, name='item_modification'),
- url(r'item_source_creation/(?P<step>.+)$',
- ishtar_forms.item_source_creation_wizard,
- name='item_source_creation'),
- url(r'item_source_modification/(?P<step>.+)$',
- ishtar_forms.item_source_modification_wizard,
- name='item_source_modification'),
- url(r'item_source_deletion/(?P<step>.+)$',
- ishtar_forms.item_source_deletion_wizard,
- name='item_source_deletion'),
- # Treatments
- url(r'treatment_creation/(?P<step>.+)$',
- ishtar_forms.treatment_creation_wizard, name='treatment_creation'),
- url(r'warehouse_packaging/(?P<step>.+)$',
- ishtar_forms.warehouse_packaging_wizard, name='warehouse_packaging'),
- )"""
-for section in menu.childs:
- for menu_item in section.childs:
- if hasattr(menu_item, 'childs'):
- for menu_subitem in menu_item.childs:
- actions.append(menu_subitem.idx)
- else:
- actions.append(menu_item.idx)
-actions = r"|".join(actions)
-
-# other views
-urlpatterns += patterns('ishtar.ishtar_base.views',
- # General
- url(r'(?P<action_slug>' + actions + r')/$', 'action',
- name='action'),
- url(r'new-person/(?P<parent_name>.+)?/$',
- 'new_person', name='new-person'),
- url(r'autocomplete-person/([0-9_]+)?$', 'autocomplete_person',
- name='autocomplete-person'),
- url(r'autocomplete-town/$', 'autocomplete_town',
- name='autocomplete-town'),
- url(r'new-author/(?P<parent_name>.+)?/$',
- 'new_author', name='new-author'),
- url(r'autocomplete-author/$', 'autocomplete_author',
- name='autocomplete-author'),
- url(r'new-organization/(?P<parent_name>.+)?/$',
- 'new_organization', name='new-organization'),
- url(r'autocomplete-organization/([0-9_]+)?$',
- 'autocomplete_organization', name='autocomplete-organization'),
- url(r'new-warehouse/(?P<parent_name>.+)?/$',
- 'new_warehouse', name='new-warehouse'),
- url(r'autocomplete-warehouse/$', 'autocomplete_warehouse',
- name='autocomplete-warehouse'),
- # Archaelogical files
- url(r'autocomplete-file/$', 'autocomplete_file',
- name='autocomplete-file'),
- url(r'get-file/(?P<type>.+)?$', 'get_file',
- name='get-file'),
- url(r'get-file-full/(?P<type>.+)?$', 'get_file',
- name='get-file-full', kwargs={'full':True}),
- url(r'get-administrativeactfile/(?P<type>.+)?$',
- 'get_administrativeactfile', name='get-administrativeactfile'),
- url(r'show-file/(?P<pk>.+)?/(?P<type>.+)?$', 'show_file',
- name='show-file'),
- url(r'show-historized-file/(?P<pk>.+)?/(?P<date>.+)?$',
- 'show_file', name='show-historized-file'),
- url(r'revert-file/(?P<pk>.+)/(?P<date>.+)$',
- 'revert_file', name='revert-file'),
- # Operations
- url(r'autocomplete-operation/$', 'autocomplete_operation',
- name='autocomplete-operation'),
- url(r'get-operation/(?P<type>.+)?$', 'get_operation',
- name='get-operation'),
- url(r'get-operation-full/(?P<type>.+)?$', 'get_operation',
- name='get-operation-full', kwargs={'full':True}),
- url(r'get-available-operation-code/(?P<year>.+)?$',
- 'get_available_operation_code', name='get_available_operation_code'),
- url(r'revert-operation/(?P<pk>.+)/(?P<date>.+)$',
- 'revert_operation', name='revert-operation'),
- url(r'show-operation/(?P<pk>.+)?/(?P<type>.+)?$',
- 'show_operation', name='show-operation'),
- url(r'get-administrativeactop/(?P<type>.+)?$',
- 'get_administrativeactop', name='get-administrativeactop'),
- url(r'get-operationsource/(?P<type>.+)?$',
- 'get_operationsource', name='get-operationsource'),
- # Context records
- url(r'show-contextrecord/(?P<pk>.+)?/(?P<type>.+)?$',
- 'show_contextrecord', name='show-contextrecord'),
- url(r'get-contextrecord/(?P<type>.+)?$', 'get_contextrecord',
- name='get-contextrecord'),
- url(r'get-contextrecord-full/(?P<type>.+)?$',
- 'get_contextrecord', name='get-contextrecord-full',
- kwargs={'full':True}),
- url(r'get-contexrecordsource/(?P<type>.+)?$',
- 'get_contextrecordsource', name='get-contextrecordsource'),
- # Finds
- url(r'update-current-item/$', 'update_current_item',
- name='update-current-item'),
- url(r'get-item/(?P<type>.+)?$', 'get_archaeologicalitem',
- name='get-item'),
- url(r'get-item-full/(?P<type>.+)?$', 'get_archaeologicalitem',
- name='get-item-full', kwargs={'full':True}),
- url(r'get-itemsource/(?P<type>.+)?$',
- 'get_itemsource', name='get-itemsource'),
- url(r'get-container/$', 'get_container',
- name='get-container'),
- # Treatments
- url(r'autocomplete-container/?$',
- 'autocomplete_container', name='autocomplete-container'),
- url(r'new-container/(?P<parent_name>.+)?/$',
- 'new_container', name='new-container'),
-)
diff --git a/ishtar/ishtar_base/views.py b/ishtar/ishtar_base/views.py
deleted file mode 100644
index 4a7f276fb..000000000
--- a/ishtar/ishtar_base/views.py
+++ /dev/null
@@ -1,1333 +0,0 @@
-#!/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.
-
-try:
- import tidy
-except:
- from tidylib import tidy_document as tidy
-
-import re
-import csv
-import json
-import datetime
-import optparse
-import cStringIO as StringIO
-from tempfile import NamedTemporaryFile
-import ho.pisa as pisa
-
-from django.contrib.formtools.wizard.views import NamedUrlWizardView
-from django.core import serializers
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.urlresolvers import reverse, NoReverseMatch
-from django.db.models import Q
-from django.http import HttpResponse, Http404
-from django.shortcuts import render_to_response, redirect
-from django.template import RequestContext, loader
-from django.template.defaultfilters import slugify
-from django.utils.translation import ugettext, ugettext_lazy as _
-
-from ishtar import settings
-if settings.XHTML2ODT_PATH:
- import sys
- sys.path.append(settings.XHTML2ODT_PATH)
- from xhtml2odt import xhtml2odt
-
-from menus import menu
-import forms_main as ishtar_forms
-
-from ishtar.ishtar_base.forms import FinalForm
-from ishtar.ishtar_base.forms_common import PersonForm
-import models
-
-CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL}
-ENCODING = settings.ENCODING or 'utf-8'
-
-def index(request):
- """
- Main page
- """
- dct = {}
- return render_to_response('index.html', dct,
- context_instance=RequestContext(request))
-
-class Wizard(NamedUrlWizardView):
- model = None
- modification = None # True when the wizard modify an item
- storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'
-
- @staticmethod
- def _check_right(step, condition=True):
- '''Return a method to check the right for a specific step'''
- """
- def check_right(self, request, storage):
- cond = condition
- if callable(condition):
- cond = condition(self, request, storage)
- if not cond:
- return False
- person_type = request.user.ishtaruser.person.person_type
- if person_type.txt_idx == 'administrator':
- return True
- if person_type.rights.filter(url_name=step).count():
- return True"""
- def check_right(self):
- cond = condition
- if callable(condition):
- cond = condition(self)
- if not cond:
- return False
- person_type = self.request.user.ishtaruser.person.person_type
- if person_type.txt_idx == 'administrator':
- return True
- if person_type.rights.filter(url_name=step).count():
- return True
- return check_right
-
- def __init__(self, *args, **kwargs):
- """Check right for each step of the wizard"""
- super(Wizard, self).__init__(*args, **kwargs)
- for form_key in self.form_list.keys()[:-1]:
- condition = True
- if form_key in self.condition_dict:
- condition = self.condition_dict.get(form_key, True)
- cond = self._check_right(form_key, condition)
- self.condition_dict[form_key] = cond
- """
- for form_key in self.form_list.keys()[:-1]:
- condition = True
- if form_key in self.condition_list:
- condition = self.condition_list.get(form_key, True)
- cond = self._check_right(form_key, condition)
- self.condition_list[form_key] = cond"""
-
- def get_wizard_name(self):
- """As the class name can interfere when reused, use the url_name"""
- return self.url_name
-
- def get_template_names(self):
- templates = ['ishtar/wizard/default_wizard.html']
- current_step = self.steps.current
- if current_step == self.steps.last:
- templates = ['ishtar/wizard/confirm_wizard.html'] + templates
- return templates
-
- def get_context_data(self, form, **kwargs):
- """Add previous, next and current steps to manage the wizard path"""
- context = super(Wizard, self).get_context_data(form)
- step = self.steps.first
- current_step = self.steps.current
- context.update({'current_step':self.form_list[current_step]})
- if step == current_step:
- return context
- previous_steps, next_steps, previous_step_counter = [], [], 0
- while step:
- if step == current_step:
- break
- previous_steps.append(self.form_list[step])
- step = self.steps.next
- previous_step_counter += 1
- context.update({'previous_steps':previous_steps,
- 'previous_step_counter':previous_step_counter})
- # if modification: show the next steps
- if self.modification:
- next_step = step
- while next_step:
- # check if the form is initialized otherwise initialize it
- if not storage.get_step_data(next_step):
- values = self.get_form_initial(request, storage, next_step)
- prefixed_values = {}
- if not isinstance(values, list):
- for key in values:
- form_key = next_step + '-' + key
- prefixed_values[form_key] = values[key]
- else:
- for formset_idx, v in enumerate(values):
- prefix = u"-%d-" % formset_idx
- for key in v:
- form_key = next_step + prefix + key
- prefixed_values[form_key] = v[key]
- storage.set_step_data(next_step, prefixed_values)
- if step != next_step: # if not current step
- next_steps.append(self.form_list[next_step])
- next_step = self.get_next_step(request, storage, next_step)
- context.update({'next_steps':next_steps})
- # not last step: validation
- if current_step != self.steps.last:
- return context
- final_form_list = []
- for form_key in self.get_form_list().keys():
- form_obj = self.get_form(step=form_key,
- data=self.storage.get_step_data(form_key),
- files=self.storage.get_step_files(form_key))
- form_obj.is_valid()
- final_form_list.append(form_obj)
- last_form = final_form_list[-1]
- context.update({'datas':self.get_formated_datas(final_form_list)})
- if hasattr(last_form, 'confirm_msg'):
- context.update({'confirm_msg':last_form.confirm_msg})
- if hasattr(last_form, 'confirm_end_msg'):
- context.update({'confirm_end_msg':last_form.confirm_end_msg})
- return context
-
- def get_formated_datas(self, forms):
- """Get the data to present in the last page"""
- datas = []
- for form in forms:
- form_datas = []
- base_form = hasattr(form, 'forms') and form.forms[0] or form
- associated_models = hasattr(base_form, 'associated_models') and \
- base_form.associated_models or {}
- if not hasattr(form, 'cleaned_data') and hasattr(form, 'forms'):
- cleaned_datas = [frm.cleaned_data for frm in form.forms
- if frm.is_valid()]
- if not cleaned_datas:
- continue
- elif not hasattr(form, 'cleaned_data'):
- continue
- else:
- cleaned_datas = type(form.cleaned_data) == list and \
- form.cleaned_data \
- or [form.cleaned_data]
- for cleaned_data in cleaned_datas:
- if not cleaned_data:
- continue
- if form_datas:
- form_datas.append(("", "", "spacer"))
- items = hasattr(base_form, 'fields') and \
- base_form.fields.keyOrder or cleaned_data.keys()
- for key in items:
- lbl = None
- if key.startswith('hidden_'):
- continue
- if hasattr(base_form, 'fields') and key in base_form.fields:
- lbl = base_form.fields[key].label
- if hasattr(base_form, 'associated_labels') \
- and key in base_form.associated_labels:
- lbl = base_form.associated_labels[key]
- if not lbl:
- continue
- value = cleaned_data[key]
- if not value and value != False:
- continue
- if type(value) == bool:
- if value == True:
- value = _(u"Yes")
- elif value == False:
- value = _(u"No")
- elif key in associated_models:
- values = []
- if "," in unicode(value):
- values = unicode(value).split(",")
- else:
- values = [value]
- rendered_values = []
- for val in values:
- item = associated_models[key].objects.get(pk=val)
- if hasattr(item, 'short_label'):
- value = item.short_label()
- else:
- value = unicode(item)
- rendered_values.append(value)
- value = u" ; ".join(rendered_values)
- form_datas.append((lbl, value, ''))
- if form_datas:
- datas.append((form.form_label, form_datas))
- return datas
-
- def get_extra_model(self, dct, form_list):
- dct['history_modifier'] = self.request.user
- return dct
-
- def done(self, form_list, return_object=False, **kwargs):
- """Save to the model"""
- dct, m2m, whole_associated_models = {}, [], []
- for form in form_list:
- if not form.is_valid():
- return self.render(form)
- base_form = hasattr(form, 'forms') and form.forms[0] or form
- associated_models = hasattr(base_form, 'associated_models') and \
- base_form.associated_models or {}
- if hasattr(form, 'forms'):
- multi = False
- if form.forms:
- frm = form.forms[0]
- if hasattr(frm, 'base_model') and frm.base_model:
- whole_associated_models.append(frm.base_model)
- else:
- whole_associated_models += associated_models.keys()
- fields = frm.fields.copy()
- if 'DELETE' in fields:
- fields.pop('DELETE')
- multi = len(fields) > 1
- if multi:
- assert hasattr(frm, 'base_model'), \
- u"Must define a base_model for " + unicode(frm.__class__)
- for frm in form.forms:
- if not frm.is_valid():
- continue
- vals = {}
- if "DELETE" in frm.cleaned_data:
- if frm.cleaned_data["DELETE"]:
- continue
- frm.cleaned_data.pop('DELETE')
- for key in frm.cleaned_data:
- value = frm.cleaned_data[key]
- if not value and value != False:
- continue
- if key in associated_models:
- value = associated_models[key].objects.get(pk=value)
- if multi:
- vals[key] = value
- else:
- m2m.append((key, value))
- if multi and vals:
- m2m.append((frm.base_model, vals))
- elif type(form.cleaned_data) == dict:
- for key in form.cleaned_data:
- if key.startswith('hidden_'):
- continue
- value = form.cleaned_data[key]
- if key in associated_models:
- if value:
- model = associated_models[key]
- if isinstance(value, unicode) \
- or isinstance(value, str) and "," in value:
- value = value.split(",")
- if isinstance(value, list) \
- or isinstance(value, tuple):
- value = [model.objects.get(pk=val)
- for val in value if val]
- if len(value) == 1:
- value = value[0]
- else:
- value = model.objects.get(pk=value)
- else:
- value = None
- dct[key] = value
- return self.save_model(dct, m2m, whole_associated_models, form_list,
- return_object)
-
- def get_saved_model(self):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.model
-
- def get_current_saved_object(self):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.get_current_object()
-
- def save_model(self, dct, m2m, whole_associated_models, form_list,
- return_object):
- dct = self.get_extra_model(dct, form_list)
- obj = self.get_current_saved_object()
- # manage dependant items
- other_objs = {}
- for k in dct.keys():
- if '__' not in k:
- continue
- vals = k.split('__')
- assert len(vals) == 2, "Only one level of dependant item is managed"
- dependant_item, key = vals
- if dependant_item not in other_objs:
- other_objs[dependant_item] = {}
- other_objs[dependant_item][key] = dct.pop(k)
- if obj:
- for k in dct:
- if k.startswith('pk'):
- continue
- setattr(obj, k, dct[k])
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(form_list[-1])
- for dependant_item in other_objs:
- c_item = getattr(obj, dependant_item)
- # manage ManyToMany if only one associated
- if hasattr(c_item, "all"):
- c_items = c_item.all()
- if len(c_items) != 1:
- continue
- c_item = c_items[0]
- if c_item:
- # to check #
- for k in other_objs[dependant_item]:
- setattr(c_item, k, other_objs[dependant_item][k])
- c_item.save()
- else:
- m = getattr(self.model, dependant_item)
- if hasattr(m, 'related'):
- c_item = m.related.model(**other_objs[dependant_item])
- setattr(obj, dependant_item, c_item)
- obj.save()
- obj.save()
- else:
- adds = {}
- for dependant_item in other_objs:
- m = getattr(self.model, dependant_item)
- model = m.field.rel.to
- c_dct = other_objs[dependant_item].copy()
- if issubclass(model, models.BaseHistorizedItem):
- c_dct['history_modifier'] = self.request.user
- c_item = model(**c_dct)
- c_item.save()
- if hasattr(m, 'through'):
- adds[dependant_item] = c_item
- elif hasattr(m, 'field'):
- dct[dependant_item] = c_item
- if 'pk' in dct:
- dct.pop('pk')
- obj = self.get_saved_model()(**dct)
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(form_list[-1])
- obj.save()
- for k in adds:
- getattr(obj, k).add(adds[k])
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- m2m_items = {}
- for model in whole_associated_models:
- getattr(obj, model+'s').clear()
- for key, value in m2m:
- if key not in m2m_items:
- if type(key) == dict:
- vals = []
- for item in getattr(obj, key+'s').all():
- v = {}
- for k in value.keys():
- v[k] = getattr(item, k)
- vals.append(v)
- m2m_items[key] = vals
- else:
- m2m_items[key] = getattr(obj, key+'s').all()
- if value not in m2m_items[key]:
- if type(value) == dict:
- model = getattr(obj, key+'s').model
- if issubclass(model, models.BaseHistorizedItem):
- value['history_modifier'] = self.request.user
- value = model.objects.create(**value)
- value.save()
- getattr(obj, key+'s').add(value)
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- res = render_to_response('wizard_done.html', {},
- context_instance=RequestContext(self.request))
- return return_object and (obj, res) or res
-
- def get_deleted(self, keys):
- """Get the deleted and non-deleted items in formsets"""
- not_to_delete, to_delete = set(), set()
- for key in keys:
- items = key.split('-')
- if len(items) < 2 or items[-2] in to_delete:
- continue
- idx = items[-2]
- try:
- int(idx)
- except:
- continue
- if items[-1] == u'DELETE':
- to_delete.add(idx)
- if idx in not_to_delete:
- not_to_delete.remove(idx)
- elif idx not in not_to_delete:
- not_to_delete.add(idx)
- return (to_delete, not_to_delete)
-
- def get_form(self, step=None, data=None, files=None):
- """Manage formset"""
- request = self.request
- storage = self.storage
- if data:
- data = data.copy()
- if not step:
- step = self.steps.current
- form = self.get_form_list()[step]
- if hasattr(form, 'management_form'):
- # manage deletion
- to_delete, not_to_delete = self.get_deleted(data.keys())
- # raz deleted fields
- for key in data.keys():
- items = key.split('-')
- if len(items) < 2 or items[-2] not in to_delete:
- continue
- data.pop(key)
- if to_delete:
- # reorganize
- for idx, number in enumerate(sorted(not_to_delete)):
- idx = unicode(idx)
- if idx == number:
- continue
- for key in data.keys():
- items = key.split('-')
- if len(items) > 2 and number == items[-2]:
- items[-2] = unicode(idx)
- k = u'-'.join(items)
- data[k] = data.pop(key)[0]
- # get a form key
- base_key = form.form.base_fields.keys()[0]
- init = self.get_form_initial(request, storage, step)
- total_field = len([key for key in data.keys()
- if base_key in key.split('-')
- and data[key]])
- if init and not to_delete:
- total_field = max((total_field, len(init)))
- data[step + u'-INITIAL_FORMS'] = unicode(total_field)
- data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1)
- data = data or None
- form = super(Wizard, self).get_form(step, data, files)
- return form
-
- def render_next_step(self, form, **kwargs):
- """
- Manage:
- - modify or delete button in formset: next step = current step
- - validate and end: nextstep = last step
- """
- request = self.request
- if request.POST.has_key('formset_modify') \
- and request.POST['formset_modify'] \
- or [key for key in request.POST.keys()
- if key.endswith('DELETE') and request.POST[key]]:
- return self.render(form)
- elif request.POST.has_key('validate_and_end') \
- and request.POST['validate_and_end']:
- last_step = self.steps.last
- new_form = self.get_form(last_step,
- data=self.storage.get_step_data(last_step),
- files=self.storage.get_step_files(last_step))
- self.storage.current_step = last_step
- return self.render(new_form)
- return super(Wizard, self).render_next_step(form, **kwargs)
-
- def post(self, *args, **kwargs):
- """Convert numerical step number to step name"""
- request = self.request
- post_data = request.POST.copy()
- if request.POST.has_key('form_prev_step'):
- try:
- step_number = int(request.POST['form_prev_step'])
- post_data['wizard_goto_step'] = self.get_form_list().keys(
- )[step_number]
- except ValueError:
- pass
- request.POST = post_data
- return super(Wizard, self).post(*args, **kwargs)
-
- @classmethod
- def session_has_key(cls, request, storage, form_key, key=None, multi=None):
- """Check if the session has value of a specific form and (if provided)
- of a key
- """
- test = storage.prefix in request.session \
- and 'step_data' in request.session[storage.prefix] \
- and form_key in request.session[storage.prefix]['step_data']
- if not key or not test:
- return test
- key = key.startswith(form_key) and key or \
- not multi and form_key + '-' + key or \
- form_key + '-0-' + key #only check if the first field is available
- return key in request.session[storage.prefix]['step_data'][form_key]
-
- @classmethod
- def session_get_value(cls, request, storage, form_key, key, multi=False):
- """Get the value of a specific form"""
- if not cls.session_has_key(request, storage, form_key, key, multi):
- return
- if not multi:
- key = key.startswith(form_key) and key or form_key + '-' + key
- return request.session[storage.prefix]['step_data'][form_key][key]
- vals = []
- for k in request.session[storage.prefix]['step_data'][form_key]:
- if k.startswith(form_key) and k.endswith(key) and \
- request.session[storage.prefix]['step_data'][form_key][k]:
- vals.append(request.session[storage.prefix]['step_data']\
- [form_key][k])
- return vals
-
- def get_current_object(self):
- """Get the current object for an instancied wizard"""
- current_obj = None
- main_form_key = 'selec-' + self.url_name
- try:
- idx = int(self.session_get_value(self.request, self.storage,
- main_form_key, 'pk'))
- current_obj = self.model.objects.get(pk=idx)
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- return current_obj
-
- def get_form_initial(self, step):
- current_obj = self.get_current_object()
- current_step = self.steps.current
- if step.startswith('selec-') and step in self.form_list \
- and 'pk' in self.form_list[step].associated_models:
- model_name = self.form_list[step].associated_models['pk'
- ].__name__.lower()
- if step == current_step:
- self.reset_wizard(request, storage)
- val = model_name in request.session and request.session[model_name]
- if val:
- return {'pk':val}
- elif current_obj:
- return self.get_instanced_init(current_obj, step)
- current_form = self.form_list[current_step]
- if hasattr(current_form, 'currents'):
- initial = {}
- for key in current_form.currents:
- model_name = current_form.currents[key].__name__.lower()
- val = model_name in request.session and \
- request.session[model_name]
- if val:
- initial[key] = val
- if initial:
- return initial
- return super(Wizard, self).get_form_initial(step)
-
- def get_instanced_init(self, obj, step=None):
- """Get initial data from an init"""
- current_step = step or self.steps.current
- c_form = self.form_list[current_step]
- # make the current object the default item for the session
- obj_name = obj.__class__.__name__.lower()
- # prefer a specialized name if available
- prefixes = self.storage.prefix.split('_')
- if len(prefixes) > 1 and prefixes[-2].startswith(obj_name):
- obj_name = prefixes[-2]
- self.request.session[obj_name] = unicode(obj.pk)
- initial = {}
- if self.request.POST or \
- (step in self.request.session[self.storage.prefix] and\
- self.request.session[self.storage.prefix]['step_data'][step]):
- return {}
- if hasattr(c_form, 'base_fields'):
- for base_field in c_form.base_fields.keys():
- fields = base_field.split('__')
- value = obj
- for field in fields:
- if not hasattr(value, field) or \
- getattr(value, field) == None:
- value = obj
- break
- value = getattr(value, field)
- if value == obj:
- continue
- if hasattr(value, 'pk'):
- value = value.pk
- if value in (True, False):
- initial[base_field] = value
- elif value != None:
- initial[base_field] = unicode(value)
- elif hasattr(c_form, 'management_form'):
- initial = []
- if hasattr(c_form.form, 'base_model'):
- key = c_form.form.base_model + 's'
- else:
- key = current_step.split('-')[0]
- if not hasattr(obj, key):
- return initial
- keys = c_form.form.base_fields.keys()
- for child_obj in getattr(obj, key).order_by('pk').all():
- if not keys:
- break
- vals = {}
- if len(keys) == 1:
- # only one field: must be the id of the object
- vals[keys[0]] = unicode(child_obj.pk)
- else:
- for field in keys:
- if hasattr(child_obj, field):
- value = getattr(child_obj, field)
- if hasattr(value, 'pk'):
- value = value.pk
- if value != None:
- vals[field] = unicode(value)
- if vals:
- initial.append(vals)
- return initial
-
-class PersonWizard(Wizard):
- model = models.Person
-
-person_creation_wizard = PersonWizard.as_view([
- ('identity-person_creation', PersonForm),
- ('final-person_creation', FinalForm)],
- url_name='person_creation_step',)
-
-
-def update_current_item(request):
- if not request.is_ajax() and not request.method == 'POST':
- raise Http404
- if 'value' in request.POST and 'item' in request.POST:
- request.session[request.POST['item']] = request.POST['value']
- return HttpResponse('ok')
-
-def check_permission(request, action_slug, obj_id=None):
- if action_slug not in menu.items:
- #! TODO
- return True
- if obj_id:
- return menu.items[action_slug].is_available(request.user, obj_id)
- return menu.items[action_slug].can_be_available(request.user)
-
-def autocomplete_person(request, person_type=None):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_person', models.Person) and
- not request.user.has_perm('ishtar_base.view_own_person', models.Person)
- and not person_types.rights.filter(wizard__url_name='person_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- limit = request.GET.get('limit', 20)
- try:
- limit = int(limit)
- except ValueError:
- return HttpResponseBadRequest()
- query = Q()
- for q in q.split(' '):
- query = query & (Q(name__icontains=q) | Q(surname__icontains=q) | \
- Q(email__icontains=q))
- if person_type:
- try:
- typs = [int(tp) for tp in person_type.split('_') if tp]
- typ = models.PersonType.objects.filter(pk__in=typs).all()
- query = query & Q(person_type__in=typ)
- except (ValueError, ObjectDoesNotExist):
- pass
- limit = 20
- persons = models.Person.objects.filter(query)[:limit]
- data = json.dumps([{'id':person.pk, 'value':unicode(person)}
- for person in persons if person])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_town(request):
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q)
- if settings.COUNTRY == 'fr':
- extra = (extra | Q(numero_insee__istartswith=q) | \
- Q(departement__label__istartswith=q))
- query = query & extra
- limit = 20
- towns = models.Town.objects.filter(query)[:limit]
- data = json.dumps([{'id':town.pk, 'value':unicode(town)}
- for town in towns])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_file(request):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_file', models.File) and \
- not request.user.has_perm('ishtar_base.view_own_file', models.File)
- and not person_types.rights.filter(wizard__url_name='file_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(internal_reference__icontains=q) | \
- Q(towns__name__icontains=q)
- try:
- value = int(q)
- extra = extra | Q(year=q) | Q(numeric_reference=q)
- except ValueError:
- pass
- query = query & extra
- limit = 20
- files = models.File.objects.filter(query)[:limit]
- data = json.dumps([{'id':file.pk, 'value':unicode(file)}
- for file in files])
- return HttpResponse(data, mimetype='text/plain')
-
-from types import NoneType
-
-def format_val(val):
- if type(val) == NoneType:
- return u""
- if type(val) == bool:
- if val:
- return unicode(_(u"True"))
- else:
- return unicode(_(u"False"))
- return unicode(val)
-
-HIERARCHIC_LEVELS = 5
-HIERARCHIC_FIELDS = ['period', 'unit', 'material_type']
-PRIVATE_FIELDS = ('id', 'history_modifier', 'order')
-def get_item(model, func_name, default_name, extra_request_keys=[],
- base_request={}, bool_fields=[]):
- """
- Generic treatment of tables
- """
- def func(request, data_type='json', full=False, **dct):
- if 'type' in dct:
- data_type = dct.pop('type')
- if not data_type:
- data_type = 'json'
- fields = [model._meta.get_field_by_name(k)[0]
- for k in model._meta.get_all_field_names()]
- request_keys = dict([(field.name,
- field.name + (hasattr(field, 'rel') and field.rel and '__pk' or ''))
- for field in fields])
- request_keys.update(extra_request_keys)
- request_items = request.method == 'POST' and request.POST or request.GET
- dct = base_request.copy()
- try:
- old = 'old' in request_items and int(request_items['old'])
- except ValueError:
- return HttpResponse(None, mimetype='text/plain')
- for k in request_keys:
- q = request_items.get(k)
- if not q:
- continue
- dct[request_keys[k]] = q
- if not dct and 'submited' not in request_items:
- if default_name in request.session and \
- request.session[default_name]:
- dct = {"pk":request.session[default_name]}
- if (not dct or data_type == 'csv') and func_name in request.session:
- dct = request.session[func_name]
- else:
- request.session[func_name] = dct
- for k in bool_fields:
- if k in dct:
- if dct[k] == u"1":
- dct.pop(k)
- else:
- dct[k] = dct[k] == u"2" and True or False
-
- # manage hierarchic conditions
- or_reqs = []
- for req in dct.copy():
- for k_hr in HIERARCHIC_FIELDS:
- if req.endswith(k_hr + '__pk'):
- val = dct.pop(req)
- reqs = Q(**{req:val})
- req = req[:-2] + '__'
- for idx in xrange(HIERARCHIC_LEVELS):
- req = req[:-2] + 'parent__pk'
- q = Q(**{req:val})
- reqs = reqs | q
- or_reqs.append(reqs)
- break
- query = Q(**dct)
- for or_req in or_reqs:
- query = query & or_req
- items = model.objects.filter(query)
- q = request_items.get('sidx')
-
- # manage sort tables
- if q and q in request_keys:
- ks = request_keys[q]
- if type(ks) not in (list, tuple):
- ks = [ks]
- orders = []
- for k in ks:
- if k.endswith("__pk"):
- k = k[:-len("__pk")] + "__label"
- q = request_items.get('sord')
- sign = q and q == u'desc' and "-" or ''
- if '__' in k:
- k = k.split('__')[0]
- orders.append(sign+k)
- items = items.order_by(*orders)
-
- # pager management
- start, end = 0, None
- page_nb = 1
- try:
- row_nb = int(request_items.get('rows'))
- except (ValueError, TypeError):
- row_nb = None
- if row_nb:
- try:
- page_nb = int(request_items.get('page'))
- assert page_nb >= 1
- except (ValueError, AssertionError):
- pass
- start = (page_nb-1)*row_nb
- end = page_nb*row_nb
- items_nb = items.count()
- items = items[start:end]
-
- datas = []
- if old:
- items = [item.get_previous(old) for item in items]
- table_cols = full and [field.name for field in model._meta.fields
- if field.name not in PRIVATE_FIELDS] \
- or model.TABLE_COLS
- for item in items:
- data = [item.pk]
- for k in table_cols:
- vals = [item]
- for ky in k.split('.'):
- new_vals = []
- for val in vals:
- if hasattr(val, 'all'): # manage related objects
- val = list(val.all())
- for v in val:
- new_vals.append(getattr(v, ky))
- elif val:
- new_vals.append(getattr(val, ky))
- vals = new_vals
- if vals and hasattr(vals[0], 'all'): # manage last related objects
- new_vals = []
- for val in vals:
- new_vals += list(val.all())
- vals = new_vals
- data.append(", ".join([format_val(v) for v in vals]) or u"")
- datas.append(data)
- link_template = "<a href='#' onclick='load_window(\"%%s\")'>%s</a>" % \
- (unicode(_("Details")))
- if data_type == "json":
- rows = []
- for data in datas:
- try:
- lnk = link_template % reverse('show-'+default_name,
- args=[data[0], ''])
- except NoReverseMatch:
- lnk = ''
- res = {'id':data[0], 'link':lnk}
- for idx, value in enumerate(data[1:]):
- if value:
- res[table_cols[idx].split('.')[-1]] = value
- rows.append(res)
- data = json.dumps({
- "records":items_nb,
- "rows":rows,
- "page":page_nb,
- "total":items_nb/row_nb + 1,
- })
- return HttpResponse(data, mimetype='text/plain')
- elif data_type == "csv":
- response = HttpResponse(mimetype='text/csv')
- n = datetime.datetime.now()
- filename = u'%s_%s.csv' % (default_name,
- n.strftime('%Y%m%d-%H%M%S'))
- response['Content-Disposition'] = 'attachment; filename=%s'%filename
- writer = csv.writer(response, **CSV_OPTIONS)
- col_names = []
- for field_name in table_cols:
- try:
- field = model._meta.get_field(field_name)
- except:
- col_names.append(u"".encode(ENCODING))
- continue
- col_names.append(unicode(field.verbose_name).encode(ENCODING))
- writer.writerow(col_names)
- for data in datas:
- writer.writerow([val.encode(ENCODING) for val in data[1:]])
- return response
- return HttpResponse(None, mimetype='text/plain')
-
- return func
-
-def show_item(model, name):
- def func(request, pk, **dct):
- try:
- item = model.objects.get(pk=pk)
- except ObjectDoesNotExist:
- return HttpResponse(None)
- doc_type = 'type' in dct and dct.pop('type')
- date = 'date' in dct and dct.pop('date')
- dct['window_id'] = "%s-%d-%s" % (name, item.pk,
- datetime.datetime.now().strftime('%M%s'))
- if date:
- try:
- date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f')
- item = item.get_previous(date=date)
- assert item != None
- except (ValueError, AssertionError):
- return HttpResponse(None, mimetype='text/plain')
- dct['previous'] = item._previous
- dct['next'] = item._next
- else:
- historized = item.history.all()
- if historized:
- item.history_date = historized[0].history_date
- if len(historized) > 1:
- dct['previous'] = historized[1].history_date
- dct['item'], dct['item_name'] = item, name
- context_instance = RequestContext(request)
- context_instance.update(dct)
- n = datetime.datetime.now()
- filename = u'%s_%s_%s' % (name, slugify(unicode(item)),
- n.strftime('%Y%m%d-%H%M%S'))
- if doc_type == "odt" and settings.XHTML2ODT_PATH and \
- settings.ODT_TEMPLATE:
- tpl = loader.get_template('sheet_%s.html' % name)
- content = tpl.render(context_instance)
- try:
- tidy_options = dict(output_xhtml=1, add_xml_decl=1, indent=1,
- tidy_mark=0, output_encoding='utf8', doctype='auto',
- wrap=0, char_encoding='utf8')
- html = str(tidy.parseString(content.encode('utf-8'),
- **tidy_options))
- html = html.replace("&nbsp;", "&#160;")
- html = re.sub('<pre([^>]*)>\n', '<pre\\1>', html)
-
- odt = NamedTemporaryFile()
- options = optparse.Values()
- options.with_network = True
- for k, v in (('input', ''),
- ('output', odt.name),
- ('template', settings.ODT_TEMPLATE),
- ('with_network', True),
- ('top_header_level', 1),
- ('img_width', '8cm'),
- ('img_height', '6cm'),
- ('verbose', False),
- ('replace_keyword', 'ODT-INSERT'),
- ('cut_start', 'ODT-CUT-START'),
- ('htmlid', None),
- ('url', "#")):
- setattr(options, k, v)
- odtfile = xhtml2odt.ODTFile(options)
- odtfile.open()
- odtfile.import_xhtml(html)
- odtfile = odtfile.save()
- except xhtml2odt.ODTExportError, ex:
- return HttpResponse(content, content_type="application/xhtml")
- response = HttpResponse(
- mimetype='application/vnd.oasis.opendocument.text')
- response['Content-Disposition'] = 'attachment; filename=%s.odt' % \
- filename
- response.write(odtfile)
- return response
- elif doc_type == 'pdf':
- tpl = loader.get_template('sheet_%s_pdf.html' % name)
- content = tpl.render(context_instance)
- result = StringIO.StringIO()
- html = content.encode('utf-8')
- html = html.replace("<table", "<pdf:nextpage/><table repeat='1'")
- pdf = pisa.pisaDocument(StringIO.StringIO(html), result)
- response = HttpResponse(result.getvalue(),
- mimetype='application/pdf')
- response['Content-Disposition'] = 'attachment; filename=%s.pdf' % \
- filename
- if not pdf.err:
- return response
- return HttpResponse(content, content_type="application/xhtml")
- else:
- tpl = loader.get_template('sheet_%s_window.html' % name)
- content = tpl.render(context_instance)
- return HttpResponse(content, content_type="application/xhtml")
- return func
-
-def revert_item(model):
- def func(request, pk, date, **dct):
- try:
- item = model.objects.get(pk=pk)
- date = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%f')
- item.rollback(date)
- except (ObjectDoesNotExist, ValueError, HistoryError):
- return HttpResponse(None, mimetype='text/plain')
- return HttpResponse("True", mimetype='text/plain')
- return func
-
-
-get_file = get_item(models.File, 'get_file', 'file')
-show_file = show_item(models.File, 'file')
-revert_file = revert_item(models.File)
-
-def autocomplete_operation(request, non_closed=True):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_base.view_own_operation',
- models.Operation)
- and not person_types.rights.filter(wizard__url_name='operation_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(towns__name__icontains=q)
- try:
- value = int(q)
- extra = extra | Q(year=q) | Q(operation_code=q)
- except ValueError:
- pass
- query = query & extra
- if non_closed:
- query = query & Q(end_date__isnull=True)
- limit = 15
- operations = models.Operation.objects.filter(query)[:limit]
- data = json.dumps([{'id':operation.pk, 'value':unicode(operation)}
- for operation in operations])
- return HttpResponse(data, mimetype='text/plain')
-
-def get_available_operation_code(request, year=None):
- if not request.user.has_perm('ishtar_base.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_base.view_own_operation',
- models.Operation):
- return HttpResponse(mimetype='text/plain')
- data = json.dumps({'id':models.Operation.get_available_operation_code(year)})
- return HttpResponse(data, mimetype='text/plain')
-
-get_operation = get_item(models.Operation, 'get_operation', 'operation',
- bool_fields = ['end_date__isnull'],
- extra_request_keys={'common_name':'common_name__icontains',
- 'end_date':'end_date__isnull',
- 'year_index':('year', 'operation_code')})
-show_operation = show_item(models.Operation, 'operation')
-revert_operation = revert_item(models.Operation)
-
-get_operationsource = get_item(models.OperationSource,
- 'get_operationsource', 'operationsource',
- extra_request_keys={'operation__towns':'operation__towns__pk',
- 'operation__operation_type':'operation__operation_type__pk',
- 'operation__year':'operation__year'})
-
-get_administrativeactfile = get_item(models.AdministrativeAct,
- 'get_administrativeactfile', 'administrativeactfile',
- extra_request_keys={'associated_file__towns':'associated_file__towns__pk',
- 'operation__towns':'operation__towns__pk',
- 'act_type__intented_to':'act_type__intented_to'})
-get_administrativeactop = get_item(models.AdministrativeAct,
- 'get_administrativeactop', 'administrativeactop',
- extra_request_keys={'associated_file__towns':'associated_file__towns__pk',
- 'operation__towns':'operation__towns__pk',
- 'act_type__intented_to':'act_type__intented_to'})
-
-def autocomplete_organization(request, orga_type=None):
- person_types = request.user.ishtaruser.person.person_type
- if (not request.user.has_perm('ishtar_base.view_organization',
- models.Organization) and \
- not request.user.has_perm('ishtar_base.view_own_organization',
- models.Organization)
- and not person_types.rights.filter(wizard__url_name='person_search'
- ).count()):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q)
- query = query & extra
- if orga_type:
- try:
- typs = [int(tp) for tp in orga_type.split('_') if tp]
- typ = models.OrganizationType.objects.filter(pk__in=typs).all()
- query = query & Q(organization_type__in=typ)
- except (ValueError, ObjectDoesNotExist):
- pass
- limit = 15
- organizations = models.Organization.objects.filter(query)[:limit]
- data = json.dumps([{'id':org.pk, 'value':unicode(org)}
- for org in organizations])
- return HttpResponse(data, mimetype='text/plain')
-
-show_contextrecord = show_item(models.ContextRecord, 'contextrecord')
-get_contextrecord = get_item(models.ContextRecord,
- 'get_contextrecord', 'contextrecord',
- extra_request_keys={'parcel__town':'parcel__town__pk',
- 'operation__year':'operation__year__contains',
- 'datings__period':'datings__period__pk'},)
-get_contextrecordsource = get_item(models.ContextRecordSource,
- 'get_contextrecordsource', 'contextrecordsource',
- extra_request_keys={
- 'context_record__parcel__town':'context_record__parcel__town__pk',
- 'context_record__operation__year':'context_record__operation__year',
- 'context_record__datings__period':'context_record__datings__period__pk',
- 'context_record__unit':'context_record__unit__pk',
- })
-get_archaeologicalitem = get_item(models.Item,
- 'get_archaeologicalitem', 'item',
- bool_fields = ['base_items__is_isolated'],
- base_request={'downstream_treatment__isnull':True},
- extra_request_keys={
-'base_items__context_record__parcel__town':
- 'base_items__context_record__parcel__town',
-'base_items__context_record__operation__year':
- 'base_items__context_record__operation__year__contains',
-'base_items__context_record__operation__code_patriarche':
- 'base_items__context_record__operation__code_patriarche',
-'dating__period':'dating__period__pk',
-'base_items__item__description':'base_items__item__description__icontains',
-'base_items__is_isolated':'base_items__is_isolated'})
-get_itemsource = get_item(models.ItemSource,
- 'get_itemsource', 'itemsource',
- extra_request_keys={
-'item__context_record__operation__year':'item__context_record__operation__year',
-'item__dating__period':'item__dating__period__pk',
-'item__description':'item__description__icontains',
- })
-get_container = get_item(models.Container,
- 'get_container', 'container',
- extra_request_keys={
-'location':'location__pk',
-'container_type':'container_type__pk',
-'reference':'reference__icontains',
- })
-
-def autocomplete_warehouse(request):
- if not request.user.has_perm('ishtar_base.view_warehouse', models.Warehouse)\
- and not request.user.has_perm('ishtar_base.view_own_warehouse',
- models.Warehouse) :
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(name__icontains=q) | \
- Q(warehouse_type__label__icontains=q)
- query = query & extra
- limit = 15
- warehouses = models.Warehouse.objects.filter(query)[:limit]
- data = json.dumps([{'id':warehouse.pk, 'value':unicode(warehouse)}
- for warehouse in warehouses])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_author(request):
- if not request.user.has_perm('ishtar_base.view_author', models.Author)\
- and not request.user.has_perm('ishtar_base.view_own_author',
- models.Warehouse) :
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(person__name__icontains=q) | \
- Q(person__surname__icontains=q) | \
- Q(person__email__icontains=q) | \
- Q(author_type__label__icontains=q)
- query = query & extra
- limit = 15
- authors = models.Author.objects.filter(query)[:limit]
- data = json.dumps([{'id':author.pk, 'value':unicode(author)}
- for author in authors])
- return HttpResponse(data, mimetype='text/plain')
-
-def autocomplete_container(request):
- if not request.user.has_perm('ishtar_base.view_warehouse',
- models.Warehouse)\
- and not request.user.has_perm('ishtar_base.view_own_warehouse',
- models.Warehouse):
- return HttpResponse(mimetype='text/plain')
- if not request.GET.get('term'):
- return HttpResponse(mimetype='text/plain')
- q = request.GET.get('term')
- query = Q()
- for q in q.split(' '):
- extra = Q(container_type__label__icontains=q) | \
- Q(container_type__reference__icontains=q) | \
- Q(reference__icontains=q) | \
- Q(location__name=q) | \
- Q(location__town=q)
- query = query & extra
- limit = 15
- containers = models.Container.objects.filter(query)[:limit]
- data = json.dumps([{'id':container.pk, 'value':unicode(container)}
- for container in containers])
- return HttpResponse(data, mimetype='text/plain')
-
-def new_item(model):
- def func(request, parent_name):
- model_name = model._meta.object_name
- if not check_permission(request, 'add_'+model_name.lower()):
- not_permitted_msg = ugettext(u"Operation not permitted.")
- return HttpResponse(not_permitted_msg)
- frm = getattr(ishtar_forms, model_name + 'Form')
- dct = {'title':unicode(_(u'New %s' % model_name.lower()))}
- if request.method == 'POST':
- dct['form'] = frm(request.POST)
- if dct['form'].is_valid():
- new_item = dct['form'].save(request.user)
- dct['new_item_label'] = unicode(new_item)
- dct['new_item_pk'] = new_item.pk
- dct['parent_name'] = parent_name
- dct['parent_pk'] = parent_name
- if dct['parent_pk'] and '_select_' in dct['parent_pk']:
- parents = dct['parent_pk'].split('_')
- dct['parent_pk'] = "_".join([parents[0]] + parents[2:])
- return render_to_response('window.html', dct,
- context_instance=RequestContext(request))
- else:
- dct['form'] = frm()
- return render_to_response('window.html', dct,
- context_instance=RequestContext(request))
- return func
-
-new_warehouse = new_item(models.Warehouse)
-new_person = new_item(models.Person)
-new_organization = new_item(models.Organization)
-new_author = new_item(models.Author)
-new_container = new_item(models.Container)
-
-def action(request, action_slug, obj_id=None, *args, **kwargs):
- """
- Action management
- """
- if not check_permission(request, action_slug, obj_id):
- not_permitted_msg = ugettext(u"Operation not permitted.")
- return HttpResponse(not_permitted_msg)
- request.session['CURRENT_ACTION'] = action_slug
- associated_wizard = action_slug + '_wizard'
- dct = {}
- globals_dct = globals()
- if action_slug in globals_dct:
- return globals_dct[action_slug](request, dct, obj_id, *args, **kwargs)
- elif hasattr(ishtar_forms, action_slug + "_wizard"):
- return getattr(ishtar_forms, action_slug+"_wizard")(request, *args,
- **kwargs)
- return render_to_response('index.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_main(request, dct, obj_id=None, *args, **kwargs):
- """
- Main dashboard
- """
- dct = {'items':[
- (_(u"Archaeological files"), models.Dashboard(models.File)),
- (_(u"Operations"), models.Dashboard(models.Operation)),
- (_(u"Context records"), models.Dashboard(models.ContextRecord)),
- (_(u"Archaeological items"), models.Dashboard(models.Item)),
- ],
- 'ishtar_users':models.UserDashboard()}
- return render_to_response('dashboard_main.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_file(request, dct, obj_id=None, *args, **kwargs):
- """
- Main dashboard
- """
- dct = {'dashboard': models.FileDashboard()}
- return render_to_response('dashboard_file.html', dct,
- context_instance=RequestContext(request))
-
-def dashboard_operation(request, dct, obj_id=None, *args, **kwargs):
- """
- Operation dashboard
- """
- dct = {'dashboard': models.OperationDashboard()}
- return render_to_response('dashboard_operation.html', dct,
- context_instance=RequestContext(request))
diff --git a/ishtar/ishtar_base/widgets.py b/ishtar/ishtar_base/widgets.py
deleted file mode 100644
index 00f185b5a..000000000
--- a/ishtar/ishtar_base/widgets.py
+++ /dev/null
@@ -1,367 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
-# Copyright (C) 2007 skam <massimo dot scamarcia at gmail.com>
-# (http://djangosnippets.org/snippets/233/)
-
-# 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 import forms
-from django.template import Context, loader
-from django.utils.safestring import mark_safe
-from django.forms.widgets import flatatt
-from django.utils.encoding import smart_unicode
-from django.utils.html import escape
-from django.utils.simplejson import JSONEncoder
-from django.core.urlresolvers import resolve, reverse
-from django.utils.translation import ugettext_lazy as _
-from django.db.models import fields
-
-from ishtar import settings
-import models
-
-class DeleteWidget(forms.CheckboxInput):
- def render(self, name, value, attrs=None):
- final_attrs = flatatt(self.build_attrs(attrs, name=name,
- value='1'))
- output = ['<tr class="delete"><td colspan="2">']
- output.append(u"<button%s>%s</button>" % (final_attrs, _("Delete")))
- output.append('</td></tr>')
- return mark_safe('\n'.join(output))
-
-class SquareMeterWidget(forms.TextInput):
- def render(self, name, value, attrs=None):
- if not value:
- value = u""
- final_attrs = flatatt(self.build_attrs(attrs, name=name, value=value))
- output = u'<input class="area_widget" type="text"%s> %s '\
- u'(<span id="ha_%s">0</span> ha)' % (final_attrs,
- settings.SURFACE_UNIT_LABEL, attrs['id'])
- output += """
-<script type="text/javascript"><!--//
- function evaluate_%(safe_id)s(){
- value = parseFloat($("#%(id)s").val());
- if(!isNaN(value)){
- value = value/10000;
- } else {
- value = 0;
- }
- $("#ha_%(id)s").html(value);
- }
- $("#%(id)s").keyup(evaluate_%(safe_id)s);
- $(document).ready(evaluate_%(safe_id)s());
-//--></script>
-""" % {"id":attrs['id'], "safe_id":attrs['id'].replace('-', '_')}
- return mark_safe(output)
-
-AreaWidget = forms.TextInput
-if settings.SURFACE_UNIT == 'square-metre':
- global AreaWidget
- AreaWidget = SquareMeterWidget
-
-class JQueryDate(forms.TextInput):
- def __init__(self, *args, **kwargs):
- super(JQueryDate, self).__init__(*args, **kwargs)
- if 'class' not in self.attrs:
- self.attrs['class'] = ''
- self.attrs['class'] = 'date-pickup'
-
- def render(self, name, value=None, attrs=None):
- rendered = super(JQueryDate, self).render(name, value, attrs)
- # use window.onload to be sure that datepicker don't interfere
- # with autocomplete fields
- rendered += """
-<script type="text/javascript"><!--//
- $(window).load(function() {
- $(".date-pickup").datepicker($.datepicker.regional["%(country)s"]);
- var val = $("#id_%(name)s").val();
- if(val){
- var dt = $.datepicker.parseDate('yy-mm-dd', val);
- val = $.datepicker.formatDate(
- $.datepicker.regional["%(country)s"]['dateFormat'],
- dt);
- $("#id_%(name)s").val(val);
- }
- });
-//--></script>
-""" % {"name":name, "country":settings.COUNTRY}
- return rendered
-
-class JQueryAutoComplete(forms.TextInput):
- def __init__(self, source, associated_model=None, options={}, attrs={},
- new=False):
- """
- Source can be a list containing the autocomplete values or a
- string containing the url used for the request.
- """
- self.options = None
- self.attrs = {}
- self.source = source
- self.associated_model = associated_model
- if len(options) > 0:
- self.options = JSONEncoder().encode(options)
- self.attrs.update(attrs)
- self.new = new
-
- def render_js(self, field_id):
- if isinstance(self.source, list):
- source = JSONEncoder().encode(self.source)
- elif isinstance(self.source, str) or isinstance(self.source, unicode):
- source = "'%s'" % escape(self.source)
- else:
- try:
- source = "'" + unicode(self.source) + "'"
- except:
- raise ValueError('source type is not valid')
- options = 'source : ' + source
- options += ''', select: function( event, ui ) {
- if(ui.item){
- $('#id_%s').val(ui.item.id);
- } else {
- $('#id_%s').val(null);
- }
- }, minLength: 2
- ''' % (field_id, field_id)
- if self.options:
- options += ',%s' % self.options
-
- js = u'$(\'#id_select_%s\').autocomplete({%s});\n' % (field_id, options)
- js += u'''$(\'#id_select_%s\').live('click', function(){
- $('#id_%s').val(null);
- $('#id_select_%s').val(null);
-});''' % (field_id, field_id, field_id)
- return js
-
- def render(self, name, value=None, attrs=None):
- attrs_hidden = self.build_attrs(attrs, name=name)
- attrs_select = self.build_attrs(attrs)
-
- if value:
- val = escape(smart_unicode(value))
- attrs_hidden['value'] = val
- attrs_select['value'] = val
- if self.associated_model:
- try:
- attrs_select['value'] = unicode(self.associated_model.\
-objects.get(pk=value))
- except:
- attrs_select['value'] = ""
- if not self.attrs.has_key('id'):
- attrs_hidden['id'] = 'id_%s' % name
- attrs_select['id'] = 'id_select_%s' % name
- if 'class' not in attrs_select:
- attrs_select['class'] = 'autocomplete'
- new = ''
- if self.new:
- model_name = self.associated_model._meta.object_name.lower()
- url_new = reverse('new-' + model_name, args=[attrs_select['id']])
- new = u' <a href="#" class="add-button" '\
- u'onclick="open_window(\'%s\');">+</a>' % url_new
- html = u'''<input%(attrs_select)s/>%(new)s\
-<input type="hidden"%(attrs_hidden)s/>\
- <script type="text/javascript"><!--//
- $(function() {%(js)s});//--></script>
- ''' % {
- 'attrs_select' : flatatt(attrs_select),
- 'attrs_hidden' : flatatt(attrs_hidden),
- 'js' : self.render_js(name),
- 'new':new
- }
- return html
-
-class JQueryJqGrid(forms.RadioSelect):
- COL_TPL = "{name:'%(idx)s', index:'%(idx)s', sortable:true}"
- class Media:
- js = ['%s/js/i18n/grid.locale-%s.js' % (settings.MEDIA_URL,
- settings.COUNTRY),
- '%s/js/jquery.jqGrid.min.js' % settings.MEDIA_URL,
- ]
- css = {'all':['%s/media/ui.jqgrid.css' % settings.MEDIA_URL,
- ]}
-
- def __init__(self, source, form, associated_model, attrs={},
- table_cols='TABLE_COLS', multiple=False, multiple_cols=[2], new=False,
- new_message="", source_full=None):
- self.source = source
- self.form = form
- self.attrs = attrs
- self.associated_model = associated_model
- self.table_cols = table_cols
- self.multiple = multiple
- self.multiple_cols = multiple_cols
- self.new, self.new_message = new, new_message
- self.source_full = source_full
-
- def render(self, name, value=None, attrs=None):
- t = loader.get_template('form_snippet.html')
- rendered = t.render(Context({'form':self.form}))
- rendered += u"\n</table>\n"\
- u"<button id='search_%s' class='submit'>%s</button>" % (
- name, unicode(_("Search")))
- if self.new:
- model_name = self.associated_model._meta.object_name.lower()
- url_new = reverse('new-' + model_name)
- rendered += u'<p><a href="#" onclick="open_window(\'%s\');">'\
- u'%s</a></p>' % (url_new, unicode(self.new_message))
- rendered += "\n<h4>%s</h4>\n" % unicode(_("Search and select an item"))
- extra_cols = []
- col_names, col_idx = [], []
- for k in self.form.fields:
- field = self.form.fields[k]
- col_idx.append(u'"%s"' % k)
- for field_name in getattr(self.associated_model, self.table_cols):
- field = self.associated_model
- keys = field_name.split('.')
- field_verbose_name = ""
- for key in keys:
- if hasattr(field, 'rel'):
- field = field.rel.to
- try:
- field = field._meta.get_field(key)
- field_verbose_name = field.verbose_name
- field_name = field.name
- except fields.FieldDoesNotExist:
- if hasattr(field, key + '_lbl'):
- field_name = key
- field_verbose_name = getattr(field, key + '_lbl')
- else:
- continue
- col_names.append(u'"%s"' % field_verbose_name)
- extra_cols.append(self.COL_TPL % {'idx':field_name})
- col_names = col_names and ",\n".join(col_names) or ""
- col_idx = col_idx and ",\n".join(col_idx) or ""
- extra_cols = extra_cols and ",\n".join(extra_cols) or ""
- rendered += u"<table id='grid_%s' class='jqgrid'></table>\n"\
- u"<div id='pager_%s'></div>\n"% (name, name)
- encoding = settings.ENCODING or 'utf-8'
- rendered += u"<div id='foot_%s' class='gridfooter'>\n" % name
- if unicode(self.source_full):
- rendered += u"%s (%s) <a href='%scsv' target='_blank'>%s</a> - "\
- u"<a href='%scsv' target='_blank'>%s</a>\n" % (
- unicode(_("Export as CSV")), encoding, unicode(self.source),
- unicode(_(u"simple")), unicode(self.source_full),
- unicode(_(u"full")),)
- else:
- rendered += u'<a href="%scsv" target="_blank">%s (%s)</a>\n' % (
- unicode(self.source), unicode(_("Export as CSV")), encoding)
- rendered += "</div>\n"
- if self.multiple:
- rendered += u'<input type="button" id="add_button_%s" value="%s"/>'\
- u'<ul id="selectmulti_%s" class="selectmulti">\n</ul>\n' % (
- name, unicode(_("Add")), name)
- rendered += '<input type="hidden" id="hidden_%s" name="%s"/>\n' % (name,
- name)
- dct = {'name':name,
- 'col_names':col_names,
- 'extra_cols':extra_cols,
- 'source':unicode(self.source),
- 'col_idx':col_idx,
- 'no_result':unicode(_("No results")),
- 'loading':unicode(_("Loading...")),
- 'remove':unicode(_(u"Remove")),
- 'sname':name.replace('-', ''),
- 'multi_cols': ",".join((u'"%d"' % col \
- for col in self.multiple_cols))
- }
- rendered += """<script type="text/javascript">
- var query_vars = new Array(%(col_idx)s);
- var selItems_%(sname)s = new Array();
- jQuery(document).ready(function(){
- jQuery("#search_%(name)s").click(function (){
- var data = "";
- for (idx in query_vars)
- {
- var key = query_vars[idx];
- var val = jQuery("#id_"+key).val();
- if (val){
- if (data) data += "&";
- data += key + "=" + val;
- }
- }
- var mygrid = jQuery("#grid_%(name)s");
- var url = "%(source)s?submited=1&amp;" + data;
- mygrid.setGridParam({url:url});
- mygrid.trigger("reloadGrid");
- return false;
- });
-
- jQuery("#grid_%(name)s").jqGrid({
- url:'%(source)s',
- datatype: "json",
- mtype: 'GET',
- colNames:['id', '', %(col_names)s],
- colModel:[
- {name:'id', index:'id', hidden:true},
- {name:'link', index:'link', width:80},
- %(extra_cols)s
- ],
- sortname: 'value',
- viewrecords: true,
- sortorder: "asc",
- emptyrecords: "%(no_result)s",
- loadtext: "%(loading)s",
- pager: '#pager_%(name)s',
- width:740,
- rowNum:20,
- jsonReader : {repeatitems: false},
- });
- """ % dct
- if self.multiple:
- rendered += """
- jQuery("#add_button_%(name)s").click(function (){
- var mygrid = jQuery("#grid_%(name)s");
- var idx = mygrid.getGridParam('selrow');
- var lbl_cols = new Array(%(multi_cols)s);
- var label = "";
- for (var id in lbl_cols){
- if(id == 1){
- label += " (";
- }else if (id > 1){
- label += " ; ";
- }
- label += mygrid.getCell(idx, lbl_cols[id]);
- }
- if (id > 0){
- label += ")";
- }
- for (id in selItems_%(sname)s){
- if(selItems_%(sname)s[id] == idx){
- return false;
- }
- }
- selItems_%(sname)s.push(idx);
- jQuery("#selectmulti_%(name)s").append(
- "<li id='selected_%(name)s_"+idx+"'>\
- <a href='#' class='remove' \
- onclick=\\"multiRemoveItem(selItems_%(sname)s, '%(name)s', "+ idx +");\
- return false;\\" title=\\"%(remove)s\\">X</a>" + label + "</li>");
- return true;
- });
- jQuery("#submit_form").click(function (){
- jQuery("#hidden_%(name)s").val(selItems_%(sname)s);
- return true;
- });
- """ % dct
- else:
- rendered += """
- jQuery("#submit_form").click(function (){
- var mygrid = jQuery("#grid_%(name)s");
- jQuery("#hidden_%(name)s").val(mygrid.getGridParam('selrow'));
- return true;
- });
- """ % dct
- rendered += "});\n</script>\n"
- return mark_safe(rendered)
-