summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/admin.py56
-rw-r--r--archaeological_context_records/forms.py (renamed from ishtar_common/forms_context_records.py)0
-rw-r--r--archaeological_context_records/ishtar_menu.py67
-rw-r--r--archaeological_context_records/migrations/0001_initial.py70
-rw-r--r--archaeological_context_records/models.py49
-rw-r--r--archaeological_context_records/urls.py57
-rw-r--r--archaeological_context_records/views.py36
-rw-r--r--archaeological_files/admin.py42
-rw-r--r--archaeological_files/forms.py (renamed from ishtar_common/forms_files.py)26
-rw-r--r--archaeological_files/ishtar_menu.py8
-rw-r--r--archaeological_files/models.py124
-rw-r--r--archaeological_files/urls.py64
-rw-r--r--archaeological_files/views.py66
-rw-r--r--archaeological_finds/admin.py75
-rw-r--r--archaeological_finds/forms.py (renamed from ishtar_common/forms_items.py)24
-rw-r--r--archaeological_finds/ishtar_menu.py67
-rw-r--r--archaeological_finds/migrations/0001_initial.py188
-rw-r--r--archaeological_finds/models.py134
-rw-r--r--archaeological_finds/urls.py52
-rw-r--r--archaeological_finds/views.py43
-rw-r--r--archaeological_operations/admin.py72
-rw-r--r--archaeological_operations/forms.py (renamed from ishtar_common/forms_operations.py)66
-rw-r--r--archaeological_operations/ishtar_menu.py98
-rw-r--r--archaeological_operations/migrations/0001_initial.py54
-rw-r--r--archaeological_operations/models.py500
-rw-r--r--archaeological_operations/urls.py75
-rw-r--r--archaeological_operations/views.py97
-rw-r--r--archaeological_warehouse/admin.py51
-rw-r--r--archaeological_warehouse/ishtar_menu.py40
-rw-r--r--archaeological_warehouse/models.py1
-rw-r--r--archaeological_warehouse/urls.py45
-rw-r--r--archaeological_warehouse/views.py81
-rw-r--r--example_project/urls.py21
-rw-r--r--ishtar_common/admin.py158
-rw-r--r--ishtar_common/context_processors.py19
-rw-r--r--ishtar_common/forms_common.py52
-rw-r--r--ishtar_common/menus.py132
-rw-r--r--ishtar_common/models.py568
-rw-r--r--ishtar_common/templates/sheet_contextrecord.html10
-rw-r--r--ishtar_common/templates/sheet_operation.html10
-rw-r--r--ishtar_common/urls.py157
-rw-r--r--ishtar_common/views.py199
42 files changed, 2147 insertions, 1607 deletions
diff --git a/archaeological_context_records/admin.py b/archaeological_context_records/admin.py
new file mode 100644
index 000000000..5985f4462
--- /dev/null
+++ b/archaeological_context_records/admin.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf import settings
+from django.contrib import admin
+
+from ishtar_common.admin import HistorizedObjectAdmin
+
+import models
+
+class 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)
+
+basic_models = [models.DatingType, models.DatingQuality,
+ models.Unit, models.ActivityType, models.IdentificationType]
+
+for model in basic_models:
+ admin.site.register(model)
diff --git a/ishtar_common/forms_context_records.py b/archaeological_context_records/forms.py
index 816782bd8..816782bd8 100644
--- a/ishtar_common/forms_context_records.py
+++ b/archaeological_context_records/forms.py
diff --git a/archaeological_context_records/ishtar_menu.py b/archaeological_context_records/ishtar_menu.py
new file mode 100644
index 000000000..c471a75a8
--- /dev/null
+++ b/archaeological_context_records/ishtar_menu.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.utils.translation import ugettext_lazy as _
+
+from archaeological_operations.models import Operation
+from ishtar_common.menu_base import SectionItem, MenuItem
+
+import models
+
+MENU_SECTIONS = [
+ (40, 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('record_source', _(u"Documentation"),
+ childs=[
+ MenuItem('record_source_creation',
+ _(u"Add"),
+ model=models.ContextRecordSource,
+ access_controls=['change_contextrecord',
+ 'change_own_contextrecord']),
+ MenuItem('record_source_modification',
+ _(u"Modification"),
+ model=models.ContextRecordSource,
+ access_controls=['change_contextrecord',
+ 'change_own_contextrecord']),
+ MenuItem('record_source_deletion',
+ _(u"Deletion"),
+ model=models.ContextRecordSource,
+ access_controls=['change_contextrecord',
+ 'change_own_contextrecord']),
+ ])
+ ])
+ )
+]
+
diff --git a/archaeological_context_records/migrations/0001_initial.py b/archaeological_context_records/migrations/0001_initial.py
index 09ee30efe..599a6d4f7 100644
--- a/archaeological_context_records/migrations/0001_initial.py
+++ b/archaeological_context_records/migrations/0001_initial.py
@@ -8,32 +8,6 @@ from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
- # Adding model 'Parcel'
- db.create_table('archaeological_context_records_parcel', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
- ('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
- ('associated_file', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='parcels', null=True, to=orm['archaeological_files.File'])),
- ('operation', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='parcels', null=True, to=orm['archaeological_operations.Operation'])),
- ('year', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
- ('town', self.gf('django.db.models.fields.related.ForeignKey')(related_name='parcels', to=orm['ishtar_common.Town'])),
- ('section', self.gf('django.db.models.fields.CharField')(max_length=4)),
- ('parcel_number', self.gf('django.db.models.fields.CharField')(max_length=6)),
- ))
- db.send_create_signal('archaeological_context_records', ['Parcel'])
-
- # Adding model 'ParcelOwner'
- db.create_table('archaeological_context_records_parcelowner', (
- ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
- ('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
- ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Person'])),
- ('parcel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_context_records.Parcel'])),
- ('start_date', self.gf('django.db.models.fields.DateField')()),
- ('end_date', self.gf('django.db.models.fields.DateField')()),
- ))
- db.send_create_signal('archaeological_context_records', ['ParcelOwner'])
-
# Adding model 'DatingType'
db.create_table('archaeological_context_records_datingtype', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
@@ -133,7 +107,7 @@ class Migration(SchemaMigration):
db.create_table('archaeological_context_records_contextrecord', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
- ('parcel', self.gf('django.db.models.fields.related.ForeignKey')(related_name='context_record', to=orm['archaeological_context_records.Parcel'])),
+ ('parcel', self.gf('django.db.models.fields.related.ForeignKey')(related_name='context_record', to=orm['archaeological_operations.Parcel'])),
('operation', self.gf('django.db.models.fields.related.ForeignKey')(related_name='context_record', to=orm['archaeological_operations.Operation'])),
('label', self.gf('django.db.models.fields.CharField')(max_length=200)),
('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
@@ -185,12 +159,6 @@ class Migration(SchemaMigration):
def backwards(self, orm):
- # Deleting model 'Parcel'
- db.delete_table('archaeological_context_records_parcel')
-
- # Deleting model 'ParcelOwner'
- db.delete_table('archaeological_context_records_parcelowner')
-
# Deleting model 'DatingType'
db.delete_table('archaeological_context_records_datingtype')
@@ -251,7 +219,7 @@ class Migration(SchemaMigration):
'length': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'operation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Operation']"}),
- 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_context_records.Parcel']"}),
+ 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Parcel']"}),
'taq': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'taq_estimated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'thickness': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
@@ -333,28 +301,6 @@ class Migration(SchemaMigration):
'order': ('django.db.models.fields.IntegerField', [], {}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
- 'archaeological_context_records.parcel': {
- 'Meta': {'object_name': 'Parcel'},
- 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}),
- 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}),
- 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
- 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}),
- 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
- },
- 'archaeological_context_records.parcelowner': {
- 'Meta': {'object_name': 'ParcelOwner'},
- 'end_date': ('django.db.models.fields.DateField', [], {}),
- 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']"}),
- 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_context_records.Parcel']"}),
- 'start_date': ('django.db.models.fields.DateField', [], {})
- },
'archaeological_context_records.unit': {
'Meta': {'object_name': 'Unit'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
@@ -456,6 +402,18 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
+ 'archaeological_operations.parcel': {
+ 'Meta': {'object_name': 'Parcel'},
+ 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}),
+ 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
+ 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
+ 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}),
+ 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
'archaeological_operations.period': {
'Meta': {'object_name': 'Period'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index c47fd3354..75653e78e 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -22,53 +22,8 @@ from django.contrib.gis.db import models
from django.utils.translation import ugettext_lazy as _, ugettext
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
- LightHistorizedItem, HistoricalRecords, OwnPerms, Town, Person, Source
-FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS
-if FILES_AVAILABLE:
- from archaeological_files.models import File
-from archaeological_operations.models import Operation, Period
-
-class Parcel(LightHistorizedItem):
- if FILES_AVAILABLE:
- 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 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
+ HistoricalRecords, OwnPerms, Town, Person, Source
+from archaeological_operations.models import Operation, Period, Parcel
class DatingType(GeneralType):
class Meta:
diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py
new file mode 100644
index 000000000..c42ae2b02
--- /dev/null
+++ b/archaeological_context_records/urls.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf.urls.defaults import *
+"""
+import forms
+
+# forms
+urlpatterns = patterns('',
+ # Context records
+ url(r'record_search/(?P<step>.+)$',
+ forms.record_search_wizard, name='record_search'),
+ url(r'record_creation/(?P<step>.+)$',
+ forms.record_creation_wizard, name='record_creation'),
+ url(r'record_modification/(?P<step>.+)$',
+ forms.record_modification_wizard, name='record_modification'),
+ url(r'record_deletion/(?P<step>.+)$',
+ forms.record_deletion_wizard, name='record_deletion'),
+ url(r'record_source_creation/(?P<step>.+)$',
+ forms.record_source_creation_wizard,
+ name='record_source_creation'),
+ url(r'record_source_modification/(?P<step>.+)$',
+ forms.record_source_modification_wizard,
+ name='record_source_modification'),
+ url(r'record_source_deletion/(?P<step>.+)$',
+ forms.record_source_deletion_wizard,
+ name='record_source_deletion'),
+)
+
+urlpatterns += patterns('archaeological_context_records.views',
+ 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'),
+)
+"""
diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py
new file mode 100644
index 000000000..89a45482b
--- /dev/null
+++ b/archaeological_context_records/views.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from ishtar_common.views import get_item, show_item, revert_item
+import models
+
+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',
+ })
diff --git a/archaeological_files/admin.py b/archaeological_files/admin.py
new file mode 100644
index 000000000..339b19661
--- /dev/null
+++ b/archaeological_files/admin.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf import settings
+from django.contrib import admin
+
+from ishtar_common.admin import HistorizedObjectAdmin
+
+import models
+
+class 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)
+
+basic_models = [models.FileType, models.PermitType]
+if settings.COUNTRY == 'fr':
+ basic_models.append(models.SaisineType)
+for model in basic_models:
+ admin.site.register(model)
diff --git a/ishtar_common/forms_files.py b/archaeological_files/forms.py
index c4c460cee..368c57843 100644
--- a/ishtar_common/forms_files.py
+++ b/archaeological_files/forms.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -23,25 +23,27 @@ Files forms definitions
import datetime
from django import forms
-from django.shortcuts import render_to_response
-from django.template import RequestContext
+from django.conf import settings
from django.core import validators
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Max
+from django.shortcuts import render_to_response
+from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
-from ishtar import settings
-
+from ishtar_common.models import Town
import models
-import widgets
-from forms import Wizard, FinalForm, FormSet, ClosingWizard, \
+from ishtar_common.views import Wizard
+from ishtar_common.forms import FinalForm, FormSet, ClosingWizard, \
ClosingDateFormSelection, SearchWizard, formset_factory, get_now, \
reverse_lazy
-from forms_common import TownFormset, ParcelFormSet, \
+from ishtar_common.forms_common import TownFormset, ParcelFormSet, \
get_town_field, get_person_field
-from forms_operations import OperationAdministrativeActWizard, \
-AdministrativeActOpeForm, AdministrativeActOpeFormSelection, \
-AdministrativeActDeletionWizard, FinalAdministrativeActDeleteForm, is_preventive
+from archaeological_operations.forms import OperationAdministrativeActWizard, \
+ AdministrativeActOpeForm, AdministrativeActOpeFormSelection, \
+ AdministrativeActDeletionWizard, FinalAdministrativeActDeleteForm, \
+ is_preventive
+from ishtar_common import widgets
class FileWizard(Wizard):
model = models.File
@@ -67,7 +69,7 @@ class FileWizard(Wizard):
for k in qdict.keys():
if k.endswith("town") and qdict[k]:
try:
- town = models.Town.objects.get(pk=int(qdict[k]))
+ town = Town.objects.get(pk=int(qdict[k]))
towns.append((town.pk, unicode(town)))
except (ObjectDoesNotExist, ValueError):
pass
diff --git a/archaeological_files/ishtar_menu.py b/archaeological_files/ishtar_menu.py
index 370320f69..398b43f4b 100644
--- a/archaeological_files/ishtar_menu.py
+++ b/archaeological_files/ishtar_menu.py
@@ -21,14 +21,13 @@ from django.utils.translation import ugettext_lazy as _
from archaeological_operations.models import Operation
from ishtar_common.menu_base import SectionItem, MenuItem
-from ishtar_common.models import AdministrativeAct
-import models
+from archaeological_operations.models import AdministrativeAct
-ORDER = 20
+import models
MENU_SECTIONS = [
- SectionItem('file_management', _(u"Archaeological file"),
+ (20, SectionItem('file_management', _(u"Archaeological file"),
childs=[
MenuItem('file_search', _(u"Search"),
model=models.File,
@@ -62,4 +61,5 @@ MENU_SECTIONS = [
access_controls=['delete_file', 'delete_own_file']),
],),
]),
+ )
]
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index 68a65f6de..90f60fe64 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -24,7 +24,8 @@ from django.contrib.gis.db import models
from django.utils.translation import ugettext_lazy as _, ugettext
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
- HistoricalRecords, OwnPerms, Person, Organization, Department, Town
+ HistoricalRecords, OwnPerms, Person, Organization, Department, Town, \
+ Dashboard
class FileType(GeneralType):
class Meta:
@@ -183,3 +184,124 @@ class FileByDepartment(models.Model):
class Meta:
managed = False
db_table = 'file_department'
+
+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')
diff --git a/archaeological_files/urls.py b/archaeological_files/urls.py
new file mode 100644
index 000000000..e32ab8294
--- /dev/null
+++ b/archaeological_files/urls.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf.urls.defaults import *
+
+"""
+import forms
+
+# forms
+urlpatterns = patterns('',
+ url(r'file_search/(?P<step>.+)$',
+ forms.file_search_wizard, name='file_search'),
+ url(r'file_creation/(?P<step>.+)$',
+ forms.file_creation_wizard, name='file_creation'),
+ url(r'file_modification/(?P<step>.+)$',
+ forms.file_modification_wizard, name='file_modification'),
+ url(r'file_closing/(?P<step>.+)$',
+ forms.file_closing_wizard, name='file_closing'),
+ url(r'file_deletion/(?P<step>.+)$',
+ forms.file_deletion_wizard, name='file_deletion'),
+ url(r'file_administrativeactfile/(?P<step>.+)$',
+ forms.file_administrativeactfile_wizard,
+ name='file_administrativeactfile'),
+ url(r'file_administrativeactfile_modification/(?P<step>.+)$',
+ forms.file_administrativeactfile_modification_wizard,
+ name='file_administrativeactfile_modification'),
+ url(r'file_administrativeactfile_deletion/(?P<step>.+)$',
+ forms.file_administrativeactfile_deletion_wizard,
+ name='file_administrativeactfile_deletion'),
+)
+
+urlpatterns += patterns('archaeological_files.views',
+ 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'),
+)
+"""
diff --git a/archaeological_files/views.py b/archaeological_files/views.py
new file mode 100644
index 000000000..02332b629
--- /dev/null
+++ b/archaeological_files/views.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import json
+
+from django.db.models import Q
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+
+from ishtar_common.views import get_item, show_item, revert_item
+import models
+
+def autocomplete_file(request):
+ person_types = request.user.ishtaruser.person.person_type
+ if (not request.user.has_perm('ishtar_common.view_file', models.File) and \
+ not request.user.has_perm('ishtar_common.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')
+
+get_file = get_item(models.File, 'get_file', 'file')
+show_file = show_item(models.File, 'file')
+revert_file = revert_item(models.File)
+
+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))
+
diff --git a/archaeological_finds/admin.py b/archaeological_finds/admin.py
new file mode 100644
index 000000000..096f05bf3
--- /dev/null
+++ b/archaeological_finds/admin.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf import settings
+from django.contrib import admin
+
+from ishtar_common.admin import HistorizedObjectAdmin
+
+import models
+
+class BaseFindAdmin(HistorizedObjectAdmin):
+ list_display = ('label', 'context_record', 'is_isolated')
+ search_fields = ('label', 'context_record__parcel__operation__name',)
+ model = models.BaseFind
+
+admin.site.register(models.BaseFind, BaseFindAdmin)
+
+class FindAdmin(HistorizedObjectAdmin):
+ list_display = ('label', 'material_type', 'dating', 'volume', 'weight',
+ 'find_number',)
+ list_filter = ('material_type',)
+ search_fields = ('label', "dating__period__label")
+ model = models.Find
+
+admin.site.register(models.Find, FindAdmin)
+
+class FindSourceAdmin(admin.ModelAdmin):
+ list_display = ('find', 'title', 'source_type',)
+ list_filter = ('source_type',)
+ search_fields = ('title', )
+ model = models.FindSource
+
+admin.site.register(models.FindSource, FindSourceAdmin)
+
+class PropertyAdmin(admin.ModelAdmin):
+ list_display = ['find', 'person', 'start_date', 'end_date']
+ search_fields = ('find__label', 'person__name')
+ model = models.Property
+
+admin.site.register(models.Property, PropertyAdmin)
+
+class TreatmentAdmin(HistorizedObjectAdmin):
+ list_display = ('location', 'treatment_type', 'container', 'person')
+ list_filter = ('treatment_type',)
+ model = models.Treatment
+
+admin.site.register(models.Treatment, TreatmentAdmin)
+
+class TreatmentSourceAdmin(admin.ModelAdmin):
+ list_display = ('treatment', 'title', 'source_type',)
+ list_filter = ('source_type',)
+ search_fields = ('title',)
+ model = models.TreatmentSource
+
+admin.site.register(models.TreatmentSource, TreatmentSourceAdmin)
+
+basic_models = [models.MaterialType, models.TreatmentType]
+for model in basic_models:
+ admin.site.register(model)
diff --git a/ishtar_common/forms_items.py b/archaeological_finds/forms.py
index b763d94b2..7d64214f5 100644
--- a/ishtar_common/forms_items.py
+++ b/archaeological_finds/forms.py
@@ -59,9 +59,9 @@ class ItemWizard(Wizard):
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
+ base_finds = current_item.base_finds.all()
+ if base_finds:
+ return base_finds[0].context_record
def get_template_context(self, request, storage, form=None):
"""
@@ -89,18 +89,18 @@ class ItemWizard(Wizard):
form_list)
dct['order'] = 1
if 'pk' in dct and type(dct['pk']) == models.ContextRecord:
- dct['base_items__context_record'] = dct.pop('pk')
+ dct['base_finds__context_record'] = dct.pop('pk')
return dct
class ItemForm(forms.Form):
form_label = _("Item")
- base_model = 'base_items'
+ base_model = 'base_finds'
associated_models = {'material_type':models.MaterialType,}
label = forms.CharField(label=_(u"ID"),
validators=[validators.MaxLengthValidator(60)])
description = forms.CharField(label=_("Description"),
widget=forms.Textarea)
- base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"),
+ base_finds__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"),
required=False)
material_type = forms.ChoiceField(label=_("Material type"),
choices=models.MaterialType.get_types())
@@ -137,16 +137,16 @@ item_creation_wizard = ItemWizard([
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(
+ base_finds__context_record__parcel__town = get_town_field()
+ base_finds__context_record__operation__year = forms.IntegerField(
label=_(u"Year"))
- base_items__context_record__operation__code_patriarche = \
+ base_finds__context_record__operation__code_patriarche = \
forms.IntegerField(label=_(u"Code PATRIARCHE"))
dating__period = forms.ChoiceField(label=_(u"Period"), choices=[])
# TODO search by warehouse
material_type = forms.ChoiceField(label=_(u"Material type"), choices=[])
- base_items__item__description = forms.CharField(label=_(u"Description"))
- base_items__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"))
+ base_finds__item__description = forms.CharField(label=_(u"Description"))
+ base_finds__is_isolated = forms.NullBooleanField(label=_(u"Is isolated?"))
def __init__(self, *args, **kwargs):
super(ItemSelect, self).__init__(*args, **kwargs)
@@ -424,7 +424,7 @@ item_source_creation_wizard = ItemSourceWizard([
url_name='item_source_creation',)
class ItemSourceSelect(SourceSelect):
- item__base_items__context_record__operation__year = forms.IntegerField(
+ item__base_finds__context_record__operation__year = forms.IntegerField(
label=_(u"Year of the operation"))
item__dating__period = forms.ChoiceField(
label=_(u"Period of the archaelogical item"),
diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py
new file mode 100644
index 000000000..55a498184
--- /dev/null
+++ b/archaeological_finds/ishtar_menu.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.utils.translation import ugettext_lazy as _
+
+from ishtar_common.menu_base import SectionItem, MenuItem
+
+import models
+
+MENU_SECTIONS = [
+ (50, SectionItem('find_management', _(u"Find"),
+ childs=[
+ MenuItem('find_search', _(u"Search"),
+ model=models.Find,
+ access_controls=['view_item',
+ 'view_own_item']),
+ MenuItem('find_creation', _(u"Creation"),
+ model=models.Find,
+ access_controls=['add_item',
+ 'add_own_item']),
+ MenuItem('find_modification', _(u"Modification"),
+ model=models.Find,
+ access_controls=['change_item',
+ 'change_own_item']),
+ MenuItem('warehouse_packaging', _(u"Packaging"),
+ model=models.Treatment,
+ access_controls=['add_treatment', 'add_own_treatment']),
+ #MenuItem('treatment_creation', _(u"Add a treatment"),
+ # model=models.Treatment,
+ # access_controls=['add_treatment',
+ # 'add_own_treatment']),
+ SectionItem('find_source', _(u"Documentation"),
+ childs=[
+ MenuItem('find_source_creation',
+ _(u"Creation"),
+ model=models.FindSource,
+ access_controls=['change_item',
+ 'change_own_item']),
+ MenuItem('find_source_modification',
+ _(u"Modification"),
+ model=models.FindSource,
+ access_controls=['change_item',
+ 'change_own_item']),
+ MenuItem('find_source_deletion',
+ _(u"Deletion"),
+ model=models.FindSource,
+ access_controls=['change_item',
+ 'change_own_item']),
+ ])
+ ]))
+]
diff --git a/archaeological_finds/migrations/0001_initial.py b/archaeological_finds/migrations/0001_initial.py
index 03a45ed8d..eab75b03c 100644
--- a/archaeological_finds/migrations/0001_initial.py
+++ b/archaeological_finds/migrations/0001_initial.py
@@ -20,8 +20,8 @@ class Migration(SchemaMigration):
))
db.send_create_signal('archaeological_finds', ['MaterialType'])
- # Adding model 'HistoricalBaseItem'
- db.create_table('archaeological_finds_historicalbaseitem', (
+ # Adding model 'HistoricalBaseFind'
+ db.create_table('archaeological_finds_historicalbasefind', (
('id', self.gf('django.db.models.fields.IntegerField')(db_index=True, blank=True)),
('history_modifier_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
('label', self.gf('django.db.models.fields.CharField')(max_length=60)),
@@ -35,23 +35,23 @@ class Migration(SchemaMigration):
('history_user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
('history_type', self.gf('django.db.models.fields.CharField')(max_length=1)),
))
- db.send_create_signal('archaeological_finds', ['HistoricalBaseItem'])
+ db.send_create_signal('archaeological_finds', ['HistoricalBaseFind'])
- # Adding model 'BaseItem'
- db.create_table('archaeological_finds_baseitem', (
+ # Adding model 'BaseFind'
+ db.create_table('archaeological_finds_basefind', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
('label', self.gf('django.db.models.fields.CharField')(max_length=60)),
('description', self.gf('django.db.models.fields.TextField')()),
- ('context_record', self.gf('django.db.models.fields.related.ForeignKey')(related_name='base_items', to=orm['archaeological_context_records.ContextRecord'])),
+ ('context_record', self.gf('django.db.models.fields.related.ForeignKey')(related_name='base_finds', to=orm['archaeological_context_records.ContextRecord'])),
('is_isolated', self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True)),
('index', self.gf('django.db.models.fields.IntegerField')(default=0)),
('material_index', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
- db.send_create_signal('archaeological_finds', ['BaseItem'])
+ db.send_create_signal('archaeological_finds', ['BaseFind'])
- # Adding model 'HistoricalItem'
- db.create_table('archaeological_finds_historicalitem', (
+ # Adding model 'HistoricalFind'
+ db.create_table('archaeological_finds_historicalfind', (
('id', self.gf('django.db.models.fields.IntegerField')(db_index=True, blank=True)),
('history_modifier_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
('order', self.gf('django.db.models.fields.IntegerField')()),
@@ -60,7 +60,7 @@ class Migration(SchemaMigration):
('material_type_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
('volume', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
('weight', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
- ('item_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
+ ('find_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('upstream_treatment_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
('downstream_treatment_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
('dating_id', self.gf('django.db.models.fields.IntegerField')(db_index=True, null=True, blank=True)),
@@ -70,10 +70,10 @@ class Migration(SchemaMigration):
('history_user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
('history_type', self.gf('django.db.models.fields.CharField')(max_length=1)),
))
- db.send_create_signal('archaeological_finds', ['HistoricalItem'])
+ db.send_create_signal('archaeological_finds', ['HistoricalFind'])
- # Adding model 'Item'
- db.create_table('archaeological_finds_item', (
+ # Adding model 'Find'
+ db.create_table('archaeological_finds_find', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
('order', self.gf('django.db.models.fields.IntegerField')()),
@@ -82,41 +82,41 @@ class Migration(SchemaMigration):
('material_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.MaterialType'])),
('volume', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
('weight', self.gf('django.db.models.fields.FloatField')(null=True, blank=True)),
- ('item_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
+ ('find_number', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
('upstream_treatment', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='downstream_treatment', null=True, to=orm['archaeological_finds.Treatment'])),
('downstream_treatment', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='upstream_treatment', null=True, to=orm['archaeological_finds.Treatment'])),
('dating', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_context_records.Dating'])),
- ('container', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='items', null=True, to=orm['archaeological_warehouse.Container'])),
+ ('container', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='finds', null=True, to=orm['archaeological_warehouse.Container'])),
))
- db.send_create_signal('archaeological_finds', ['Item'])
+ db.send_create_signal('archaeological_finds', ['Find'])
- # Adding M2M table for field base_items on 'Item'
- db.create_table('archaeological_finds_item_base_items', (
+ # Adding M2M table for field base_finds on 'Find'
+ db.create_table('archaeological_finds_find_base_finds', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('item', models.ForeignKey(orm['archaeological_finds.item'], null=False)),
- ('baseitem', models.ForeignKey(orm['archaeological_finds.baseitem'], null=False))
+ ('find', models.ForeignKey(orm['archaeological_finds.find'], null=False)),
+ ('basefind', models.ForeignKey(orm['archaeological_finds.basefind'], null=False))
))
- db.create_unique('archaeological_finds_item_base_items', ['item_id', 'baseitem_id'])
+ db.create_unique('archaeological_finds_find_base_finds', ['find_id', 'basefind_id'])
- # Adding model 'ItemSource'
- db.create_table('archaeological_finds_itemsource', (
+ # Adding model 'FindSource'
+ db.create_table('archaeological_finds_findsource', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200)),
('source_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.SourceType'])),
('associated_url', self.gf('django.db.models.fields.URLField')(max_length=200, null=True, blank=True)),
('receipt_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)),
('creation_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)),
- ('item', self.gf('django.db.models.fields.related.ForeignKey')(related_name='source', to=orm['archaeological_finds.Item'])),
+ ('find', self.gf('django.db.models.fields.related.ForeignKey')(related_name='source', to=orm['archaeological_finds.Find'])),
))
- db.send_create_signal('archaeological_finds', ['ItemSource'])
+ db.send_create_signal('archaeological_finds', ['FindSource'])
- # Adding M2M table for field authors on 'ItemSource'
- db.create_table('archaeological_finds_itemsource_authors', (
+ # Adding M2M table for field authors on 'FindSource'
+ db.create_table('archaeological_finds_findsource_authors', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('itemsource', models.ForeignKey(orm['archaeological_finds.itemsource'], null=False)),
+ ('findsource', models.ForeignKey(orm['archaeological_finds.findsource'], null=False)),
('author', models.ForeignKey(orm['ishtar_common.author'], null=False))
))
- db.create_unique('archaeological_finds_itemsource_authors', ['itemsource_id', 'author_id'])
+ db.create_unique('archaeological_finds_findsource_authors', ['findsource_id', 'author_id'])
# Adding model 'TreatmentType'
db.create_table('archaeological_finds_treatmenttype', (
@@ -186,7 +186,7 @@ class Migration(SchemaMigration):
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
- ('item', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.Item'])),
+ ('find', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_finds.Find'])),
('administrative_act', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_operations.AdministrativeAct'])),
('person', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Person'])),
('start_date', self.gf('django.db.models.fields.DateField')()),
@@ -199,26 +199,26 @@ class Migration(SchemaMigration):
# Deleting model 'MaterialType'
db.delete_table('archaeological_finds_materialtype')
- # Deleting model 'HistoricalBaseItem'
- db.delete_table('archaeological_finds_historicalbaseitem')
+ # Deleting model 'HistoricalBaseFind'
+ db.delete_table('archaeological_finds_historicalbasefind')
- # Deleting model 'BaseItem'
- db.delete_table('archaeological_finds_baseitem')
+ # Deleting model 'BaseFind'
+ db.delete_table('archaeological_finds_basefind')
- # Deleting model 'HistoricalItem'
- db.delete_table('archaeological_finds_historicalitem')
+ # Deleting model 'HistoricalFind'
+ db.delete_table('archaeological_finds_historicalfind')
- # Deleting model 'Item'
- db.delete_table('archaeological_finds_item')
+ # Deleting model 'Find'
+ db.delete_table('archaeological_finds_find')
- # Removing M2M table for field base_items on 'Item'
- db.delete_table('archaeological_finds_item_base_items')
+ # Removing M2M table for field base_finds on 'Find'
+ db.delete_table('archaeological_finds_find_base_finds')
- # Deleting model 'ItemSource'
- db.delete_table('archaeological_finds_itemsource')
+ # Deleting model 'FindSource'
+ db.delete_table('archaeological_finds_findsource')
- # Removing M2M table for field authors on 'ItemSource'
- db.delete_table('archaeological_finds_itemsource_authors')
+ # Removing M2M table for field authors on 'FindSource'
+ db.delete_table('archaeological_finds_findsource_authors')
# Deleting model 'TreatmentType'
db.delete_table('archaeological_finds_treatmenttype')
@@ -265,7 +265,7 @@ class Migration(SchemaMigration):
'length': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'operation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Operation']"}),
- 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_context_records.Parcel']"}),
+ 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'context_record'", 'to': "orm['archaeological_operations.Parcel']"}),
'taq': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'taq_estimated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'thickness': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
@@ -308,18 +308,6 @@ class Migration(SchemaMigration):
'order': ('django.db.models.fields.IntegerField', [], {}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
- 'archaeological_context_records.parcel': {
- 'Meta': {'object_name': 'Parcel'},
- 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}),
- 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
- 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}),
- 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
- 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}),
- 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
- },
'archaeological_context_records.unit': {
'Meta': {'object_name': 'Unit'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
@@ -382,9 +370,9 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
- 'archaeological_finds.baseitem': {
- 'Meta': {'object_name': 'BaseItem'},
- 'context_record': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'base_items'", 'to': "orm['archaeological_context_records.ContextRecord']"}),
+ 'archaeological_finds.basefind': {
+ 'Meta': {'object_name': 'BaseFind'},
+ 'context_record': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'base_finds'", 'to': "orm['archaeological_context_records.ContextRecord']"}),
'description': ('django.db.models.fields.TextField', [], {}),
'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
@@ -393,8 +381,36 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
'material_index': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
- 'archaeological_finds.historicalbaseitem': {
- 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalBaseItem'},
+ 'archaeological_finds.find': {
+ 'Meta': {'object_name': 'Find'},
+ 'base_finds': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'find'", 'symmetrical': 'False', 'to': "orm['archaeological_finds.BaseFind']"}),
+ 'container': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'finds'", 'null': 'True', 'to': "orm['archaeological_warehouse.Container']"}),
+ 'dating': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_context_records.Dating']"}),
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'downstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'upstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}),
+ 'find_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
+ 'material_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.MaterialType']"}),
+ 'order': ('django.db.models.fields.IntegerField', [], {}),
+ 'upstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'downstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}),
+ 'volume': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
+ 'weight': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'archaeological_finds.findsource': {
+ 'Meta': {'object_name': 'FindSource'},
+ 'associated_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+ 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.Author']", 'symmetrical': 'False'}),
+ 'creation_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'find': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['archaeological_finds.Find']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'receipt_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'source_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.SourceType']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+ },
+ 'archaeological_finds.historicalbasefind': {
+ 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalBaseFind'},
'context_record_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {}),
'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
@@ -408,19 +424,19 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
'material_index': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
- 'archaeological_finds.historicalitem': {
- 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalItem'},
+ 'archaeological_finds.historicalfind': {
+ 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalFind'},
'container_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'dating_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'downstream_treatment_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'find_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}),
- 'item_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
'material_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {}),
@@ -444,34 +460,6 @@ class Migration(SchemaMigration):
'start_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
'treatment_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
},
- 'archaeological_finds.item': {
- 'Meta': {'object_name': 'Item'},
- 'base_items': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'item'", 'symmetrical': 'False', 'to': "orm['archaeological_finds.BaseItem']"}),
- 'container': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'to': "orm['archaeological_warehouse.Container']"}),
- 'dating': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_context_records.Dating']"}),
- 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'downstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'upstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}),
- 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'item_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
- 'label': ('django.db.models.fields.CharField', [], {'max_length': '60'}),
- 'material_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.MaterialType']"}),
- 'order': ('django.db.models.fields.IntegerField', [], {}),
- 'upstream_treatment': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'downstream_treatment'", 'null': 'True', 'to': "orm['archaeological_finds.Treatment']"}),
- 'volume': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
- 'weight': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'})
- },
- 'archaeological_finds.itemsource': {
- 'Meta': {'object_name': 'ItemSource'},
- 'associated_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
- 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.Author']", 'symmetrical': 'False'}),
- 'creation_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
- 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'item': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['archaeological_finds.Item']"}),
- 'receipt_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
- 'source_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.SourceType']"}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
- },
'archaeological_finds.materialtype': {
'Meta': {'object_name': 'MaterialType'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
@@ -486,10 +474,10 @@ class Migration(SchemaMigration):
'Meta': {'object_name': 'Property'},
'administrative_act': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_operations.AdministrativeAct']"}),
'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'find': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.Find']"}),
'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'item': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_finds.Item']"}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']"}),
'start_date': ('django.db.models.fields.DateField', [], {})
},
@@ -588,6 +576,18 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
+ 'archaeological_operations.parcel': {
+ 'Meta': {'object_name': 'Parcel'},
+ 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}),
+ 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
+ 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
+ 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}),
+ 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
'archaeological_operations.period': {
'Meta': {'object_name': 'Period'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index cea9a35f1..c61e22e68 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -39,11 +39,11 @@ class MaterialType(GeneralType):
verbose_name = _(u"Material type")
verbose_name_plural = _(u"Material types")
-class BaseItem(BaseHistorizedItem, OwnPerms):
+class BaseFind(BaseHistorizedItem, OwnPerms):
label = models.CharField(_(u"ID"), max_length=60)
description = models.TextField(_(u"Description"))
context_record = models.ForeignKey(ContextRecord,
- related_name='base_items', verbose_name=_(u"Context Record"))
+ related_name='base_finds', verbose_name=_(u"Context Record"))
is_isolated = models.NullBooleanField(_(u"Is isolated?"), blank=True,
null=True)
index = models.IntegerField(u"Index", default=0)
@@ -51,40 +51,40 @@ class BaseItem(BaseHistorizedItem, OwnPerms):
history = HistoricalRecords()
class Meta:
- verbose_name = _(u"Base item")
- verbose_name_plural = _(u"Base items")
+ verbose_name = _(u"Base find")
+ verbose_name_plural = _(u"Base finds")
permissions = (
- ("view_own_baseitem", ugettext(u"Can view own Base item")),
- ("add_own_baseitem", ugettext(u"Can add own Base item")),
- ("change_own_baseitem", ugettext(u"Can change own Base item")),
- ("delete_own_baseitem", ugettext(u"Can delete own Base item")),
+ ("view_own_basefind", ugettext(u"Can view own Base find")),
+ ("add_own_basefind", ugettext(u"Can add own Base find")),
+ ("change_own_basefind", ugettext(u"Can change own Base find")),
+ ("delete_own_basefind", ugettext(u"Can delete own Base find")),
)
def __unicode__(self):
return self.label
- def get_last_item(self):
- #TODO: manage virtuals - property(last_item) ?
- items = self.item.filter().order_by("-order").all()
- return items and items[0]
+ def get_last_find(self):
+ #TODO: manage virtuals - property(last_find) ?
+ finds = self.find.filter().order_by("-order").all()
+ return finds and finds[0]
def full_label(self):
return self._real_label() or self._temp_label()
def material_type_label(self):
- item = self.get_last_item()
- items = [item and unicode(item.material_type) or '']
+ find = self.get_last_find()
+ finds = [find and unicode(find.material_type) or '']
ope = self.context_record.operation
- items += [ope.code_patriarche or \
+ finds += [ope.code_patriarche or \
(unicode(ope.year) + "-" + unicode(ope.operation_code))]
- items += [self.context_record.label, unicode(self.material_index)]
- return JOINT.join(items)
+ finds += [self.context_record.label, unicode(self.material_index)]
+ return JOINT.join(finds)
def _real_label(self):
if not self.context_record.parcel.operation.code_patriarche:
return
- item = self.get_last_item()
- lbl = item.label or self.label
+ find = self.get_last_find()
+ lbl = find.label or self.label
return JOINT.join([unicode(it) for it in (
self.context_record.parcel.operation.code_patriarche,
self.context_record.label,
@@ -93,25 +93,25 @@ class BaseItem(BaseHistorizedItem, OwnPerms):
def _temp_label(self):
if self.context_record.parcel.operation.code_patriarche:
return
- item = self.get_last_item()
- lbl = item.label or self.label
+ find = self.get_last_find()
+ lbl = find.label or self.label
return JOINT.join([unicode(it) for it in (
self.context_record.parcel.year,
self.index,
self.context_record.label,
lbl) if it])
-class Item(BaseHistorizedItem, OwnPerms):
+class Find(BaseHistorizedItem, OwnPerms):
TABLE_COLS = ['label', 'material_type', 'dating.period',
- 'base_items.context_record.parcel.town',
- 'base_items.context_record.parcel.operation.year',
- 'base_items.context_record.parcel.operation.operation_code',
- 'base_items.is_isolated']
+ 'base_finds.context_record.parcel.town',
+ 'base_finds.context_record.parcel.operation.year',
+ 'base_finds.context_record.parcel.operation.operation_code',
+ 'base_finds.is_isolated']
if settings.COUNTRY == 'fr':
TABLE_COLS.insert(6,
- 'base_items.context_record.parcel.operation.code_patriarche')
- base_items = models.ManyToManyField(BaseItem, verbose_name=_(u"Base item"),
- related_name='item')
+ 'base_finds.context_record.parcel.operation.code_patriarche')
+ base_finds = models.ManyToManyField(BaseFind, verbose_name=_(u"Base find"),
+ related_name='find')
order = models.IntegerField(_(u"Order"))
label = models.CharField(_(u"ID"), max_length=60)
description = models.TextField(_(u"Description"), blank=True, null=True)
@@ -119,7 +119,7 @@ class Item(BaseHistorizedItem, OwnPerms):
verbose_name = _(u"Material type"))
volume = models.FloatField(_(u"Volume (l)"), blank=True, null=True)
weight = models.FloatField(_(u"Weight (g)"), blank=True, null=True)
- item_number = models.IntegerField(_("Item number"), blank=True, null=True)
+ find_number = models.IntegerField(_("Find number"), blank=True, null=True)
upstream_treatment = models.ForeignKey("Treatment", blank=True, null=True,
related_name='downstream_treatment', verbose_name=_("Upstream treatment"))
downstream_treatment = models.ForeignKey("Treatment", blank=True, null=True,
@@ -127,15 +127,15 @@ class Item(BaseHistorizedItem, OwnPerms):
dating = models.ForeignKey(Dating, verbose_name=_(u"Dating"))
if WAREHOUSE_AVAILABLE:
container = models.ForeignKey(Container, verbose_name=_(u"Container"),
- blank=True, null=True, related_name='items')
+ blank=True, null=True, related_name='finds')
history = HistoricalRecords()
@classmethod
def get_years(cls):
years = set()
- items = cls.objects.filter(downstream_treatment__isnull=True)
- for item in items:
- bi = item.base_items.all()
+ finds = cls.objects.filter(downstream_treatment__isnull=True)
+ for find in finds:
+ bi = find.base_finds.all()
if not bi:
continue
bi = bi[0]
@@ -146,14 +146,14 @@ class Item(BaseHistorizedItem, OwnPerms):
@classmethod
def get_by_year(cls, year):
return cls.objects.filter(downstream_treatment__isnull=True,
- base_items__context_record__operation__start_date__year=year)
+ base_finds__context_record__operation__start_date__year=year)
@classmethod
def get_operations(cls):
operations = set()
- items = cls.objects.filter(downstream_treatment__isnull=True)
- for item in items:
- bi = item.base_items.all()
+ finds = cls.objects.filter(downstream_treatment__isnull=True)
+ for find in finds:
+ bi = find.base_finds.all()
if not bi:
continue
bi = bi[0]
@@ -164,7 +164,7 @@ class Item(BaseHistorizedItem, OwnPerms):
@classmethod
def get_by_operation(cls, operation_id):
return cls.objects.filter(downstream_treatment__isnull=True,
- base_items__context_record__operation__pk=operation_id)
+ base_finds__context_record__operation__pk=operation_id)
@classmethod
def get_total_number(cls):
@@ -173,23 +173,23 @@ class Item(BaseHistorizedItem, OwnPerms):
def duplicate(self, user):
dct = dict([(attr, getattr(self, attr)) for attr in ('order', 'label',
'description', 'material_type', 'volume', 'weight',
- 'item_number', 'dating')])
+ 'find_number', 'dating')])
dct['order'] += 1
dct['history_modifier'] = user
new = self.__class__(**dct)
new.save()
- for base_item in self.base_items.all():
- new.base_items.add(base_item)
+ for base_find in self.base_finds.all():
+ new.base_finds.add(base_find)
return new
class Meta:
- verbose_name = _(u"Item")
- verbose_name_plural = _(u"Items")
+ verbose_name = _(u"Find")
+ verbose_name_plural = _(u"Finds")
permissions = (
- ("view_own_item", ugettext(u"Can view own Item")),
- ("add_own_item", ugettext(u"Can add own Item")),
- ("change_own_item", ugettext(u"Can change own Item")),
- ("delete_own_item", ugettext(u"Can delete own Item")),
+ ("view_own_find", ugettext(u"Can view own Find")),
+ ("add_own_find", ugettext(u"Can add own Find")),
+ ("change_own_find", ugettext(u"Can change own Find")),
+ ("delete_own_find", ugettext(u"Can delete own Find")),
)
def __unicode__(self):
@@ -197,27 +197,27 @@ class Item(BaseHistorizedItem, OwnPerms):
def save(self, *args, **kwargs):
if not self.pk:
- super(Item, self).save(*args, **kwargs)
- for base_item in self.base_items.all():
- if not base_item.index:
- idx = BaseItem.objects.filter(context_record=\
- base_item.context_record).aggregate(Max('index'))
- base_item.index = idx and idx['index__max'] + 1 or 1
- if not base_item.material_index:
- idx = BaseItem.objects.filter(context_record=\
- base_item.context_record,
- item__material_type=self.material_type).aggregate(
+ super(Find, self).save(*args, **kwargs)
+ for base_find in self.base_finds.all():
+ if not base_find.index:
+ idx = BaseFind.objects.filter(context_record=\
+ base_find.context_record).aggregate(Max('index'))
+ base_find.index = idx and idx['index__max'] + 1 or 1
+ if not base_find.material_index:
+ idx = BaseFind.objects.filter(context_record=\
+ base_find.context_record,
+ find__material_type=self.material_type).aggregate(
Max('material_index'))
- base_item.material_index = idx and \
+ base_find.material_index = idx and \
idx['material_index__max'] + 1 or 1
- base_item.save()
- super(Item, self).save(*args, **kwargs)
+ base_find.save()
+ super(Find, self).save(*args, **kwargs)
-class ItemSource(Source):
+class FindSource(Source):
class Meta:
- verbose_name = _(u"Item documentation")
- verbose_name_plural = _(u"Item documentations")
- item = models.ForeignKey(Item, verbose_name=_(u"Item"),
+ verbose_name = _(u"Find documentation")
+ verbose_name_plural = _(u"Find documentations")
+ find = models.ForeignKey(Find, verbose_name=_(u"Find"),
related_name="source")
class TreatmentType(GeneralType):
@@ -265,7 +265,7 @@ class TreatmentSource(Source):
related_name="source")
class Property(LightHistorizedItem):
- item = models.ForeignKey(Item, verbose_name=_(u"Item"))
+ find = models.ForeignKey(Find, verbose_name=_(u"Find"))
administrative_act = models.ForeignKey(AdministrativeAct,
verbose_name=_(u"Administrative act"))
person = models.ForeignKey(Person, verbose_name=_(u"Person"))
@@ -277,5 +277,5 @@ class Property(LightHistorizedItem):
verbose_name_plural = _(u"Properties")
def __unicode__(self):
- return self.person + JOINT + self.item
+ return self.person + JOINT + self.find
diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py
new file mode 100644
index 000000000..4c733436d
--- /dev/null
+++ b/archaeological_finds/urls.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf.urls.defaults import *
+
+"""
+import forms
+
+# forms
+urlpatterns = patterns('',
+ url(r'item_search/(?P<step>.+)$',
+ forms.item_search_wizard, name='item_search'),
+ url(r'item_creation/(?P<step>.+)$',
+ forms.item_creation_wizard, name='item_creation'),
+ url(r'item_modification/(?P<step>.+)$',
+ forms.item_modification_wizard, name='item_modification'),
+ url(r'item_source_creation/(?P<step>.+)$',
+ forms.item_source_creation_wizard,
+ name='item_source_creation'),
+ url(r'item_source_modification/(?P<step>.+)$',
+ forms.item_source_modification_wizard,
+ name='item_source_modification'),
+ url(r'item_source_deletion/(?P<step>.+)$',
+ forms.item_source_deletion_wizard,
+ name='item_source_deletion'),
+)
+
+urlpatterns += patterns('archaeological_finds.views',
+ url(r'get-find/(?P<type>.+)?$', 'get_find',
+ name='get-find'),
+ url(r'get-find-full/(?P<type>.+)?$', 'get_find',
+ name='get-find-full', kwargs={'full':True}),
+ url(r'get-findsource/(?P<type>.+)?$',
+ 'get_findsource', name='get-findsource'),
+)
+"""
diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py
new file mode 100644
index 000000000..af428d59e
--- /dev/null
+++ b/archaeological_finds/views.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from ishtar_common.views import get_item, show_item, revert_item
+import models
+
+get_find = get_item(models.Find,
+ 'get_find', 'find',
+ bool_fields = ['base_finds__is_isolated'],
+ base_request={'downstream_treatment__isnull':True},
+ extra_request_keys={
+'base_finds__context_record__parcel__town':
+ 'base_finds__context_record__parcel__town',
+'base_finds__context_record__operation__year':
+ 'base_finds__context_record__operation__year__contains',
+'base_finds__context_record__operation__code_patriarche':
+ 'base_finds__context_record__operation__code_patriarche',
+'dating__period':'dating__period__pk',
+'base_finds__find__description':'base_finds__find__description__icontains',
+'base_finds__is_isolated':'base_finds__is_isolated'})
+get_findsource = get_item(models.FindSource,
+ 'get_findsource', 'findsource',
+ extra_request_keys={
+'find__context_record__operation__year':'find__context_record__operation__year',
+'find__dating__period':'find__dating__period__pk',
+'find__description':'find__description__icontains',
+ })
diff --git a/archaeological_operations/admin.py b/archaeological_operations/admin.py
new file mode 100644
index 000000000..de8b47edc
--- /dev/null
+++ b/archaeological_operations/admin.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf import settings
+from django.contrib import admin
+
+from ishtar_common.admin import HistorizedObjectAdmin
+
+import models
+
+class 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 PeriodAdmin(admin.ModelAdmin):
+ list_display = ('label', 'start_date', 'end_date', 'parent')
+ model = models.Period
+
+admin.site.register(models.Period, PeriodAdmin)
+
+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)
+
+basic_models = [models.OperationType, models.RemainType, models.ActType,
+ models.ParcelOwner]
+for model in basic_models:
+ admin.site.register(model)
diff --git a/ishtar_common/forms_operations.py b/archaeological_operations/forms.py
index e163b5869..d4152d4fa 100644
--- a/ishtar_common/forms_operations.py
+++ b/archaeological_operations/forms.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -23,6 +23,7 @@ Operations forms definitions
import datetime
from django import forms
+from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core import validators
@@ -30,15 +31,13 @@ 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, \
+from ishtar_common.forms import Wizard, FinalForm, FormSet, SearchWizard, \
+ ClosingWizard, ClosingDateFormSelection, DeletionWizard, formset_factory, \
+ get_now, reverse_lazy, get_form_selection
+from ishtar_common.forms_common import TownForm, TownFormSet, TownFormset, \
+ AuthorFormset, SourceForm, SourceWizard, SourceSelect, \
SourceDeletionForm, get_town_field
def is_preventive(form_name, model, type_key='operation_type', key=''):
@@ -57,6 +56,57 @@ def is_preventive(form_name, model, type_key='operation_type', key=''):
return False
return func
+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")
+
class OperationWizard(Wizard):
model = models.Operation
object_parcel_type = 'operation'
diff --git a/archaeological_operations/ishtar_menu.py b/archaeological_operations/ishtar_menu.py
index dfd45a167..faf749480 100644
--- a/archaeological_operations/ishtar_menu.py
+++ b/archaeological_operations/ishtar_menu.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -20,53 +20,69 @@
from django.utils.translation import ugettext_lazy as _
from ishtar_common.menu_base import SectionItem, MenuItem
-from ishtar_common.models import AdministrativeAct
import models
-ORDER = 30
-
MENU_SECTIONS = [
- SectionItem('operation_management', _(u"Operation"),
+ (30, 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_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"),
+ 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('operation_source', _(u"Documentation"),
childs=[
- MenuItem('operation_administrativeactop',
+ MenuItem('operation_source_creation',
_(u"Add"),
- model=models.Operation,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_administrativeactop_modification',
+ model=models.OperationSource,
+ access_controls=['change_operation',
+ 'change_own_operation']),
+ MenuItem('operation_source_modification',
_(u"Modification"),
- model=AdministrativeAct,
- access_controls=['change_operation',
- 'change_own_operation']),
- MenuItem('operation_administrativeactop_deletion',
+ model=models.OperationSource,
+ access_controls=['change_operation',
+ 'change_own_operation']),
+ MenuItem('operation_source_deletion',
_(u"Deletion"),
- model=AdministrativeAct,
- access_controls=['operation_deletion',
- 'delete_own_operation']),
- ],),
- ]),
+ model=models.OperationSource,
+ access_controls=['change_operation',
+ 'change_own_operation']),
+ ])
+ ]),
+ )
]
diff --git a/archaeological_operations/migrations/0001_initial.py b/archaeological_operations/migrations/0001_initial.py
index e472e5e4d..2039268aa 100644
--- a/archaeological_operations/migrations/0001_initial.py
+++ b/archaeological_operations/migrations/0001_initial.py
@@ -200,6 +200,32 @@ class Migration(SchemaMigration):
))
db.send_create_signal('archaeological_operations', ['AdministrativeAct'])
+ # Adding model 'Parcel'
+ db.create_table('archaeological_operations_parcel', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
+ ('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
+ ('associated_file', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='parcels', null=True, to=orm['archaeological_files.File'])),
+ ('operation', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='parcels', null=True, to=orm['archaeological_operations.Operation'])),
+ ('year', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
+ ('town', self.gf('django.db.models.fields.related.ForeignKey')(related_name='parcels', to=orm['ishtar_common.Town'])),
+ ('section', self.gf('django.db.models.fields.CharField')(max_length=4)),
+ ('parcel_number', self.gf('django.db.models.fields.CharField')(max_length=6)),
+ ))
+ db.send_create_signal('archaeological_operations', ['Parcel'])
+
+ # Adding model 'ParcelOwner'
+ db.create_table('archaeological_operations_parcelowner', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('history_modifier', self.gf('django.db.models.fields.related.ForeignKey')(related_name='+', to=orm['auth.User'])),
+ ('history_date', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
+ ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['ishtar_common.Person'])),
+ ('parcel', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['archaeological_operations.Parcel'])),
+ ('start_date', self.gf('django.db.models.fields.DateField')()),
+ ('end_date', self.gf('django.db.models.fields.DateField')()),
+ ))
+ db.send_create_signal('archaeological_operations', ['ParcelOwner'])
+
def backwards(self, orm):
# Deleting model 'OperationType'
@@ -241,6 +267,12 @@ class Migration(SchemaMigration):
# Deleting model 'AdministrativeAct'
db.delete_table('archaeological_operations_administrativeact')
+ # Deleting model 'Parcel'
+ db.delete_table('archaeological_operations_parcel')
+
+ # Deleting model 'ParcelOwner'
+ db.delete_table('archaeological_operations_parcelowner')
+
models = {
'archaeological_files.file': {
@@ -427,6 +459,28 @@ class Migration(SchemaMigration):
'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
+ 'archaeological_operations.parcel': {
+ 'Meta': {'object_name': 'Parcel'},
+ 'associated_file': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_files.File']"}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'operation': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parcels'", 'null': 'True', 'to': "orm['archaeological_operations.Operation']"}),
+ 'parcel_number': ('django.db.models.fields.CharField', [], {'max_length': '6'}),
+ 'section': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
+ 'town': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'parcels'", 'to': "orm['ishtar_common.Town']"}),
+ 'year': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'archaeological_operations.parcelowner': {
+ 'Meta': {'object_name': 'ParcelOwner'},
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'history_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']"}),
+ 'parcel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['archaeological_operations.Parcel']"}),
+ 'start_date': ('django.db.models.fields.DateField', [], {})
+ },
'archaeological_operations.period': {
'Meta': {'object_name': 'Period'},
'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 48baa57ba..9b3631114 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -23,7 +23,8 @@ from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _, ugettext
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
- HistoricalRecords, OwnPerms, Department, Source, Person, Organization, Town
+ HistoricalRecords, LightHistorizedItem, OwnPerms, Department, Source,\
+ Person, Organization, Town, Dashboard
FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS
if FILES_AVAILABLE:
from archaeological_files.models import File
@@ -288,13 +289,502 @@ related_name='+', verbose_name=_(u"Person in charge of the scientific part"))
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")),
+ ("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 Parcel(LightHistorizedItem):
+ if FILES_AVAILABLE:
+ 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 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 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']))
diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py
new file mode 100644
index 000000000..a761b4ccc
--- /dev/null
+++ b/archaeological_operations/urls.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf.urls.defaults import *
+
+"""
+import forms
+
+# forms
+urlpatterns = patterns('',
+ url(r'operation_search/(?P<step>.+)$',
+ forms.operation_search_wizard, name='operation_search'),
+ url(r'operation_creation/(?P<step>.+)$',
+ forms.operation_creation_wizard, name='operation_creation'),
+ url(r'operation_modification/(?P<step>.+)$',
+ forms.operation_modification_wizard,
+ name='operation_modification'),
+ url(r'operation_closing/(?P<step>.+)$',
+ forms.operation_closing_wizard, name='operation_closing'),
+ url(r'operation_deletion/(?P<step>.+)$',
+ forms.operation_deletion_wizard, name='operation_deletion'),
+ url(r'operation_administrativeactop/(?P<step>.+)$',
+ forms.operation_administrativeactop_wizard,
+ name='operation_administrativeactop'),
+ url(r'operation_administrativeactop_modification/(?P<step>.+)$',
+ forms.operation_administrativeactop_modification_wizard,
+ name='operation_administrativeactop_modification'),
+ url(r'operation_administrativeactop_deletion/(?P<step>.+)$',
+ forms.operation_administrativeactop_deletion_wizard,
+ name='operation_administrativeactop_deletion'),
+ url(r'operation_source_creation/(?P<step>.+)$',
+ forms.operation_source_creation_wizard,
+ name='operation_source_creation'),
+ url(r'operation_source_modification/(?P<step>.+)$',
+ forms.operation_source_modification_wizard,
+ name='operation_source_modification'),
+ url(r'operation_source_deletion/(?P<step>.+)$',
+ forms.operation_source_deletion_wizard,
+ name='operation_source_deletion'),
+)
+
+urlpatterns += patterns('archaeological_operations.views',
+ 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'),
+)"""
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
new file mode 100644
index 000000000..27ebd60e9
--- /dev/null
+++ b/archaeological_operations/views.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import json
+
+from django.db.models import Q
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+
+from ishtar_common.views import get_item, show_item, revert_item
+import models
+
+def autocomplete_operation(request, non_closed=True):
+ person_types = request.user.ishtaruser.person.person_type
+ if (not request.user.has_perm('ishtar_common.view_operation', models.Operation)\
+ and not request.user.has_perm('ishtar_common.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_common.view_operation', models.Operation)\
+ and not request.user.has_perm('ishtar_common.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 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/archaeological_warehouse/admin.py b/archaeological_warehouse/admin.py
new file mode 100644
index 000000000..cf026e86c
--- /dev/null
+++ b/archaeological_warehouse/admin.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf import settings
+from django.contrib import admin
+
+from ishtar_common.admin import HistorizedObjectAdmin
+
+import models
+
+class 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 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)
+
+basic_models = [models.WarehouseType]
+for model in basic_models:
+ admin.site.register(model)
diff --git a/archaeological_warehouse/ishtar_menu.py b/archaeological_warehouse/ishtar_menu.py
new file mode 100644
index 000000000..1a9d57aaa
--- /dev/null
+++ b/archaeological_warehouse/ishtar_menu.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.utils.translation import ugettext_lazy as _
+
+from ishtar_common.menu_base import SectionItem, MenuItem
+
+from archaeological_finds.models import Treatment
+import models
+
+MENU_SECTIONS = [
+ (60, SectionItem('warehouse', _(u"Warehouse"),
+ childs=[
+ MenuItem('warehouse_inventory', _(u"Inventory"),
+ model=models.Warehouse,
+ access_controls=['change_warehouse',]),
+ MenuItem('warehouse_recording', _(u"Recording"),
+ model=Treatment,
+ access_controls=['add_treatment', 'add_own_treatment']),
+ MenuItem('warehouse_lend', _(u"Lending"),
+ model=Treatment,
+ access_controls=['add_treatment', 'add_own_treatment']),
+ ]))
+]
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index fe381e521..877d16487 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -51,7 +51,6 @@ class Warehouse(Address, OwnPerms):
def __unicode__(self):
return u"%s (%s)" % (self.name, unicode(self.warehouse_type))
-
class ContainerType(GeneralType):
length = models.IntegerField(_(u"Length (mm)"), blank=True, null=True)
width = models.IntegerField(_(u"Width (mm)"), blank=True, null=True)
diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py
new file mode 100644
index 000000000..914ee2533
--- /dev/null
+++ b/archaeological_warehouse/urls.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+from django.conf.urls.defaults import *
+
+"""
+import forms
+
+# forms
+urlpatterns = patterns('',
+ url(r'treatment_creation/(?P<step>.+)$',
+ forms.treatment_creation_wizard, name='treatment_creation'),
+ url(r'warehouse_packaging/(?P<step>.+)$',
+ forms.warehouse_packaging_wizard, name='warehouse_packaging'),
+)
+
+urlpatterns += patterns('archaeological_warehouse.views',
+ url(r'new-warehouse/(?P<parent_name>.+)?/$',
+ 'new_warehouse', name='new-warehouse'),
+ url(r'autocomplete-warehouse/$', 'autocomplete_warehouse',
+ name='autocomplete-warehouse'),
+ url(r'new-container/(?P<parent_name>.+)?/$',
+ 'new_container', name='new-container'),
+ url(r'get-container/$', 'get_container',
+ name='get-container'),
+ url(r'autocomplete-container/?$',
+ 'autocomplete_container', name='autocomplete-container'),
+)
+"""
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py
new file mode 100644
index 000000000..16a8e19f5
--- /dev/null
+++ b/archaeological_warehouse/views.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# See the file COPYING for details.
+
+import json
+
+from django.db.models import Q
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+
+from ishtar_common.views import get_item, show_item, revert_item
+import models
+
+get_container = get_item(models.Container,
+ 'get_container', 'container',
+ extra_request_keys={
+ 'location':'location__pk',
+ 'container_type':'container_type__pk',
+ 'reference':'reference__icontains',
+ })
+
+new_warehouse = new_item(models.Warehouse)
+new_container = new_item(models.Container)
+
+def autocomplete_warehouse(request):
+ if not request.user.has_perm('ishtar_common.view_warehouse',
+ models.Warehouse)\
+ and not request.user.has_perm('ishtar_common.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_container(request):
+ if not request.user.has_perm('ishtar_common.view_warehouse',
+ models.Warehouse)\
+ and not request.user.has_perm('ishtar_common.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')
diff --git a/example_project/urls.py b/example_project/urls.py
index ea54a61e1..02936e6df 100644
--- a/example_project/urls.py
+++ b/example_project/urls.py
@@ -1,3 +1,4 @@
+from django.conf import settings
from django.conf.urls.defaults import *
from django.contrib.auth.models import User
@@ -5,15 +6,23 @@ from django.contrib import admin
admin.autodiscover()
#admin.site.unregister(User)
-from settings import URL_PATH
-
-BASE_URL = r'^' + URL_PATH
urlpatterns = patterns('',
- (BASE_URL + 'accounts/', include('registration.urls')),
- (BASE_URL + r'admin/', include(admin.site.urls)),
+ (r'^accounts/', include('registration.urls')),
+ (r'^admin/', include(admin.site.urls)),
('', include('ishtar_common.urls')),
)
+
+"""
+for app in ['archaeological_files', 'archaeological_operations',
+ 'archaeological_context_records', 'archaeological_warehouse',
+ 'archaeological_finds']:
+ if app in settings.INSTALLED_APPS:
+ urlpatterns = patterns('',
+ ('', include(app+'.urls')),
+ )
+"""
+
urlpatterns += patterns('ishtar_common.views',
- url(BASE_URL + '$', 'index', name='start'),
+ url(r'$', 'index', name='start'),
)
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py
index c4e5fa7f2..8f6a07f88 100644
--- a/ishtar_common/admin.py
+++ b/ishtar_common/admin.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -57,130 +57,6 @@ class PersonAdmin(HistorizedObjectAdmin):
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']
@@ -199,42 +75,16 @@ class AuthorAdmin(admin.ModelAdmin):
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]
+basic_models = [models.IshtarUser, models.SourceType, models.AuthorType,
+ models.OrganizationType]
if settings.COUNTRY == 'fr':
- basic_models += [models.Arrondissement, models.Canton, models.SaisineType]
+ basic_models += [models.Arrondissement, models.Canton]
for model in basic_models:
admin.site.register(model)
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index 5de5a6afd..884ec19b4 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -23,6 +23,19 @@ from django.utils.translation import ugettext, ugettext_lazy as _
from menus import Menu
import models
+from archaeological_operations.models import Operation
+
+CURRENT_ITEMS = []
+if 'archaeological_files' in settings.INSTALLED_APPS:
+ from archaeological_files.models import File
+ CURRENT_ITEMS.append((_(u"Archaeological file"), File))
+CURRENT_ITEMS.append((_(u"Operation"), Operation))
+if 'archaeological_context_records' in settings.INSTALLED_APPS:
+ from archaeological_context_records.models import ContextRecord
+ CURRENT_ITEMS.append((_(u"Context record"), ContextRecord))
+if 'archaeological_finds' in settings.INSTALLED_APPS:
+ from archaeological_finds.models import Find
+ CURRENT_ITEMS.append((_(u"Find"), Find))
def get_base_context(request):
dct = {'URL_PATH':settings.URL_PATH}
@@ -39,11 +52,7 @@ def get_base_context(request):
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),
- ):
+ for lbl, model in CURRENT_ITEMS:
model_name = model.__name__.lower()
current = model_name in request.session and request.session[model_name]
items = []
diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py
index e5f23e620..d3ae65d55 100644
--- a/ishtar_common/forms_common.py
+++ b/ishtar_common/forms_common.py
@@ -265,58 +265,6 @@ class TownFormSet(FormSet):
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 #
######################
diff --git a/ishtar_common/menus.py b/ishtar_common/menus.py
index c55e2a328..3737846b9 100644
--- a/ishtar_common/menus.py
+++ b/ishtar_common/menus.py
@@ -47,127 +47,31 @@ _extra_menus = [(
]
)]
+# collect menu from INSTALLED_APPS
for app in settings.INSTALLED_APPS:
+ print app
+ if app == 'ishtar_common':
+ continue
mod = __import__(app, fromlist=['ishtar_menu'])
if hasattr(mod, 'ishtar_menu'):
menu = getattr(mod, 'ishtar_menu')
- _extra_menus.append((menu.ORDER, menu.MENU_SECTIONS))
+ _extra_menus += menu.MENU_SECTIONS
-_section_items = []
-for order, menu in sorted(_extra_menus, key=lambda x:x[0]):
- _section_items += menu
+# sort
+__section_items = [menu for order, menu in sorted(_extra_menus,
+ key=lambda x:x[0])]
+
+# regroup menus
+_section_items, __keys = [], []
+for section_item in _section_items:
+ if section_item.idx not in __keys:
+ __keys.append(section_item.idx)
+ _section_items.append(section_item)
+ continue
+ _section_items[_section_items.index(section_item.idx)].childs.append(
+ section_item.childs)
"""
- 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"),
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 4406a2b86..b4bf2cd57 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -398,570 +398,6 @@ class UserDashboard:
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
@@ -973,7 +409,7 @@ class Dashboard:
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:
+ if self.model == Find:
last_ids = last_ids.filter(downstream_treatment_id__isnull=True)
if modif_type == '+':
last_ids = last_ids.filter(upstream_treatment_id__isnull=True)
@@ -1252,5 +688,3 @@ class Town(models.Model):
if settings.COUNTRY == "fr":
return u"%s (%s)" % (self.name, self.numero_insee)
return self.name
-
-
diff --git a/ishtar_common/templates/sheet_contextrecord.html b/ishtar_common/templates/sheet_contextrecord.html
index c2b94bafe..806b06288 100644
--- a/ishtar_common/templates/sheet_contextrecord.html
+++ b/ishtar_common/templates/sheet_contextrecord.html
@@ -109,7 +109,7 @@
<th>{% trans "Parcel" %}</th>
<th class='link'>&nbsp;</th>
</tr>
- {% for find in item.base_items.all %}
+ {% for find in item.base_finds.all %}
<tr>
<td>{{ find.full_label }}</td>
{# Displayed as (Patriarche operation code)-(Record unit label)-(Finds label). #}
@@ -119,10 +119,10 @@
{# or displayed as (Year)-(index)-(Record unit label)-(material code)-(Finds label indexed by material type) #}
<td class='string'>{{find.context_record}}</td>
- <td>{{ find.get_last_item.dating}}</td>{# TODO .all|join:", " ? #}
- <td>{{ find.get_last_item.description }}</td>
- <td>{{ find.get_last_item.weight }}</td>
- <td>{{ find.get_last_item.item_number }}</td>
+ <td>{{ find.get_last_find.dating}}</td>{# TODO .all|join:", " ? #}
+ <td>{{ find.get_last_find.description }}</td>
+ <td>{{ find.get_last_find.weight }}</td>
+ <td>{{ find.get_last_find.item_number }}</td>
<td>{{ item.context_record.parcel.short_label }}</td>
<td class='link'><a href="#">{% trans "Details" %}</a></td>
{#<a href="#" onclick='load_window("{% url show-find find.pk%}");'>{%trans "Details"%}</a></td>#}
diff --git a/ishtar_common/templates/sheet_operation.html b/ishtar_common/templates/sheet_operation.html
index aa571d20c..edceca989 100644
--- a/ishtar_common/templates/sheet_operation.html
+++ b/ishtar_common/templates/sheet_operation.html
@@ -156,17 +156,17 @@
<th class='link'>&nbsp;</th>
</tr>
{% for context_record in item.context_record.all %}
- {% for find in context_record.base_items.all %}
+ {% for find in context_record.base_finds.all %}
<tr>
<td class="ref">{{ find.full_label }}</td>
{# Displayed as (Patriarche operation code)-(Record unit label)-(Finds label). #}
{# or displayed as (Year)-(index)-(Record unit label)-(Finds label). #}
<td class="ref">{{ find.material_type_label }}</td>
<td>{{find.context_record.label}}</td>
- <td class='string'>{{ find.get_last_item.dating}}</td>{# TODO .all|join:", " ? #}
- <td class='string'>{{ find.get_last_item.description }}</td>
- <td>{{ find.get_last_item.weight }}</td>
- <td>{{ find.get_last_item.item_number }}</td>
+ <td class='string'>{{ find.get_last_find.dating}}</td>{# TODO .all|join:", " ? #}
+ <td class='string'>{{ find.get_last_find.description }}</td>
+ <td>{{ find.get_last_find.weight }}</td>
+ <td>{{ find.get_last_find.item_number }}</td>
<td class="ref">{{ context_record.parcel.short_label }}</td>
<td class='link'><a href="#">{% trans "Details" %}</a></td>
{#<a href="#" onclick='load_window("{% url show-find find.pk%}");'>{%trans "Details"%}</a></td>#}
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index f6636255e..40ef4a1d2 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -37,97 +37,6 @@ urlpatterns = patterns('',
url(r'account_management/(?P<step>.+)?$',
views.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'):
@@ -142,6 +51,8 @@ urlpatterns += patterns('ishtar_common.views',
# General
url(r'(?P<action_slug>' + actions + r')/$', 'action',
name='action'),
+ url(r'update-current-item/$', 'update_current_item',
+ name='update-current-item'),
url(r'new-person/(?P<parent_name>.+)?/$',
'new_person', name='new-person'),
url(r'autocomplete-person/([0-9_]+)?$', 'autocomplete_person',
@@ -156,66 +67,4 @@ urlpatterns += patterns('ishtar_common.views',
'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_common/views.py b/ishtar_common/views.py
index fe464ade7..69fa8b90b 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2011 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -886,32 +886,6 @@ def autocomplete_town(request):
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_common.view_file', models.File) and \
- not request.user.has_perm('ishtar_common.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):
@@ -1198,72 +1172,6 @@ def revert_item(model):
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_common.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_common.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_common.view_operation', models.Operation)\
- and not request.user.has_perm('ishtar_common.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_common.view_organization',
@@ -1293,72 +1201,10 @@ def autocomplete_organization(request, orga_type=None):
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_common.view_warehouse', models.Warehouse)\
- and not request.user.has_perm('ishtar_common.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_common.view_author', models.Author)\
and not request.user.has_perm('ishtar_common.view_own_author',
- models.Warehouse) :
+ models.Author) :
return HttpResponse(mimetype='text/plain')
if not request.GET.get('term'):
return HttpResponse(mimetype='text/plain')
@@ -1376,29 +1222,6 @@ def autocomplete_author(request):
for author in authors])
return HttpResponse(data, mimetype='text/plain')
-def autocomplete_container(request):
- if not request.user.has_perm('ishtar_common.view_warehouse',
- models.Warehouse)\
- and not request.user.has_perm('ishtar_common.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
@@ -1426,11 +1249,9 @@ def new_item(model):
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):
"""
@@ -1464,19 +1285,3 @@ def dashboard_main(request, dct, obj_id=None, *args, **kwargs):
'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))