summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_files/forms.py26
-rw-r--r--archaeological_files/ishtar_menu.py6
-rw-r--r--archaeological_files/models.py14
-rw-r--r--archaeological_files/templates/ishtar/administrativeact_document.html23
-rw-r--r--archaeological_files/urls.py7
-rw-r--r--archaeological_files/views.py28
-rw-r--r--archaeological_operations/models.py5
-rw-r--r--ishtar_common/admin.py2
-rw-r--r--ishtar_common/migrations/0005_auto__add_documenttemplate.py209
-rw-r--r--ishtar_common/models.py57
-rw-r--r--ishtar_common/ooo_replace.py102
-rw-r--r--ishtar_common/templates/ishtar/wizard/wizard_list_search_result.html2
-rw-r--r--ishtar_common/views.py3
13 files changed, 467 insertions, 17 deletions
diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py
index 2adc58ba1..9affc0901 100644
--- a/archaeological_files/forms.py
+++ b/archaeological_files/forms.py
@@ -33,7 +33,7 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe
from ishtar_common.models import Person, PersonType, Town, Organization, \
- OrganizationType, valid_id, is_unique
+ OrganizationType, valid_id, is_unique, DocumentTemplate
from archaeological_operations.models import ActType, AdministrativeAct
import models
from ishtar_common.forms import FinalForm, FormSet, ClosingDateFormSelection, \
@@ -185,16 +185,36 @@ class FileFormPreventive(forms.Form):
self.fields['permit_type'].choices = models.PermitType.get_types()
self.fields['permit_type'].help_text = models.PermitType.get_help()
-
class FinalFileClosingForm(FinalForm):
confirm_msg = " "
confirm_end_msg = _(u"Would you like to close this archaeological file?")
-
class FinalFileDeleteForm(FinalForm):
confirm_msg = " "
confirm_end_msg = _(u"Would you like to delete this archaelogical file ?")
+class DocumentGenerationAdminActForm(forms.Form):
+ _associated_model = AdministrativeAct
+ document_template = forms.ChoiceField(label=_("Template"), choices=[])
+
+ def __init__(self, *args, **kwargs):
+ super(DocumentGenerationAdminActForm, self).__init__(*args, **kwargs)
+ self.fields['document_template'].choices = DocumentTemplate.get_tuples(
+ dct={'associated_object_name':
+ 'archaeological_operations.models.AdministrativeAct'})
+
+ def save(self, object_pk):
+ try:
+ c_object = self._associated_model.objects.get(pk=object_pk)
+ except self._associated_model.DoesNotExist:
+ return
+ try:
+ template = DocumentTemplate.objects.get(
+ pk=self.cleaned_data.get('document_template'))
+ except DocumentTemplate.DoesNotExist:
+ return
+ return template.publish(c_object)
+
class AdministrativeActFileSelect(TableSelect):
associated_file__towns = get_town_field()
act_type = forms.ChoiceField(label=_("Act type"), choices=[])
diff --git a/archaeological_files/ishtar_menu.py b/archaeological_files/ishtar_menu.py
index 6655a381c..87958848a 100644
--- a/archaeological_files/ishtar_menu.py
+++ b/archaeological_files/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) 2010-2013 É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
@@ -60,6 +60,10 @@ MENU_SECTIONS = [
_(u"Deletion"),
model=AdministrativeAct,
access_controls=['delete_file', 'delete_own_file']),
+ MenuItem('file_administrativeact_document',
+ _(u"Documents"),
+ model=AdministrativeAct,
+ access_controls=['change_file', 'change_own_file']),
],),
]),
),
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index 0095dd13b..2b739fb1c 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -29,7 +29,7 @@ from ishtar_common.utils import cached_label_changed
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
HistoricalRecords, OwnPerms, Person, Organization, Department, Town, \
- Dashboard, IshtarUser
+ Dashboard, IshtarUser, ValueGetter
class FileType(GeneralType):
class Meta:
@@ -53,14 +53,14 @@ class PermitType(GeneralType):
ordering = ('label',)
if settings.COUNTRY == 'fr':
- class SaisineType(GeneralType):
+ class SaisineType(GeneralType, ValueGetter):
delay = models.IntegerField(_(u"Delay (in days)"))
class Meta:
verbose_name = u"Type Saisine"
verbose_name_plural = u"Types Saisine"
ordering = ('label',)
-class File(BaseHistorizedItem, OwnPerms):
+class File(BaseHistorizedItem, OwnPerms, ValueGetter):
TABLE_COLS = ['numeric_reference', 'year', 'internal_reference',
'file_type', 'saisine_type', 'towns', ]
year = models.IntegerField(_(u"Year"),
@@ -139,6 +139,14 @@ class File(BaseHistorizedItem, OwnPerms):
def get_total_number(cls):
return cls.objects.count()
+ def get_values(self, prefix=''):
+ values = super(File, self).get_values(prefix=prefix)
+ values['adminact_associated_file_towns_count'] = unicode(
+ self.towns.count())
+ values['adminact_associated_file_towns'] = u", ".join(
+ [unicode(town)for town in self.towns.all()])
+ return values
+
def __unicode__(self):
if self.cached_label:
return self.cached_label
diff --git a/archaeological_files/templates/ishtar/administrativeact_document.html b/archaeological_files/templates/ishtar/administrativeact_document.html
new file mode 100644
index 000000000..cdb2b45be
--- /dev/null
+++ b/archaeological_files/templates/ishtar/administrativeact_document.html
@@ -0,0 +1,23 @@
+{% extends "base.html" %}Q
+{% load i18n %}
+{% block extra_head %}
+{{search_form.media}}
+{{ template_form.media }}
+{% endblock %}
+
+{% block content %}
+<h2>{% trans "Document generation" %}</h2>
+<form action="." method="post">{% csrf_token %}
+<div class='form'>
+<table>
+{{ search_form.as_table }}
+</table>
+<h4>{% trans "Choose the type of document" %}</h4>
+<table>
+{{ template_form }}
+</table>
+<input type="submit" id="submit_form" name='validate' value="{% trans "Generate" %}"/>
+</div>
+</form>
+{% endblock %}
+
diff --git a/archaeological_files/urls.py b/archaeological_files/urls.py
index 72a6e2df7..9d1f4f56f 100644
--- a/archaeological_files/urls.py
+++ b/archaeological_files/urls.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2010-2012 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2010-2013 É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
@@ -59,5 +59,8 @@ urlpatterns += patterns('archaeological_files.views',
'show_file', name='show-historized-file'),
url(r'revert-file/(?P<pk>.+)/(?P<date>.+)$',
'revert_file', name='revert-file'),
- url(r'dashboard_file/$', 'dashboard_file', name='dashboard-file')
+ url(r'dashboard_file/$', 'dashboard_file', name='dashboard-file'),
+ url(r'file_administrativeact_document/$',
+ 'file_administrativeactfile_document',
+ name='administrativeact_document'),
)
diff --git a/archaeological_files/views.py b/archaeological_files/views.py
index 407bbe821..e55368e62 100644
--- a/archaeological_files/views.py
+++ b/archaeological_files/views.py
@@ -18,10 +18,12 @@
# See the file COPYING for details.
import json
+import os
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render_to_response
+from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _
from ishtar_common.views import get_item, show_item, revert_item
@@ -156,3 +158,29 @@ file_administrativeactfile_deletion_wizard = \
label=_(u"File: administrative act deletion"),
url_name='file_administrativeactfile_deletion',)
+def file_administrativeactfile_document(request):
+ dct = {}
+ if request.POST:
+ dct['search_form'] = AdministrativeActFileFormSelection(request.POST)
+ dct['template_form'] = DocumentGenerationAdminActForm(request.POST)
+ if dct['search_form'].is_valid() and dct['template_form'].is_valid():
+ doc = dct['template_form'].save(
+ dct['search_form'].cleaned_data.get('pk'))
+ if doc:
+ MIMES = {'odt':'application/vnd.oasis.opendocument.text',
+ 'ods':'application/vnd.oasis.opendocument.spreadsheet'}
+ ext = doc.split('.')[-1]
+ doc_name = slugify(doc.split(os.path.sep)[-1][:-len(ext)])+ "."\
+ + ext
+ mimetype = 'text/csv'
+ if ext in MIMES:
+ mimetype = MIMES[ext]
+ response = HttpResponse(open(doc), mimetype=mimetype)
+ response['Content-Disposition'] = 'attachment; filename=%s' % \
+ doc_name
+ return response
+ else:
+ dct['search_form'] = AdministrativeActFileFormSelection()
+ dct['template_form'] = DocumentGenerationAdminActForm()
+ return render_to_response('ishtar/administrativeact_document.html', dct,
+ context_instance=RequestContext(request))
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 3d6eaa15a..e846f15f8 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -31,7 +31,7 @@ from ishtar_common.utils import cached_label_changed
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
HistoricalRecords, LightHistorizedItem, OwnPerms, Department, Source,\
- Person, Organization, Town, Dashboard, IshtarUser
+ Person, Organization, Town, Dashboard, IshtarUser, ValueGetter
FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS
if FILES_AVAILABLE:
from archaeological_files.models import File
@@ -347,7 +347,7 @@ class ActType(GeneralType):
verbose_name_plural = _(u"Act types")
ordering = ('label',)
-class AdministrativeAct(BaseHistorizedItem, OwnPerms):
+class AdministrativeAct(BaseHistorizedItem, OwnPerms, ValueGetter):
TABLE_COLS = ['act_type', 'associated_file', 'operation',
'associated_file.towns', 'operation.towns']
TABLE_COLS_FILE = ['act_type', 'associated_file', 'associated_file.towns',]
@@ -375,6 +375,7 @@ class AdministrativeAct(BaseHistorizedItem, OwnPerms):
ref_sra = models.CharField(u"Référence SRA", max_length=15, blank=True,
null=True)
history = HistoricalRecords()
+ _prefix = 'adminact_'
class Meta:
verbose_name = _(u"Administrative act")
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py
index 093d137ae..320136aec 100644
--- a/ishtar_common/admin.py
+++ b/ishtar_common/admin.py
@@ -88,7 +88,7 @@ general_models = [models.OrganizationType, models.SourceType, models.AuthorType]
for model in general_models:
admin.site.register(model, GeneralTypeAdmin)
-basic_models = [models.IshtarUser]
+basic_models = [models.IshtarUser, models.DocumentTemplate]
if settings.COUNTRY == 'fr':
basic_models += [models.Arrondissement, models.Canton]
diff --git a/ishtar_common/migrations/0005_auto__add_documenttemplate.py b/ishtar_common/migrations/0005_auto__add_documenttemplate.py
new file mode 100644
index 000000000..383ee5a32
--- /dev/null
+++ b/ishtar_common/migrations/0005_auto__add_documenttemplate.py
@@ -0,0 +1,209 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'DocumentTemplate'
+ db.create_table('ishtar_common_documenttemplate', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('template', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ('associated_object_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('available', self.gf('django.db.models.fields.BooleanField')(default=True)),
+ ))
+ db.send_create_signal('ishtar_common', ['DocumentTemplate'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'DocumentTemplate'
+ db.delete_table('ishtar_common_documenttemplate')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.arrondissement': {
+ 'Meta': {'object_name': 'Arrondissement'},
+ 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.author': {
+ 'Meta': {'object_name': 'Author'},
+ 'author_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AuthorType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'author'", 'to': "orm['ishtar_common.Person']"})
+ },
+ 'ishtar_common.authortype': {
+ 'Meta': {'object_name': 'AuthorType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.canton': {
+ 'Meta': {'object_name': 'Canton'},
+ 'arrondissement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Arrondissement']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ },
+ 'ishtar_common.department': {
+ 'Meta': {'ordering': "['number']", 'object_name': 'Department'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'})
+ },
+ 'ishtar_common.documenttemplate': {
+ 'Meta': {'ordering': "['associated_object_name']", 'object_name': 'DocumentTemplate'},
+ 'associated_object_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'template': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ },
+ 'ishtar_common.historicalorganization': {
+ 'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalOrganization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', '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'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'organization_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.ishtaruser': {
+ 'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']},
+ 'person': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ishtaruser'", 'unique': 'True', 'to': "orm['ishtar_common.Person']"}),
+ 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
+ },
+ 'ishtar_common.organization': {
+ 'Meta': {'object_name': 'Organization'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', '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'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'organization_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.OrganizationType']"}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.organizationtype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'OrganizationType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.person': {
+ 'Meta': {'object_name': 'Person'},
+ 'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'attached_to': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Organization']", 'null': 'True', 'blank': 'True'}),
+ 'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.CharField', [], {'max_length': '40', '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'}),
+ 'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
+ 'person_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.PersonType']", 'symmetrical': 'False'}),
+ 'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}),
+ 'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'surname': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '2'}),
+ 'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.persontype': {
+ 'Meta': {'ordering': "('label',)", 'object_name': 'PersonType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.sourcetype': {
+ 'Meta': {'object_name': 'SourceType'},
+ 'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'ishtar_common.town': {
+ 'Meta': {'ordering': "['numero_insee']", 'object_name': 'Town'},
+ 'canton': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Canton']", 'null': 'True', 'blank': 'True'}),
+ 'center': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '27572', 'null': 'True', 'blank': 'True'}),
+ 'departement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']", 'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'numero_insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '6'}),
+ 'surface': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'ishtar_common.wizard': {
+ 'Meta': {'ordering': "['url_name']", 'object_name': 'Wizard'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'url_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
+ },
+ 'ishtar_common.wizardstep': {
+ 'Meta': {'ordering': "['wizard', 'order']", 'object_name': 'WizardStep'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {}),
+ 'url_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'wizard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Wizard']"})
+ }
+ }
+
+ complete_apps = ['ishtar_common'] \ No newline at end of file
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 89fbd1589..8d153f120 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -24,6 +24,7 @@ from cStringIO import StringIO
import datetime
from PIL import Image
import os
+import tempfile
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, ValidationError
@@ -43,6 +44,8 @@ from django.contrib import admin
from simple_history.models import HistoricalRecords as BaseHistoricalRecords
+from ooo_replace import ooo_replace
+
def post_save_user(sender, **kwargs):
user = kwargs['instance']
ishtaruser = None
@@ -57,6 +60,22 @@ def post_save_user(sender, **kwargs):
txt_idx='administrator'))
post_save.connect(post_save_user, sender=User)
+class ValueGetter(object):
+ _prefix = ""
+ def get_values(self, prefix=''):
+ if not prefix:
+ prefix = self._prefix
+ values = {}
+ for field_name in self._meta.get_all_field_names():
+ if not hasattr(self, field_name):
+ continue
+ value = getattr(self, field_name)
+ if hasattr(value, 'get_values'):
+ values.update(value.get_values(prefix + field_name + '_'))
+ else:
+ values[prefix + field_name] = value
+ return values
+
class HistoricalRecords(BaseHistoricalRecords):
def create_historical_record(self, instance, type):
history_modifier = getattr(instance, 'history_modifier', None)
@@ -592,6 +611,41 @@ class Dashboard:
if vals[v] == mx:
return v
+class DocumentTemplate(models.Model):
+ CLASSNAMES = (('archaeological_operations.models.AdministrativeAct',
+ _(u"Administrative Act")),)
+ name = models.CharField(_(u"Name"), max_length=100)
+ template = models.FileField(_(u"Template"), upload_to="upload/templates/")
+ associated_object_name = models.CharField(_(u"Associated object"),
+ max_length=100, choices=CLASSNAMES)
+ available = models.BooleanField(_(u"Available"), default=True)
+
+ class Meta:
+ verbose_name = _(u"Document template")
+ verbose_name_plural = _(u"Document templates")
+ ordering = ['associated_object_name']
+
+ def __unicode__(self):
+ return self.name
+
+ @classmethod
+ def get_tuples(cls, dct={}, empty_first=True):
+ dct['available'] = True
+ if empty_first:
+ yield ('', '--')
+ items = cls.objects.filter(**dct)
+ for item in items.order_by(*cls._meta.ordering).all():
+ yield (item.pk, _(unicode(item)))
+
+ def publish(self, c_object):
+ tempdir = tempfile.mkdtemp("-ishtardocs")
+ output_name = tempdir + os.path.sep + \
+ self.name.replace(' ', '_').lower() + u'-' +\
+ datetime.date.today().strftime('%Y-%m-%d') +\
+ u"." + self.template.name.split('.')[-1]
+ missing = ooo_replace(self.template, output_name, c_object.get_values())
+ return output_name
+
class Department(models.Model):
label = models.CharField(_(u"Label"), max_length=30)
number = models.CharField(_(u"Number"), unique=True, max_length=3)
@@ -654,7 +708,8 @@ class PersonType(GeneralType):
verbose_name_plural = _(u"Person types")
ordering = ('label',)
-class Person(Address, OwnPerms) :
+class Person(Address, OwnPerms, ValueGetter) :
+ _prefix = 'person_'
TYPE = (('Mr', _(u'Mr')),
('Ms', _(u'Miss')),
('Md', _(u'Mrs')),
diff --git a/ishtar_common/ooo_replace.py b/ishtar_common/ooo_replace.py
new file mode 100644
index 000000000..63b983b7b
--- /dev/null
+++ b/ishtar_common/ooo_replace.py
@@ -0,0 +1,102 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 É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 zipfile import ZipFile, ZIP_DEFLATED
+from cStringIO import StringIO
+from xml.etree.cElementTree import ElementTree, fromstring
+
+OOO_NS = "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}"
+
+def _set_value_from_formula(value, context):
+ value = value.strip()
+ if value.startswith("ooow:") and len(value) >= 5:
+ value = value[5:]
+ if value.startswith('"') and value.endswith('"') and len(value) > 1:
+ value = value[1:-1]
+ elif value in context:
+ value = unicode(context[value])
+ else:
+ value = None
+ return value
+
+def _parse_condition(condition, context):
+ # parse only == and != operator
+ operator = ""
+ if "!=" in condition:
+ operator = "!="
+ elif "==" in condition:
+ operator = "=="
+ else:
+ return
+ var1, var2 = condition.split(operator)
+ var1 = _set_value_from_formula(var1, context)
+ var2 = _set_value_from_formula(var2, context)
+ res = var1 == var2
+ if operator == '!=':
+ res = not res
+ return res
+
+def _format_value(value, default_value):
+ value = unicode(value) if value else default_value
+ #if hasattr(value, 'strftime'):
+ # value = value.strftime()
+ return value
+
+def ooo_replace(infile, outfile, context, default_value=''):
+ inzip = ZipFile(infile, 'r', ZIP_DEFLATED)
+ outzip = ZipFile(outfile, 'w', ZIP_DEFLATED)
+ content = ElementTree(fromstring(inzip.read('content.xml')))
+ missing_keys = set()
+ for xp in ('variable-set', 'variable-get'):
+ for p in content.findall(".//"+OOO_NS+xp):
+ name = p.get(OOO_NS+"name")
+ if name in context:
+ value = context[name]
+ p.text = _format_value(value, default_value)
+ else:
+ if default_value != None:
+ p.text = default_value
+ missing_keys.add(name)
+ for p in content.findall(".//"+OOO_NS+"conditional-text"):
+ condition = p.get(OOO_NS+"condition")
+ res = 'true' if _parse_condition(condition, context) else 'false'
+ value = p.get(OOO_NS+'string-value-if-' + res)
+ value = _format_value(value, default_value)
+ if value.strip() in context:
+ value = context[value.strip()]
+ p.text = value
+ for f in inzip.infolist():
+ if f.filename == 'content.xml':
+ s = StringIO()
+ content.write(s)
+ outzip.writestr('content.xml', s.getvalue())
+ else:
+ outzip.writestr(f, inzip.read(f.filename))
+ inzip.close()
+ outzip.close()
+ return missing_keys
+
+if __name__ == '__main__':
+ infile = "../archaeological_files/tests/AR_dossier_DRAC_modele_ishtar_1-MOD.odt"
+ outfile = "../archaeological_files/tests/AR_dossier_DRAC_modele_ishtar-test.odt"
+ rep = {"file_incharge_surname":u"Yann",
+ "file_incharge_name":u"Le Jeune",
+ "fileact_ref":u"ref"}
+ ooo_replace(infile, outfile, rep, default_value="")
diff --git a/ishtar_common/templates/ishtar/wizard/wizard_list_search_result.html b/ishtar_common/templates/ishtar/wizard/wizard_list_search_result.html
index c6be97b64..aca1798d9 100644
--- a/ishtar_common/templates/ishtar/wizard/wizard_list_search_result.html
+++ b/ishtar_common/templates/ishtar/wizard/wizard_list_search_result.html
@@ -3,7 +3,7 @@
{% block content %}
<div class='form'>
- <p>{% trans {%trans "PLease note that the file must be processed before :"%} %} {% calculated_deadline %} </p>
+ <p>{% trans {%trans "Please note that the file must be processed before :"%} %} {% calculated_deadline %} </p>
<p>{% trans {%trans "Item successfully saved"%} %}</p>
<p>{% trans "You have saved the following informations:" %}</p>
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 46ea938de..31f5f688b 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -608,9 +608,6 @@ def action(request, action_slug, obj_id=None, *args, **kwargs):
globals_dct = globals()
if action_slug in globals_dct:
return globals_dct[action_slug](request, dct, obj_id, *args, **kwargs)
- elif hasattr(ishtar_forms, action_slug + "_wizard"):
- return getattr(ishtar_forms, action_slug+"_wizard")(request, *args,
- **kwargs)
return render_to_response('index.html', dct,
context_instance=RequestContext(request))