diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-10-25 18:47:43 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2017-10-25 18:47:43 +0200 |
commit | 2cb20872730f20d1a0d73c321f269a754ffb5893 (patch) | |
tree | 997479d14469cda15f0ae5b20c9011eb3a71e6b6 | |
parent | fcec6f796641431981daaed874a1cda18336996a (diff) | |
parent | 92985883584d6f38313f4050d38eb77f5086896a (diff) | |
download | Ishtar-2cb20872730f20d1a0d73c321f269a754ffb5893.tar.bz2 Ishtar-2cb20872730f20d1a0d73c321f269a754ffb5893.zip |
Merge branch 'develop' into develop-bootstrap
41 files changed, 925 insertions, 1043 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53b4d7d88..fb2d4e824 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ before_script: - apt-get update - - apt-get install -q -y git python-pip libpq-dev python-dev libjpeg-dev zlib1g-dev libxml2-dev libxslt1-dev libgeos-dev tidy binutils libproj-dev gdal-bin - - pip install -q -r requirements.txt + - apt-get install -q -y git python-pip libpq-dev python-dev libjpeg-dev zlib1g-dev libxml2-dev libxslt1-dev libgeos-dev python-cairocffi tidy binutils libproj-dev gdal-bin libpangocairo-1.0-0 + - pip install -r requirements.txt - cp Makefile.example Makefile - cp example_project/local_settings.py.gitlab-ci example_project/local_settings.py diff --git a/Makefile.example b/Makefile.example index 8c79c209f..c3b40b6df 100644 --- a/Makefile.example +++ b/Makefile.example @@ -51,10 +51,10 @@ coverage: clean archaeological_context_records,archaeological_files,archaeological_finds,archaeological_warehouse,\ archaeological_files_pdl" ./manage.py test $(apps) && coverage report -build_gitlab: +build_gitlab: clean collectstatic cd $(project); $(PYTHON) ./manage.py migrate -test_gitlab: clean +test_gitlab: build_gitlab cd $(project); $(PYTHON) manage.py test $(apps) pep8: diff --git a/archaeological_context_records/data_importer.py b/archaeological_context_records/data_importer.py deleted file mode 100644 index 5fdc67949..000000000 --- a/archaeological_context_records/data_importer.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (C) 2015 É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.data_importer import * - -from archaeological_context_records import models - - -class ContextRecordsImporterBibracte(Importer): - DESC = u"Exports Bibracte : importeur pour l'onglet UE" - OBJECT_CLS = models.ContextRecord - DEFAULTS = {} - LINE_FORMAT = [ - # ID operation - ImportFormater('operation__operation_code', IntegerFormater(), - duplicate_fields=[('parcel__operation__operation_code', - False)]), - # ID UE - ImportFormater('external_id', UnicodeFormater(120), - duplicate_fields=[('label', False)],), - # Type - ImportFormater('unit', TypeFormater(models.Unit), required=False), - # description - ImportFormater('description', UnicodeFormater(1000), required=False,), - # interprétation - ImportFormater('interpretation', UnicodeFormater(1000), - required=False,), - # date ouverture - ImportFormater('opening_date', DateFormater(['%Y/%m/%d']), - required=False,), - # date fermeture - ImportFormater('closing_date', DateFormater(['%Y/%m/%d']), - required=False,), - # lien vers parcelle - ImportFormater('parcel__external_id', UnicodeFormater(12), - required=False,), - # lien vers ID sig - None, - # commentaire - ImportFormater('comment', UnicodeFormater(1000), required=False,), - # ???? - None, - # chrono #TODO! pas de vrai création de nouvelle et en cas de modif - # c'est la zone - ImportFormater('datings__period', TypeFormater(models.Period), - required=False), - ] - - -class ContextRecordsRelationImporterBibracte(Importer): - DESC = u"Exports Bibracte : importeur pour l'onglet relations entre UE" - OBJECT_CLS = models.RecordRelations - DEFAULTS = {} - LINE_FORMAT = [ - # code OA - ImportFormater( - 'left_record__operation__operation_code', IntegerFormater(), - duplicate_fields=[('right_record__operation__operation_code', - False)],), - # identifiant UE 1 - ImportFormater('left_record__external_id', UnicodeFormater(120),), - # type relation - ImportFormater('relation_type', TypeFormater(models.RelationType),), - # identifiant UE 2 - ImportFormater('right_record__external_id', UnicodeFormater(120),), - ] diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index a8517ed26..925a48597 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -578,6 +578,10 @@ class RecordRelations(GeneralRecordRelations, models.Model): class Meta: verbose_name = _(u"Record relation") verbose_name_plural = _(u"Record relations") + permissions = [ + ("view_recordrelation", u"Can view all Context record relations"), + ] + post_delete.connect(post_delete_record_relation, sender=RecordRelations) @@ -626,6 +630,9 @@ class RecordRelationView(models.Model): managed = False db_table = 'record_relations' unique_together = ('id', 'right_record') + permissions = [ + ("view_recordrelation", u"Can view all record relations - view"), + ] def __unicode__(self): return u"{} \"{}\"".format(self.relation_type, self.right_record) diff --git a/archaeological_context_records/templates/ishtar/sheet_contextrecord_pdf.html b/archaeological_context_records/templates/ishtar/sheet_contextrecord_pdf.html index a0d0affcf..b91500403 100644 --- a/archaeological_context_records/templates/ishtar/sheet_contextrecord_pdf.html +++ b/archaeological_context_records/templates/ishtar/sheet_contextrecord_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_contextrecord.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_context_records/templates/ishtar/sheet_contextrecordsource_pdf.html b/archaeological_context_records/templates/ishtar/sheet_contextrecordsource_pdf.html index 38c5d318e..c03b80a53 100644 --- a/archaeological_context_records/templates/ishtar/sheet_contextrecordsource_pdf.html +++ b/archaeological_context_records/templates/ishtar/sheet_contextrecordsource_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_contextrecordsource.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 3bfe544be..242ccadec 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -81,11 +81,11 @@ get_contextrecordsource = get_item( get_contextrecordrelation = get_item( models.RecordRelationView, 'get_contextrecordrelation', - 'contextrecordrelation') + 'contextrecordrelation', specific_perms=['view_recordrelation']) get_contextrecordrelationdetail = get_item( models.RecordRelations, 'get_contextrecordrelationdetail', - 'contextrecordrelationdetail') + 'contextrecordrelationdetail', specific_perms=['view_recordrelation']) record_search_wizard = SearchWizard.as_view([ ('general-record_search', RecordFormSelection)], diff --git a/archaeological_files/data_importer.py b/archaeological_files/data_importer.py deleted file mode 100644 index 96b2ee007..000000000 --- a/archaeological_files/data_importer.py +++ /dev/null @@ -1,359 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (C) 2013-2015 É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 datetime -import unicodecsv - -from django.conf import settings - -from ishtar_common.data_importer import * -from ishtar_common.models import OrganizationType - -from archaeological_operations.data_importer import * - -from archaeological_files import models - - -class ImportClosingFormater(ImportFormater): - def post_process(self, obj, context, value, owner=None): - value = self.formater.format(value) - if not value: - return - open_date = obj.reception_date or obj.creation_date - if not open_date: - return - obj.end_date = open_date + datetime.timedelta(30) - obj.save() - - -class ImportMayorFormater(ImportFormater): - def post_process(self, obj, context, value, owner=None): - value = self.formater.format(value) - if type(self.field_name) in (list, tuple): - return # not managed - associated_obj = get_object_from_path(obj, self.field_name) - if not value or not obj.main_town or not associated_obj: - return - if slugify(value).endswith('le-maire'): - value += u" de " + obj.main_town.name - value = value[:300] - setattr(associated_obj, self.field_name.split('__')[-1], value) - associated_obj.save() - - -class FilePostProcessing(object): - def post_processing(self, item, data): - if not item.end_date: # auto-close - open_date = item.reception_date or item.creation_date - if open_date: - item.end_date = open_date + datetime.timedelta(30) - item.save() - return item - - -class FileImporterSraPdL(FilePostProcessing, Importer): - DESC = u"Exports dossiers SRA PdL : importeur Filemaker dossiers" - SLUG = "sra-pdl-files" - LINE_FORMAT = [] - OBJECT_CLS = models.File - UNICITY_KEYS = ['external_id'] - DEFAULTS = { - ('responsible_town_planning_service', 'attached_to'): { - 'organization_type': OrganizationType.objects.get( - txt_idx="planning_service")}, - ('general_contractor', 'attached_to'): { - 'organization_type': OrganizationType.objects.get( - txt_idx="general_contractor")}, - tuple(): { - 'file_type': models.FileType.objects.get( - txt_idx='preventive'), - 'creation_date': datetime.datetime.now, - }, - ('in_charge',): {'attached_to': None}, # initialized in __init__ - } - - def _init_line_format(self): - tf = TownFormater() - tf.town_dct_init() - self.line_format = [ - None, # A, 1 - ImportFormater( - ['general_contractor__attached_to__address', # B, 2 - 'general_contractor__attached_to__postal_code', - 'general_contractor__attached_to__town'], - [UnicodeFormater(500, clean=True), - UnicodeFormater(5, re_filter=RE_CD_POSTAL_FILTER), - UnicodeFormater(70, clean=True), ], - regexp=RE_ADD_CD_POSTAL_TOWN, - regexp_formater_args=[[0], [1], [2]], required=False, - comment=u"Aménageur - adresse"), - ImportMayorFormater( - # C, 3 TODO - extraire nom_prenom_titre - 'general_contractor__raw_name', - UnicodeFormater(200), - comment=u"Aménageur - nom brut", - post_processing=True, - required=False), - None, # D, 4 - ImportFormater( - "general_contractor__title", # E, 5 - TypeFormater(models.TitleType), - required=False, - comment=u"Aménageur - titre"), - None, # F, 6 - None, # G, 7 - None, # H, 8 - ImportFormater("parcels__year", # I, 9 - YearNoFuturFormater(), - required=False), - # J, 10 - ImportParcelFormater('', required=False, post_processing=True), - None, # K, 11 - ImportFormater([['main_town', 'parcels__town']], # L, 12 - tf, - required=False, - comment=u"Commune (si non définie avant)"), - ImportFormater([['main_town', 'parcels__town']], # M, 13 - tf, - required=False, - comment=u"Commune (si non définie avant)"), - ImportFormater('saisine_type', # N, 14 - TypeFormater(models.SaisineType), - required=False, - comment=u"Type de saisine"), - None, # O, 15 - ImportFormater('name', # P, 16 - UnicodeFormater(), - comment=u"Nom du dossier", - required=False), - None, # Q, 17 - ImportFormater( - [ - 'responsible_town_planning_service__raw_name', - # R, 18 service instructeur - 'responsible_town_planning_service__attached_to__address', - 'responsible_town_planning_service__' - 'attached_to__postal_code', - 'responsible_town_planning_service__attached_to__town'], - [UnicodeFormater(300, clean=True), - UnicodeFormater(300, clean=True), - UnicodeFormater(5, re_filter=RE_CD_POSTAL_FILTER), - UnicodeFormater(70, clean=True), ], - regexp=RE_NAME_ADD_CD_POSTAL_TOWN, - regexp_formater_args=[[0], [1], [2], [3]], - comment=u"Service instructeur - adresse", - required=False), - ImportFormater( - 'comment', # S, 19 - UnicodeFormater(prefix=u'* Considérants : '), - comment=u"Commentaire", - concat=True, - required=False), - ImportYearFormater('reception_date', # T, 20 - DateFormater(['%d/%m/%Y', '%d/%m/%Y']), - comment=u"Date de réception", - required=False, - duplicate_fields=[['creation_date', False]]), - None, # U, 21 - None, # V, 22 - None, # W, 23 - None, # X, 24 - None, # Y, 25 - None, # Z, 26 - None, # AA, 27 - None, # AB, 28 - None, # AC, 29 - None, # AD, 30 - None, # AE, 31 - None, # AF, 32 - None, # AG, 33 - None, # AH, 34 - ImportFormater('creation_date', # AI, 35 - DateFormater(['%d/%m/%Y', '%d/%m/%y']), - force_value=True, - comment=u"Date de création", - required=False,), - None, # AJ, 36 - ImportFormater('comment', # AK, 37 - UnicodeFormater(prefix=u"* Historique : "), - comment=u"Commentaire", - concat=True, required=False), - ImportFormater('internal_reference', # AL, 38 - UnicodeFormater(60), - comment=u"Autre référence", - required=False), - None, # AM, 39 - None, # AN, 40 - ImportFormater('comment', # AO, 41 - UnicodeFormater( - prefix=u"* Justificatif de prescription : "), - comment=u"Justificatif de prescription", - concat=True, required=False), - ImportFormater('comment', # AP, 42 - UnicodeFormater( - prefix=u"* Justificatif d'intervention : "), - comment=u"Justificatif d'intervention", - concat=True, required=False), - None, # AQ, 43 - None, # AR, 44 - None, # AS, 45 - None, # AT, 46 - ImportFormater('comment', # AU, 47 - UnicodeFormater( - prefix=u"* Méthodologie de l'opération : "), - comment=u"Méthodologie de l'opération", - concat=True, required=False), - None, # AV, 48 - ImportFormater('permit_reference', # AW, 49 - UnicodeFormater(300, clean=True), - regexp=RE_PERMIT_REFERENCE, - comment=u"Réf. du permis de construire", - required=False), - ImportFormater('comment', # AX, 50 - UnicodeFormater( - prefix=u"* Référence de dossier aménageur : "), - comment=u"Référence de dossier aménageur", - concat=True, required=False), - None, # AY, 51 - None, # AZ, 52 - ImportFormater('comment', # BA, 53 - UnicodeFormater( - prefix=u"* Numéro d'arrêté préfectoral : "), - comment=u"Numéro d'arrêté préfectoral", - concat=True, required=False), - ImportFormater('comment', # BB, 54 - UnicodeFormater( - prefix=u"* Numéro d'arrêté SRA : "), - comment=u"Numéro d'arrêté SRA", - concat=True, required=False), - ImportFormater('comment', # BC, 55 - UnicodeFormater( - prefix=u"* Numéro d'arrêté de " - u"post-diagnostic : "), - comment=u"Numéro d'arrêté de post-diagnostic", - concat=True, required=False), - None, # BD, 56 - ImportFormater([['main_town', 'parcels__town']], # BE, 57 - TownINSEEFormater(), - required=False, - comment=u"Commune (si non définie avant)"), - ImportFormater('comment', # BF, 58 - UnicodeFormater(2000), - comment=u"Commentaire", - concat=True, required=False), - None, # BG, 59 - None, # BH, 60 - None, # BI, 61 - None, # BJ, 62 - None, # BK, 63 - None, # BL, 64 - None, # BM, 65 - None, # BN, 66 - None, # BO, 67 - None, # BP, 68 - None, # BQ, 69 - None, # BR, 70 - None, # BS, 71 - ImportFormater( # BT, 72 nom service instructeur - ['responsible_town_planning_service__attached_to__name', ], - [UnicodeFormater(300, clean=True), ], - regexp=RE_ORGA, - comment=u"Service instructeur - nom", - required=False), - None, # BU, 73 - None, # BV, 74 - ImportFormater( - 'in_charge__raw_name', # BW, 75 responsable - UnicodeFormater(200), - comment=u"Responsable - nom brut", - required=False), - ImportFormater('total_surface', # BX, 76 surface totale - SurfaceFormater(), - comment=u"Surface totale", - required=False), - ImportFormater('total_developed_surface', - # BY, 77 surface totale aménagée - SurfaceFormater(), - comment=u"Surface totale aménagée", - required=False), - None, # BZ, 78 - None, # CA, 79 - None, # CB, 80 - None, # CC, 81 - None, # CD, 82 - None, # CE, 83 - None, # CF, 84 - ImportFormater('permit_type', - TypeFormater(models.PermitType), - required=False, - comment=u"Type de permis"), # CG, 85 - None, # CH, 85 - ImportFormater('year', # CI, 86 - IntegerFormater(), - comment=u"Année du dossier", - required=True), - ImportFormater('numeric_reference', # CJ, 87 - IntegerFormater(), - comment=u"Identifiant numérique", - required=True), - ImportFormater('external_id', # CK, 88 - UnicodeFormater(), - comment=u"Identifiant externe", - required=True), - ] - - def __init__(self, *args, **kwargs): - super(FileImporterSraPdL, self).__init__(*args, **kwargs) - self.DEFAULTS[('in_charge',)]['attached_to'], created = \ - models.Organization.objects.get_or_create( - name='SRA Pays de la Loire', - defaults={ - 'organization_type': - OrganizationType.objects.get(txt_idx='sra')}) - self._init_line_format() - if tuple() not in self._defaults: - self._defaults[tuple()] = {} - self._defaults[tuple()]['history_modifier'] = self.history_modifier - self._associate_db_target_to_formaters() - - -def test(filename): - importer = FileImporterSraPdL(skip_lines=3, output='cli') - with open(filename) as csv_file: - encodings = [settings.ENCODING, settings.ALT_ENCODING, 'utf-8'] - for encoding in encodings: - try: - importer.importation( - [line for line in - unicodecsv.reader(csv_file, encoding='utf-8')]) - # importer.importation(unicode_csv_reader( - # [line.decode(encoding) - # for line in csv_file.readlines()]) - print importer.get_csv_errors() - break - except ImporterError, e: - print(unicode(e)) - if e.type == ImporterError.HEADER \ - and encoding != encodings[-1]: - csv_file.seek(0) - continue - except UnicodeDecodeError: - if encoding != encodings[-1]: - csv_file.seek(0) - continue diff --git a/archaeological_files/templates/ishtar/sheet_file_pdf.html b/archaeological_files/templates/ishtar/sheet_file_pdf.html index eaf2a9436..7335eaec7 100644 --- a/archaeological_files/templates/ishtar/sheet_file_pdf.html +++ b/archaeological_files/templates/ishtar/sheet_file_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_file.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/data_importer.py b/archaeological_finds/data_importer.py deleted file mode 100644 index e0c18d1bf..000000000 --- a/archaeological_finds/data_importer.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (C) 2015 É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.data_importer import * - -from archaeological_finds import models - - -class FindsImporterBibracte(Importer): - DESC = u"Exports Bibracte : importeur pour l'onglet mobilier" - OBJECT_CLS = models.BaseFind - DEFAULTS = {} - LINE_FORMAT = [ - # OA - ImportFormater('context_record__operation__operation_code', - IntegerFormater(),), - # external_id - ImportFormater( - 'external_id', UnicodeFormater(120, notnull=True), - duplicate_fields=[('find__external_id', False), - ('label', False), - ('find__label', False)]), - # isolé ou non (si non isolé = lot) - None, # à corriger - # ImportFormater( - # 'is_isolated', - # StrToBoolean(choices={'lot': False, 'objet': True}), - # required=False), - # ??? - None, - # A voir - None, - # cf type - None, - # Type = sous classe de matériaux = Liste hiérarchique - ImportFormater('find__material_types', - TypeFormater(models.MaterialType), required=False), - # ??? - None, - # lien avec contenant - None, - # = nombre - ImportFormater('find__find_number', IntegerFormater(), required=False), - # poids - ImportFormater('find__weight', FloatFormater(), required=False), - # unité (g par défault) - ImportFormater('find__weight_unit', - StrChoiceFormater(models.WEIGHT_UNIT), required=False), - # lien UE - ImportFormater('context_record__external_id', UnicodeFormater(120),), - # date decouverte - ImportFormater('discovery_date', DateFormater(['%Y/%m/%d']), - required=False,), - # lien parcelle (unique) - None, - # etat conservation - ImportFormater('find__conservatory_state', - TypeFormater(models.ConservatoryState), required=False), - # preservation_to_consider - ImportFormater('find__preservation_to_considers', - TypeFormater(models.TreatmentType), required=False), - # comment - ImportFormater('comment', UnicodeFormater(1000), required=False), - # lien vers plusieurs chrono (voir gestion actuelle chrono) - None, - # ImportFormater('find__datings__period', TypeFormater(Period, - # many_split="&"), required=False), - # topographic_localisation - ImportFormater('topographic_localisation', UnicodeFormater(120), - required=False), - # special_interest - ImportFormater('special_interest', UnicodeFormater(120), - required=False), - # description - ImportFormater('description', UnicodeFormater(1000), required=False), - # remontage - None - ] - - -class FindAltImporterBibracte(Importer): - DESC = u"Exports Bibracte : importeur pour l'onglet prélèvement" - OBJECT_CLS = models.BaseFind - DEFAULTS = {} - LINE_FORMAT = [ - # code OA - ImportFormater('context_record__operation__operation_code', - IntegerFormater(),), - # identifiant prelevement - ImportFormater('external_id', UnicodeFormater(120, notnull=True), - duplicate_fields=[('find__external_id', False)]), - # nature - ImportFormater('find__material_types', - TypeFormater(models.MaterialType), required=False), - # identifiant UE - ImportFormater('context_record__external_id', UnicodeFormater(120),), - # identifiant materiel - None, - # commentaire - ImportFormater('comment', UnicodeFormater(1000), required=False), - ] - - -class ImportTreatmentFormater(ImportFormater): - def post_process(self, obj, context, value, owner=None): - if obj.upstream_treatment.count(): - return - ope_code = context['upstream_treatment'][ - 'base_finds']['context_record']['operation']['operation_code'] - ope_code = int(ope_code) - downstream = models.Find.objects.filter( - external_id=value, - base_finds__context_record__operation__operation_code=ope_code) - if not downstream.count(): - return - downstream = downstream.all()[0] - downstream.upstream_treatment = obj - downstream.save() - upstream = downstream.duplicate(owner) - upstream.downstream_treatment = obj - upstream.save() - return - - -class TreatmentImporterBibracte(Importer): - DESC = u"Exports Bibracte : importeur pour l'onglet traitement" - OBJECT_CLS = models.Treatment - DEFAULTS = {} - LINE_FORMAT = [ - # code OA - ImportFormater( - 'upstream_treatment__base_finds__context_record__operation__' - 'operation_code', - UnicodeFormater(120, notnull=True)), - # identifiant - ImportTreatmentFormater( - 'external_id', - UnicodeFormater(120, notnull=True), post_processing=True), - None, - # traitement - ImportFormater('treatment_type', TypeFormater(models.TreatmentType),), - ] diff --git a/archaeological_finds/templates/ishtar/sheet_find_pdf.html b/archaeological_finds/templates/ishtar/sheet_find_pdf.html index 262bcdad7..11c39f059 100644 --- a/archaeological_finds/templates/ishtar/sheet_find_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_find_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_find.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html b/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html index 2b55f0f76..47a4d2bd8 100644 --- a/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_findbasket_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_findbasket.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_findsource_pdf.html b/archaeological_finds/templates/ishtar/sheet_findsource_pdf.html index 26ef9f2d7..7ca3bd3c1 100644 --- a/archaeological_finds/templates/ishtar/sheet_findsource_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_findsource_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_findsource.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_treatment_pdf.html b/archaeological_finds/templates/ishtar/sheet_treatment_pdf.html index 08df52e97..ccd860ec9 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatment_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_treatment_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_treatment.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> - – <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_treatmentfile_pdf.html b/archaeological_finds/templates/ishtar/sheet_treatmentfile_pdf.html index be64ff7eb..c216556b3 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatmentfile_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_treatmentfile_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_treatmentfile.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> - – <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_treatmentfilesource_pdf.html b/archaeological_finds/templates/ishtar/sheet_treatmentfilesource_pdf.html index d0a0ec8e7..2ef4d63b5 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatmentfilesource_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_treatmentfilesource_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_treatmentfilesource.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_finds/templates/ishtar/sheet_treatmentsource_pdf.html b/archaeological_finds/templates/ishtar/sheet_treatmentsource_pdf.html index c38764559..4b7218a14 100644 --- a/archaeological_finds/templates/ishtar/sheet_treatmentsource_pdf.html +++ b/archaeological_finds/templates/ishtar/sheet_treatmentsource_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_treatmentsource.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_operations/data_importer.py b/archaeological_operations/data_importer.py deleted file mode 100644 index b4cd2f0d0..000000000 --- a/archaeological_operations/data_importer.py +++ /dev/null @@ -1,280 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Copyright (C) 2015 É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 re - -from django.db import IntegrityError -from django.template.defaultfilters import slugify - -from ishtar_common.data_importer import * -from ishtar_common.models import Town, OrganizationType, SourceType, \ - SupportType, Format, AuthorType - -from archaeological_operations import models -from archaeological_operations.forms import OPERATOR -from archaeological_operations.utils import parse_parcels - -RE_PERMIT_REFERENCE = re.compile('[A-Za-z]*(.*)') - - -class ImportParcelFormater(ImportFormater): - NEED = ['town', ] - PARCEL_OWNER_KEY = 'associated_file' - - def post_process(self, obj, context, value, owner=None): - value = value.strip() - base_dct = {self.PARCEL_OWNER_KEY: obj, 'history_modifier': owner} - if 'parcels' in context: - for key in context['parcels']: - if context['parcels'][key]: - base_dct[key] = context['parcels'][key] - for parcel_dct in parse_parcels(value, owner=owner): - parcel_dct.update(base_dct) - try: - models.Parcel.objects.get_or_create(**parcel_dct) - except IntegrityError: - try: - p = unicode(parcel_dct) - except UnicodeDecodeError: - try: - p = str(parcel_dct).decode('utf-8') - except UnicodeDecodeError: - p = u"" - raise ImporterError(u"Erreur d'import parcelle, contexte : %s" - % p) - - -class ImportYearFormater(ImportFormater): - def post_process(self, obj, context, value, owner=None): - value = self.formater.format(value) - if not value: - return - obj.year = value.year - obj.save() - - -class TownFormater(Formater): - def __init__(self, town_full_dct={}, town_dct={}): - self._town_full_dct = town_full_dct - self._town_dct = town_dct - self._initialized = False if not self._town_full_dct else True - - def town_dct_init(self): - for town in Town.objects.all(): - key = (slugify(town.name.strip()), town.numero_insee[:2]) - if key in self._town_full_dct: - # print("Danger! %s is ambiguous with another town on the same" - # " department." % town.name) - continue - self._town_full_dct[key] = town - key = slugify(town.name.strip()) - if key in self._town_dct: - # print("Warning %s is ambiguous with no department provided" % - # town.name) - continue - self._town_dct[key] = town - self._initialized = True - - def format(self, value, extra=None): - if not self._initialized: - self.town_dct_init() - m = RE_FILTER_CEDEX.match(value) - if m: - value = m.groups()[0] - if not value: - return None - if extra: - key = (slugify(value), extra) - if key in self._town_full_dct: - return self._town_full_dct[key] - key = slugify(value) - if key in self._town_dct: - return self._town_dct[key] - - -class TownINSEEFormater(Formater): - def __init__(self): - self._town_dct = {} - - def format(self, value, extra=None): - value = value.strip() - if not value: - return None - if value in self._town_dct: - return self._town_dct[value] - q = Town.objects.filter(numero_insee=value) - if not q.count(): - return - self._town_dct[value] = q.all()[0] - return self._town_dct[value] - - -class SurfaceFormater(Formater): - def test(self): - assert self.format(u"352 123") == 352123 - assert self.format(u"456 789 m²") == 456789 - assert self.format(u"78ha") == 780000 - - def format(self, value, extra=None): - value = value.strip() - if not value: - return None - factor = 1 - if value.endswith(u"m2") or value.endswith(u"m²"): - value = value[:-2] - if value.endswith(u"ha"): - value = value[:-2] - factor = 10000 - try: - return int(value.replace(' ', '')) * factor - except ValueError: - raise ImporterError("Erreur import surface : %s" % unicode(value)) - -# RE_ADD_CD_POSTAL_TOWN = re.compile("(.*)[, ](\d{5}) (.*?) *(?: "\ -# "*CEDEX|cedex|Cedex *\d*)*") - -RE_NAME_ADD_CD_POSTAL_TOWN = re.compile( - "(.+)?[, ]*" + NEW_LINE_BREAK + "(.+)?[, ]*(\d{2} *\d{3})[, ]*(.+)") - -RE_ADD_CD_POSTAL_TOWN = re.compile("(.+)?[, ]*(\d{2} *\d{3})[, ]*(.+)") - -RE_CD_POSTAL_FILTER = re.compile("(\d*) (\d*)") - -RE_ORGA = re.compile("([^,\n]*)") - - -class OperationImporterBibracte(Importer): - OBJECT_CLS = models.Operation - DESC = u"Exports Bibracte : importeur pour l'onglet opération" - DEFAULTS = { - ('operator',): { - 'organization_type': OPERATOR - }, - } - LINE_FORMAT = [ - # CODE OPE - ImportFormater('operation_code', IntegerFormater(),), - # REGION - None, - # TYPE operation - ImportFormater('operation_type', TypeFormater(models.OperationType),), - # NOM - ImportFormater('common_name', UnicodeFormater(120),), - # OPERATEUR - ImportFormater('operator__name', UnicodeFormater(120),), - # resp. lien IMPORT avec personne - ImportFormater('in_charge__raw_name', UnicodeFormater(300),), - # début - ImportFormater('start_date', DateFormater(['%Y/%m/%d']),), - # fin - ImportFormater('excavation_end_date', DateFormater(['%Y/%m/%d']),), - # Chronos - ImportFormater('periods', TypeFormater(models.Period, many_split="&"), - required=False), - ] - -RE_PARCEL_SECT_NUM = re.compile("([A-Za-z]*)([0-9]*)") -RE_NUM_INSEE = re.compile("([0-9]*)") - - -class ParcelImporterBibracte(Importer): - OBJECT_CLS = models.Parcel - DESC = u"Exports Bibracte : importeur pour l'onglet parcelles" - DEFAULTS = { - ('operator',): { - 'organization_type': OrganizationType.objects.get( - txt_idx="operator")}, - } - LINE_FORMAT = [ - # code OA - ImportFormater('operation__operation_code', IntegerFormater(),), - # identifiant parcelle - ImportFormater( - ['section', 'parcel_number'], - [UnicodeFormater(4), UnicodeFormater(6), ], - regexp=RE_PARCEL_SECT_NUM, - regexp_formater_args=[[0], [1]], required=False, - duplicate_fields=[('external_id', False)],), - # numero parcelle - ImportFormater('parcel_number', UnicodeFormater(6), - required=False,), - # section cadastre - ImportFormater('section', UnicodeFormater(4), - required=False,), - # annee cadastre - ImportFormater('year', YearFormater(), required=False,), - # nom commune - None, - # numero INSEE commune - ImportFormater('town__numero_insee', UnicodeFormater(6), - regexp=RE_NUM_INSEE, required=False,), - # nom departement - None, - # lieu dit adresse - ImportFormater('address', UnicodeFormater(500), - required=False,), - ] - -MAIN_AUTHOR, created = AuthorType.objects.get_or_create(txt_idx='main_author') - - -class DocImporterBibracte(Importer): - OBJECT_CLS = models.OperationSource - DEFAULTS = { - ('authors',): {'author_type': MAIN_AUTHOR}, - } - DESC = u"Exports Bibracte : importeur pour l'onglet documentation" - LINE_FORMAT = [ - # code OA - ImportFormater('operation__operation_code', IntegerFormater(),), - # identifiant documentation - ImportFormater('external_id', UnicodeFormater(12),), - # type - ImportFormater('source_type', TypeFormater(SourceType), - required=False), - # nature support - ImportFormater('support_type', TypeFormater(SupportType), - required=False), - # nombre element - ImportFormater('item_number', IntegerFormater(), required=False), - # auteur - ImportFormater('authors__person__raw_name', UnicodeFormater(300), - required=False), - # annee - ImportFormater('creation_date', DateFormater(['%Y']),), - # format - ImportFormater('format_type', TypeFormater(Format), required=False), - # description legende - ImportFormater('description', UnicodeFormater(1000), required=False), - # type contenant - None, - # numero contenant - None, - # commentaire - ImportFormater('comment', UnicodeFormater(1000), required=False), - # echelle - ImportFormater('scale', UnicodeFormater(30), required=False), - # type sous contenant - None, - # numero sous contenant - None, - # informations complementaires - ImportFormater('additional_information', UnicodeFormater(1000), - required=False), - ] diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index dd3e65534..70c1c02ba 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -853,6 +853,9 @@ class RecordRelations(GeneralRecordRelations, models.Model): verbose_name = _(u"Operation record relation") verbose_name_plural = _(u"Operation record relations") ordering = ('left_record', 'relation_type') + permissions = [ + ("view_operationrelation", u"Can view all Operation relations"), + ] post_delete.connect(post_delete_record_relation, sender=RecordRelations) diff --git a/archaeological_operations/templates/ishtar/sheet_administrativeact_pdf.html b/archaeological_operations/templates/ishtar/sheet_administrativeact_pdf.html index b6d257cb0..be3e24428 100644 --- a/archaeological_operations/templates/ishtar/sheet_administrativeact_pdf.html +++ b/archaeological_operations/templates/ishtar/sheet_administrativeact_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_administrativeact.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_operations/templates/ishtar/sheet_operation_pdf.html b/archaeological_operations/templates/ishtar/sheet_operation_pdf.html index dc3c8b46f..7d86bd924 100644 --- a/archaeological_operations/templates/ishtar/sheet_operation_pdf.html +++ b/archaeological_operations/templates/ishtar/sheet_operation_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_operation.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_operations/templates/ishtar/sheet_operationsource_pdf.html b/archaeological_operations/templates/ishtar/sheet_operationsource_pdf.html index 1b2cd9ff3..68eb7aa2d 100644 --- a/archaeological_operations/templates/ishtar/sheet_operationsource_pdf.html +++ b/archaeological_operations/templates/ishtar/sheet_operationsource_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_operationsource.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 67b89ce11..b75c02cae 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -19,6 +19,7 @@ import json import datetime +from subprocess import Popen, PIPE import StringIO import zipfile @@ -1043,6 +1044,32 @@ class OperationTest(TestCase, OperationInitTest): self.assertEqual(response.status_code, 200) self.assertIn('class="sheet"', response.content) + def test_show_pdf(self): + operation = self.operations[0] + c = Client() + response = c.get(reverse('show-operation', + kwargs={'pk': operation.pk, 'type': 'pdf'})) + self.assertEqual(response.status_code, 200) + # empty content when not allowed + self.assertEqual(response.content, "") + c.login(username=self.username, password=self.password) + response = c.get(reverse('show-operation', + kwargs={'pk': operation.pk, 'type': 'pdf'})) + self.assertEqual(response.status_code, 200) + f = StringIO.StringIO(response.content) + filetype = Popen("/usr/bin/file -b --mime -", shell=True, stdout=PIPE, + stdin=PIPE).communicate(f.read(1024))[0].strip() + self.assertTrue(filetype.startswith('application/pdf')) + + def test_show_odt(self): + operation = self.operations[0] + c = Client() + response = c.get(reverse('show-operation', + kwargs={'pk': operation.pk, 'type': 'pdf'})) + self.assertEqual(response.status_code, 200) + # empty content when not allowed + self.assertEqual(response.content, "") + c.login(username=self.username, password=self.password) response = c.get(reverse('show-operation', kwargs={'pk': operation.pk, 'type': 'odt'})) self.assertEqual(response.status_code, 200) diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 71f31981a..fdd3a5e63 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -262,6 +262,11 @@ class Container(LightHistorizedItem, ImageModel): 'location': 'location__pk', 'container_type': 'container_type__pk', 'reference': 'reference__icontains', + 'finds__base_finds__context_record__operation': + 'finds__base_finds__context_record__operation', + 'finds__base_finds__context_record': + 'finds__base_finds__context_record', + 'finds': 'finds', } SHOW_URL = 'show-container' COL_LABELS = { diff --git a/archaeological_warehouse/templates/ishtar/sheet_container_pdf.html b/archaeological_warehouse/templates/ishtar/sheet_container_pdf.html index 5e4947cfa..ba0e3164c 100644 --- a/archaeological_warehouse/templates/ishtar/sheet_container_pdf.html +++ b/archaeological_warehouse/templates/ishtar/sheet_container_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_container.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/archaeological_warehouse/templates/ishtar/sheet_warehouse_pdf.html b/archaeological_warehouse/templates/ishtar/sheet_warehouse_pdf.html index 260834ac6..d95efe58f 100644 --- a/archaeological_warehouse/templates/ishtar/sheet_warehouse_pdf.html +++ b/archaeological_warehouse/templates/ishtar/sheet_warehouse_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_warehouse.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/example_project/.coveragerc b/example_project/.coveragerc index 43462778f..ff9237bdd 100644 --- a/example_project/.coveragerc +++ b/example_project/.coveragerc @@ -6,4 +6,5 @@ exclude_lines = [run] omit = */migrations/* + */old_migrations/* diff --git a/fixtures/initial_data-auth-fr.json b/fixtures/initial_data-auth-fr.json index 43d11248b..4fa4af0e1 100644 --- a/fixtures/initial_data-auth-fr.json +++ b/fixtures/initial_data-auth-fr.json @@ -4807,6 +4807,226 @@ } }, { + "model": "auth.permission", + "fields": { + "name": "Can add Importer - Target key group", + "content_type": [ + "ishtar_common", + "targetkeygroup" + ], + "codename": "add_targetkeygroup" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can change Importer - Target key group", + "content_type": [ + "ishtar_common", + "targetkeygroup" + ], + "codename": "change_targetkeygroup" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can delete Importer - Target key group", + "content_type": [ + "ishtar_common", + "targetkeygroup" + ], + "codename": "delete_targetkeygroup" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can view all Containers", + "content_type": [ + "archaeological_warehouse", + "container" + ], + "codename": "view_container" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can view own Container", + "content_type": [ + "archaeological_warehouse", + "container" + ], + "codename": "view_own_container" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can add own Container", + "content_type": [ + "archaeological_warehouse", + "container" + ], + "codename": "add_own_container" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can change own Container", + "content_type": [ + "archaeological_warehouse", + "container" + ], + "codename": "change_own_container" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can delete own Container", + "content_type": [ + "archaeological_warehouse", + "container" + ], + "codename": "delete_own_container" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can add Treatment emergency type", + "content_type": [ + "archaeological_finds", + "treatmentemergencytype" + ], + "codename": "add_treatmentemergencytype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can change Treatment emergency type", + "content_type": [ + "archaeological_finds", + "treatmentemergencytype" + ], + "codename": "change_treatmentemergencytype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can delete Treatment emergency type", + "content_type": [ + "archaeological_finds", + "treatmentemergencytype" + ], + "codename": "delete_treatmentemergencytype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can add Alteration type", + "content_type": [ + "archaeological_finds", + "alterationtype" + ], + "codename": "add_alterationtype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can change Alteration type", + "content_type": [ + "archaeological_finds", + "alterationtype" + ], + "codename": "change_alterationtype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can delete Alteration type", + "content_type": [ + "archaeological_finds", + "alterationtype" + ], + "codename": "delete_alterationtype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can add Alteration cause type", + "content_type": [ + "archaeological_finds", + "alterationcausetype" + ], + "codename": "add_alterationcausetype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can change Alteration cause type", + "content_type": [ + "archaeological_finds", + "alterationcausetype" + ], + "codename": "change_alterationcausetype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can delete Alteration cause type", + "content_type": [ + "archaeological_finds", + "alterationcausetype" + ], + "codename": "delete_alterationcausetype" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can view all Operation relations", + "content_type": [ + "archaeological_operations", + "recordrelations" + ], + "codename": "view_operationrelation" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can view all Context record relations", + "content_type": [ + "archaeological_context_records", + "recordrelations" + ], + "codename": "view_recordrelation" + } +}, +{ + "model": "auth.permission", + "fields": { + "name": "Can view all record relations - view", + "content_type": [ + "archaeological_context_records", + "recordrelationview" + ], + "codename": "view_recordrelation" + } +}, +{ "model": "auth.group", "fields": { "name": "Op\u00e9rations : lecture", @@ -4815,6 +5035,11 @@ "view_operation", "archaeological_operations", "operation" + ], + [ + "view_operationrelation", + "archaeological_operations", + "recordrelations" ] ] } @@ -4841,6 +5066,16 @@ "view_contextrecord", "archaeological_context_records", "contextrecord" + ], + [ + "view_recordrelation", + "archaeological_context_records", + "recordrelations" + ], + [ + "view_recordrelation", + "archaeological_context_records", + "recordrelationview" ] ] } @@ -5050,6 +5285,11 @@ "add_operation", "archaeological_operations", "operation" + ], + [ + "add_recordrelations", + "archaeological_operations", + "recordrelations" ] ] } @@ -5068,6 +5308,16 @@ "delete_operation", "archaeological_operations", "operation" + ], + [ + "change_recordrelations", + "archaeological_operations", + "recordrelations" + ], + [ + "delete_recordrelations", + "archaeological_operations", + "recordrelations" ] ] } @@ -5112,6 +5362,11 @@ "add_contextrecord", "archaeological_context_records", "contextrecord" + ], + [ + "add_recordrelations", + "archaeological_context_records", + "recordrelations" ] ] } @@ -5130,6 +5385,16 @@ "delete_contextrecord", "archaeological_context_records", "contextrecord" + ], + [ + "change_recordrelations", + "archaeological_context_records", + "recordrelations" + ], + [ + "delete_recordrelations", + "archaeological_context_records", + "recordrelations" ] ] } @@ -6235,5 +6500,49 @@ ] ] } +}, +{ + "model": "auth.group", + "fields": { + "name": "Contenants : ajout", + "permissions": [ + [ + "add_container", + "archaeological_warehouse", + "container" + ] + ] + } +}, +{ + "model": "auth.group", + "fields": { + "name": "Contenants : lecture", + "permissions": [ + [ + "view_container", + "archaeological_warehouse", + "container" + ] + ] + } +}, +{ + "model": "auth.group", + "fields": { + "name": "Contenants : modification/suppression", + "permissions": [ + [ + "change_container", + "archaeological_warehouse", + "container" + ], + [ + "delete_container", + "archaeological_warehouse", + "container" + ] + ] + } } ] diff --git a/install/ishtar-install b/install/ishtar-install index 36b937388..a34b1984c 100755 --- a/install/ishtar-install +++ b/install/ishtar-install @@ -118,16 +118,11 @@ do_install() { ;; debian) - MAINBACKS=`cat /etc/apt/sources.list | grep jessie-backports |grep -v "^#"` - ALLBACKS='' - if [ "$(ls -A /etc/apt/sources.list.d/)" ]; then - ALLBACKS=`cat /etc/apt/sources.list.d/* | grep jessie-backports |grep -v "^#"` - fi - if [ "$ALLBACKS" != '' ] || [ "$MAINBACKS" != '' ]; then - backports_activated='true'; - fi dist_version="$(cat /etc/debian_version | sed 's/\/.*//' | sed 's/\..*//')" case "$dist_version" in + 9) + dist_version="stretch" + ;; 8) dist_version="jessie" ;; @@ -135,6 +130,16 @@ do_install() { dist_version="wheezy" ;; esac + set +e + MAINBACKS=`cat /etc/apt/sources.list | grep $dist_version'-backports' |grep -v "^#"` + ALLBACKS='' + if [ "$(ls -A /etc/apt/sources.list.d/)" ]; then + ALLBACKS=`cat /etc/apt/sources.list.d/* | grep $dist_version'-backports' |grep -v "^#"` + fi + set -e + if [ "$ALLBACKS" != '' ] || [ "$MAINBACKS" != '' ]; then + backports_activated='true'; + fi ;; oracleserver) @@ -282,7 +287,7 @@ EOF # Run setup for each distro accordingly case "$lsb_dist" in ubuntu|debian) - if [ "$dist_version" != "jessie" ] && [ "$dist_version" != "wheezy" ]; then + if [ "$dist_version" != "stretch" ] && [ "$dist_version" != "jessie" ] && [ "$dist_version" != "wheezy" ]; then echo "" cecho r " Sorry this script cannot manage your version of Debian/Ubuntu." echo "" @@ -372,9 +377,9 @@ EOF cecho y "Installing Ishtar dependencies" echo ""; ( set -x; $sh_c 'sleep 3; apt-get install -t jessie-backports -y -q python python-django\ - python-django-registration' ) + python-django-registration python-cffi' ) ( set -x; $sh_c 'sleep 3; apt-get install -y -q \ - python-pisa python-bs4 python-django-formtools\ + python-bs4 python-django-formtools libpangocairo-1.0-0 \ python-tidylib python-lxml python-imaging python-html5lib \ python-psycopg2 python-gdal gettext python-unicodecsv memcached \ python-django-extra-views python-memcache python-dbf python-markdown' ) @@ -389,6 +394,53 @@ EOF cecho y "Installing python-ajax-select (available version in Debian is not compatible with backported Django)" echo ""; ( set -x; $sh_c 'pip install django-ajax-selects==1.4.3' ) + cecho y "Installing weasyprint" + echo ""; + ( set -x; $sh_c 'pip install WeasyPrint==0.41' ) + + fi + + if [ "$dist_version" == "stretch" ]; then + if [ "$backports_activated" != 'true' ]; then + echo "" + cecho r " In order to install Ishtar you have to activate Debian backports." + echo " To do that:" + echo "" + echo " echo 'deb http://ftp.debian.org/debian stretch-backports main contrib' >> /etc/apt/sources.list" + echo "" + cecho p " Run again Ishtar installation script after that." + exit 1 + fi + + if [ "$default_db" == '127.0.0.1' ]; then + echo "-------------------------------------------------------------------------------"; + cecho y "Installing postgresql" + echo "" + POSTGIS=postgresql-9.6-postgis-2.3 + ( set -x; $sh_c 'sleep 3; apt-get install -y -q postgresql '$POSTGIS ) + fi + echo "-------------------------------------------------------------------------------"; + cecho y "Installing Ishtar dependencies" + echo ""; + ( set -x; $sh_c 'sleep 3; apt-get install -t stretch-backports -y -q python-django' ) + ( set -x; $sh_c 'sleep 3; apt-get install -y -q \ + python-django-registration libpangocairo-1.0-0 \ + python-bs4 python-django-formtools python-cffi \ + python-tidylib python-lxml python-imaging python-html5lib \ + python-psycopg2 python-gdal gettext python-unicodecsv memcached \ + python-django-extra-views python-memcache python-dbf python-markdown \ + python-reportlab django-ajax-selects python-django-extensions' ) + echo "-------------------------------------------------------------------------------"; + cecho y "Installing django-simple-history" + echo ""; + ( set -x; $sh_c 'pip install git+https://github.com/treyhunner/django-simple-history.git@1.8.2#egg=django-simple-history' ) + echo "-------------------------------------------------------------------------------"; + cecho y "Installing python-secretary" + echo ""; + ( set -x; $sh_c 'pip install secretary==0.2.14' ) + cecho y "Installing weasyprint" + echo ""; + ( set -x; $sh_c 'pip install WeasyPrint==0.41' ) fi ;; diff --git a/ishtar_common/fixtures/initial_data-fr.json b/ishtar_common/fixtures/initial_data-fr.json index d9026cf49..4045094d9 100644 --- a/ishtar_common/fixtures/initial_data-fr.json +++ b/ishtar_common/fixtures/initial_data-fr.json @@ -839,6 +839,9 @@ ], [ "Documents op\u00e9ration : lecture" + ], + [ + "Contenants : lecture" ] ] } diff --git a/ishtar_common/fixtures/initial_importtypes-fr.json b/ishtar_common/fixtures/initial_importtypes-fr.json index 4386b6de7..438a023e0 100644 --- a/ishtar_common/fixtures/initial_importtypes-fr.json +++ b/ishtar_common/fixtures/initial_importtypes-fr.json @@ -119,6 +119,13 @@ } }, { + "model": "ishtar_common.importermodel", + "fields": { + "name": "Relation entre Op\u00e9ration", + "klass": "archaeological_operations.models.RecordRelations" + } +}, +{ "model": "ishtar_common.importertype", "fields": { "name": "MCC - Op\u00e9rations", @@ -129,6 +136,7 @@ ], "is_template": true, "unicity_keys": "code_patriarche", + "available": true, "users": [], "created_models": [] } @@ -144,6 +152,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [] } @@ -159,6 +168,7 @@ ], "is_template": true, "unicity_keys": "", + "available": true, "users": [], "created_models": [] } @@ -174,6 +184,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [] } @@ -189,6 +200,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [] } @@ -204,6 +216,7 @@ ], "is_template": true, "unicity_keys": "code_patriarche", + "available": true, "users": [], "created_models": [ [ @@ -229,6 +242,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [ [ @@ -251,6 +265,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [] } @@ -266,6 +281,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [] } @@ -281,6 +297,7 @@ ], "is_template": true, "unicity_keys": "", + "available": true, "users": [], "created_models": [ [ @@ -300,6 +317,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [ [ @@ -325,6 +343,7 @@ ], "is_template": true, "unicity_keys": "external_id", + "available": true, "users": [], "created_models": [ [ @@ -343,6 +362,26 @@ } }, { + "model": "ishtar_common.importertype", + "fields": { + "name": "Ishtar - Relations entre op\u00e9rations", + "slug": "ishtar-operations-relations", + "description": null, + "associated_models": [ + "archaeological_operations.models.RecordRelations" + ], + "is_template": true, + "unicity_keys": null, + "available": true, + "users": [], + "created_models": [ + [ + "archaeological_operations.models.RecordRelations" + ] + ] + } +}, +{ "model": "ishtar_common.regexp", "fields": { "name": "Num\u00e9ro INSEE", @@ -2595,11 +2634,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 25, + "col_number": 26, "description": "Marquage visible sur le mobilier. Exemple : \"id1234 la Roche aux F\u00e9es\", \"MTX-45\", etc.\r\nCeci reproduit d'ordinaire un marquage r\u00e9alis\u00e9 par un arch\u00e9ologue. Il ne s'agit pas ici de reproduire une \u00e9pigraphie ou tout autre inscription arch\u00e9ologique (graffito, d\u00e9dicaces, defixio, etc.) , mais vous pouvez l'utiliser pour cela si vous n'avez pas \u00e0 utiliser de marquage arch\u00e9ologique.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2609,11 +2648,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 26, + "col_number": 27, "description": "Commentaire g\u00e9n\u00e9ral libre. Exemple : \"habillage en nid d'abeille, poli g\u00e9n\u00e9ralis\u00e9, encoche emmanchement lat\u00e9ral ouvert sur la face sup\u00e9rieure\", \"1 bord + bec tubulaire\", \"fibule de Langton Down\", etc.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2623,11 +2662,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 27, + "col_number": 28, "description": "Commentaire g\u00e9n\u00e9ral sur les datations, si besoin. Exemple : \"plut\u00f4t fin IIe s. ou d\u00e9but IIIe s.\", \"Datation \u00e0 pr\u00e9ciser avant publication\", \" Datation rapide faite par M. Dupont\", etc.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2637,11 +2676,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 28, + "col_number": 29, "description": "Valeur estim\u00e9e (\u20ac), sous la forme d'un nombre d\u00e9cimal. Exemple : \"4500\", \"0.2\", etc.\r\nUtile essentiellement pour les probl\u00e8mes de partage, vente, assurance etc.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2651,11 +2690,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 29, + "col_number": 30, "description": "Nom exact du fichier image, sous la forme XXXXX.jpg.\r\nAttention au respect strict des caract\u00e8res et majuscules lors d'un import de ce type, \".JPG\" ou \"*.jpg\", etc.\r\nExemple : \"P1030831.JPG\", \"IMG_6485.JPG\", \"fibule.jpg\", etc.\r\nLors de l'import il faut ajouter ces images sous la forme d'un fichier zip (joint au csv import\u00e9) pour que les images soient automatiquement int\u00e9gr\u00e9es.\r\n", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2665,7 +2704,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 30, + "col_number": 31, "description": "Chronologies associ\u00e9es (plusieurs possibles s\u00e9par\u00e9es par &). Exemple : \"Gallo-romain & M\u00e9di\u00e9val\", \"GR&MED\", \"M\u00e9solithique final & M\u00e9so moyen & Epipal\", etc.", "regexp_pre_filter": null, "required": false, @@ -2679,11 +2718,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 31, + "col_number": 32, "description": "Coordonn\u00e9e X pour cet objet.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2693,11 +2732,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 32, + "col_number": 33, "description": "Coordonn\u00e9e Y pour cet objet.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2707,11 +2746,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 33, + "col_number": 34, "description": "Coordonn\u00e9e Z pour cet objet (altitude NGF ou arbitraire).", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2721,11 +2760,11 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 34, + "col_number": 35, "description": "Code permettant de qualifier le mode de projection des donn\u00e9es (SRS /EPSG). Exemple : \"2154\" pour le Lambert 93.", "regexp_pre_filter": null, "required": false, - "export_field_name": null + "export_field_name": "" } }, { @@ -2791,7 +2830,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 36, + "col_number": 37, "description": "Identifiant textuel du d\u00e9p\u00f4t. Cet identifiant doit correspondre \u00e0 un d\u00e9p\u00f4t existant en base de donn\u00e9es.", "regexp_pre_filter": null, "required": false, @@ -2805,7 +2844,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 37, + "col_number": 38, "description": "", "regexp_pre_filter": null, "required": false, @@ -2819,7 +2858,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 38, + "col_number": 39, "description": "Champ n\u00e9cessaire si vous indiquez une caisse", "regexp_pre_filter": null, "required": false, @@ -3169,7 +3208,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 35, + "col_number": 36, "description": "Date au format JJ/MM/AAAA ou AAAA-MM-JJ. Par exemple : 2017-07-31 ou 31/07/2017.", "regexp_pre_filter": null, "required": false, @@ -3183,7 +3222,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 39, + "col_number": 40, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la premi\u00e8re localisation. Par exemple si la premi\u00e8re localisation du d\u00e9p\u00f4t concern\u00e9 est \u00ab b\u00e2timent \u00bb mettre : \u00ab A \u00bb pour b\u00e2timent A.", "regexp_pre_filter": null, "required": false, @@ -3197,7 +3236,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 40, + "col_number": 41, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la seconde localisation.", "regexp_pre_filter": null, "required": false, @@ -3211,7 +3250,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 41, + "col_number": 42, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la troisi\u00e8me localisation.", "regexp_pre_filter": null, "required": false, @@ -3225,7 +3264,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 42, + "col_number": 43, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la quatri\u00e8me localisation.", "regexp_pre_filter": null, "required": false, @@ -3239,7 +3278,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 43, + "col_number": 44, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la cinqui\u00e8me localisation.", "regexp_pre_filter": null, "required": false, @@ -3253,7 +3292,7 @@ "importer_type": [ "ishtar-finds" ], - "col_number": 44, + "col_number": 45, "description": "Localisation dans le d\u00e9p\u00f4t : r\u00e9f\u00e9rence de la sixi\u00e8me localisation. ", "regexp_pre_filter": null, "required": false, @@ -3261,6 +3300,62 @@ } }, { + "model": "ishtar_common.importercolumn", + "fields": { + "label": "NMI", + "importer_type": [ + "ishtar-finds" + ], + "col_number": 25, + "description": "Nombre minimum d'individu(s) li\u00e9(s) \u00e0 cet enregistrement (entier). Exemple : \"12\".", + "regexp_pre_filter": null, + "required": false, + "export_field_name": "" + } +}, +{ + "model": "ishtar_common.importercolumn", + "fields": { + "label": "Op\u00e9ration (identifiant externe) - membre de gauche", + "importer_type": [ + "ishtar-operations-relations" + ], + "col_number": 1, + "description": "", + "regexp_pre_filter": null, + "required": true, + "export_field_name": null + } +}, +{ + "model": "ishtar_common.importercolumn", + "fields": { + "label": "Type de relation entre op\u00e9ration", + "importer_type": [ + "ishtar-operations-relations" + ], + "col_number": 2, + "description": "", + "regexp_pre_filter": null, + "required": true, + "export_field_name": null + } +}, +{ + "model": "ishtar_common.importercolumn", + "fields": { + "label": "Op\u00e9ration (identifiant externe) - membre de droite", + "importer_type": [ + "ishtar-operations-relations" + ], + "col_number": 3, + "description": "", + "regexp_pre_filter": null, + "required": true, + "export_field_name": null + } +}, +{ "model": "ishtar_common.formatertype", "fields": { "formater_type": "IntegerFormater", @@ -3669,6 +3764,38 @@ } }, { + "model": "ishtar_common.formatertype", + "fields": { + "formater_type": "TypeFormater", + "options": "archaeological_operations.models.RelationType", + "many_split": null + } +}, +{ + "model": "ishtar_common.formatertype", + "fields": { + "formater_type": "TypeFormater", + "options": "archaeological_finds.models.AlterationType", + "many_split": "&" + } +}, +{ + "model": "ishtar_common.formatertype", + "fields": { + "formater_type": "TypeFormater", + "options": "archaeological_finds.models.AlterationCauseType", + "many_split": "&" + } +}, +{ + "model": "ishtar_common.formatertype", + "fields": { + "formater_type": "TypeFormater", + "options": "archaeological_finds.models.TreatmentEmergencyType", + "many_split": null + } +}, +{ "model": "ishtar_common.importerduplicatefield", "fields": { "column": [ @@ -4154,7 +4281,7 @@ "fields": { "column": [ "ishtar-finds", - 36 + 37 ], "field_name": "container__location__external_id", "force_new": false, @@ -4167,7 +4294,7 @@ "fields": { "column": [ "ishtar-finds", - 36 + 37 ], "field_name": "container__external_id", "force_new": false, @@ -4180,7 +4307,7 @@ "fields": { "column": [ "ishtar-finds", - 37 + 38 ], "field_name": "container__external_id", "force_new": false, @@ -7466,7 +7593,7 @@ "fields": { "column": [ "ishtar-finds", - 25 + 26 ], "target": "mark", "regexp_filter": null, @@ -7486,7 +7613,7 @@ "fields": { "column": [ "ishtar-finds", - 26 + 27 ], "target": "comment", "regexp_filter": null, @@ -7506,7 +7633,7 @@ "fields": { "column": [ "ishtar-finds", - 27 + 28 ], "target": "dating_comment", "regexp_filter": null, @@ -7526,7 +7653,7 @@ "fields": { "column": [ "ishtar-finds", - 28 + 29 ], "target": "estimated_value", "regexp_filter": null, @@ -7546,7 +7673,7 @@ "fields": { "column": [ "ishtar-finds", - 29 + 30 ], "target": "image", "regexp_filter": null, @@ -7566,7 +7693,7 @@ "fields": { "column": [ "ishtar-finds", - 30 + 31 ], "target": "datings__period", "regexp_filter": null, @@ -7606,7 +7733,7 @@ "fields": { "column": [ "ishtar-finds", - 31 + 32 ], "target": "base_finds__x", "regexp_filter": null, @@ -7626,7 +7753,7 @@ "fields": { "column": [ "ishtar-finds", - 32 + 33 ], "target": "base_finds__y", "regexp_filter": null, @@ -7646,7 +7773,7 @@ "fields": { "column": [ "ishtar-finds", - 33 + 34 ], "target": "base_finds__z", "regexp_filter": null, @@ -7666,7 +7793,7 @@ "fields": { "column": [ "ishtar-finds", - 34 + 35 ], "target": "base_finds__spatial_reference_system", "regexp_filter": null, @@ -7766,7 +7893,7 @@ "fields": { "column": [ "ishtar-finds", - 36 + 37 ], "target": "container__responsible__external_id", "regexp_filter": null, @@ -7786,7 +7913,7 @@ "fields": { "column": [ "ishtar-finds", - 37 + 38 ], "target": "container__reference", "regexp_filter": null, @@ -7806,7 +7933,7 @@ "fields": { "column": [ "ishtar-finds", - 38 + 39 ], "target": "container__container_type", "regexp_filter": null, @@ -8326,7 +8453,7 @@ "fields": { "column": [ "ishtar-finds", - 35 + 36 ], "target": "base_finds__discovery_date", "regexp_filter": null, @@ -8346,7 +8473,7 @@ "fields": { "column": [ "ishtar-finds", - 39 + 40 ], "target": "set_localisation_1", "regexp_filter": null, @@ -8366,7 +8493,7 @@ "fields": { "column": [ "ishtar-finds", - 40 + 41 ], "target": "set_localisation_2", "regexp_filter": null, @@ -8386,7 +8513,7 @@ "fields": { "column": [ "ishtar-finds", - 41 + 42 ], "target": "set_localisation_3", "regexp_filter": null, @@ -8406,7 +8533,7 @@ "fields": { "column": [ "ishtar-finds", - 42 + 43 ], "target": "set_localisation_4", "regexp_filter": null, @@ -8426,7 +8553,7 @@ "fields": { "column": [ "ishtar-finds", - 43 + 44 ], "target": "set_localisation_5", "regexp_filter": null, @@ -8446,7 +8573,7 @@ "fields": { "column": [ "ishtar-finds", - 44 + 45 ], "target": "set_localisation_6", "regexp_filter": null, @@ -8460,5 +8587,85 @@ "concat_str": "", "comment": "" } +}, +{ + "model": "ishtar_common.importtarget", + "fields": { + "column": [ + "ishtar-finds", + 25 + ], + "target": "min_number_of_individuals", + "regexp_filter": null, + "formater_type": [ + "IntegerFormater", + "", + "" + ], + "force_new": false, + "concat": false, + "concat_str": "", + "comment": "" + } +}, +{ + "model": "ishtar_common.importtarget", + "fields": { + "column": [ + "ishtar-operations-relations", + 1 + ], + "target": "left_record__external_id", + "regexp_filter": null, + "formater_type": [ + "UnicodeFormater", + "", + "" + ], + "force_new": false, + "concat": false, + "concat_str": null, + "comment": "" + } +}, +{ + "model": "ishtar_common.importtarget", + "fields": { + "column": [ + "ishtar-operations-relations", + 2 + ], + "target": "relation_type", + "regexp_filter": null, + "formater_type": [ + "TypeFormater", + "archaeological_operations.models.RelationType", + null + ], + "force_new": false, + "concat": false, + "concat_str": null, + "comment": "" + } +}, +{ + "model": "ishtar_common.importtarget", + "fields": { + "column": [ + "ishtar-operations-relations", + 3 + ], + "target": "right_record__external_id", + "regexp_filter": null, + "formater_type": [ + "UnicodeFormater", + "", + "" + ], + "force_new": false, + "concat": false, + "concat_str": null, + "comment": "" + } } ] diff --git a/ishtar_common/static/gentium/GentiumPlus-I.ttf b/ishtar_common/static/gentium/GentiumPlus-I.ttf Binary files differnew file mode 100644 index 000000000..7bc1b3d8b --- /dev/null +++ b/ishtar_common/static/gentium/GentiumPlus-I.ttf diff --git a/ishtar_common/static/gentium/GentiumPlus-R.ttf b/ishtar_common/static/gentium/GentiumPlus-R.ttf Binary files differnew file mode 100644 index 000000000..c1194dd35 --- /dev/null +++ b/ishtar_common/static/gentium/GentiumPlus-R.ttf diff --git a/ishtar_common/static/gentium/OFL.txt b/ishtar_common/static/gentium/OFL.txt new file mode 100644 index 000000000..4f7540787 --- /dev/null +++ b/ishtar_common/static/gentium/OFL.txt @@ -0,0 +1,94 @@ +Copyright (c) 2003-2014 SIL International (http://www.sil.org/),
+with Reserved Font Names "Gentium" and "SIL".
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/ishtar_common/static/gentium/README.txt b/ishtar_common/static/gentium/README.txt new file mode 100644 index 000000000..bc17a8cb7 --- /dev/null +++ b/ishtar_common/static/gentium/README.txt @@ -0,0 +1,88 @@ +README
+Gentium Plus
+========================
+
+Thank you for your interest in the Gentium Plus fonts.
+We hope you find them useful!
+
+Gentium Plus supports a wide range of Latin, Greek and Cyrillic
+characters. Documentation for the fonts is available on Gentium website
+(http://scripts.sil.org/Gentium), including details on what ranges are
+supported.
+
+Gentium Plus is released under the SIL Open Font License.
+
+See the OFL and OFL-FAQ for details of the SIL Open Font License.
+See the FONTLOG for information on this and previous releases.
+See the GENTIUM-FAQ for answers to common questions about the Gentium fonts
+See the website (http://scripts.sil.org/Gentium) for further documentation.
+See the SIL Unicode Roman FAQ (http://scripts.sil.org/ComplexRomanFontFAQ)
+for frequently asked questions and their answers regarding SIL's Roman fonts.
+
+
+TIPS
+====
+
+As this font is distributed at no cost, we are unable to provide a
+commercial level of personal technical support. The font has, however,
+been through some testing on various platforms to be sure it works in most
+situations. In particular, it has been tested and shown to work on Windows
+XP, Windows Vista and Windows 7. Graphite capabilities have been tested
+on Graphite-supported platforms.
+
+If you do find a problem, please do report it to fonts@sil.org.
+We can't guarantee any direct response, but will try to fix reported bugs in
+future versions. Make sure you read through the
+SIL Unicode Roman FAQ (http://scripts.sil.org/ComplexRomanFontFAQ).
+
+Many problems can be solved, or at least explained, through an understanding
+of the encoding and use of the fonts. Here are some basic hints:
+
+Encoding:
+The fonts are encoded according to Unicode, so your application must support
+Unicode text in order to access letters other than the standard alphabet.
+Most Windows applications provide basic Unicode support. You will, however,
+need some way of entering Unicode text into your document.
+
+Keyboarding:
+This font does not include any keyboarding helps or utilities. It uses the
+built-in keyboards of the operating system. You will need to install the
+appropriate keyboard and input method for the characters of the language you
+wish to use. If you want to enter characters that are not supported by any
+system keyboard, the Keyman program (www.tavultesoft.com) can be helpful
+on Windows systems. Also available for Windows is MSKLC
+(http://www.microsoft.com/globaldev/tools/msklc.mspx).
+For Linux systems such as Ubuntu, KMFL (http://kmfl.sourceforge.net/)
+is available. Ukelele (http://scripts.sil.org/ukelele) is available for
+Mac OS X versions 10.2 and later.
+
+For other platforms, KMFL (http://kmfl.sourceforge.net/),
+XKB (http://www.x.org/wiki/XKB) or Ukelele (http://scripts.sil.org/ukelele)
+can be helpful.
+
+If you want to enter characters that are not supported by any system
+keyboard, and to access the full Unicode range, we suggest you use
+gucharmap, kcharselect on Ubuntu or similar software.
+
+Another method of entering some symbols is provided by a few applications such
+as Adobe InDesign or OpenOffice.org. They can display a glyph palette or input
+dialog that shows all the glyphs (symbols) in a font and allow you to enter
+them by clicking on the glyph you want.
+
+Rendering:
+This font is designed to work with Graphite or Opentype advanced font
+technologies. To take advantage of the advanced typographic
+capabilities of this font, you must be using applications that provide an
+adequate level of support for Graphite or OpenType. See "Applications
+that provide an adequate level of support for SIL Unicode Roman fonts"
+(http://scripts.sil.org/Complex_AdLvSup).
+
+
+CONTACT
+========
+For more information please visit the Gentium page on SIL International's
+Computers and Writing systems website:
+http://scripts.sil.org/Gentium
+
+Support through the website: http://scripts.sil.org/Support
+
diff --git a/ishtar_common/static/media/style_basic.css b/ishtar_common/static/media/style_basic.css index 1d92928dc..d0f5bbe4a 100644 --- a/ishtar_common/static/media/style_basic.css +++ b/ishtar_common/static/media/style_basic.css @@ -1,7 +1,8 @@ @page { size: a4 portrait; - margin: 2.5cm 1cm 2.5cm 1cm; + margin: 2cm 1cm 2.5cm 1cm; background-image: url("images/ishtar-bg.jpg"); + background-repeat: no-repeat; @frame footer { -pdf-frame-content: pdffooter; bottom: 1cm; @@ -16,6 +17,9 @@ margin-right: 1cm; height: 1.5cm; } + @bottom-center { + content: counter(page) "/" counter(pages); + } } label{ @@ -36,6 +40,13 @@ caption, h3{ font-size:1.5em; } +a img { + display: block; + margin-left: auto; + margin-right: auto; + padding:0.5em; +} + th{ text-align:center; border-bottom:2px solid #922; @@ -72,10 +83,21 @@ td{ display:none; } +caption, hr, .tool-left, .tool-right, .display_details, .display_details_inline{ + display: None; + color: transparent; + background-color: transparent; + border-color: transparent; +} + p{ margin:0.2em; } +td{ + background-color: #ddd; +} + #pdffooter, #pdfheader{ text-align:center; } @@ -84,8 +106,15 @@ p{ font-weight:bold; width:100%; border-bottom:1px solid #922; + position: fixed; + top: -0.5cm; } -.display_details, .display_details_inline{ - display: none; +.window-refs{ + text-align:center; + padding:0; + margin:0; + font-size: 0.9em; + width:100%; + display:block; } diff --git a/ishtar_common/templates/ishtar/sheet_organization_pdf.html b/ishtar_common/templates/ishtar/sheet_organization_pdf.html index 887c7ccb2..2276aa4d1 100644 --- a/ishtar_common/templates/ishtar/sheet_organization_pdf.html +++ b/ishtar_common/templates/ishtar/sheet_organization_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_organization.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/ishtar_common/templates/ishtar/sheet_person_pdf.html b/ishtar_common/templates/ishtar/sheet_person_pdf.html index 199892d2f..9dd9e4c50 100644 --- a/ishtar_common/templates/ishtar/sheet_person_pdf.html +++ b/ishtar_common/templates/ishtar/sheet_person_pdf.html @@ -1,6 +1,5 @@ {% extends "ishtar/sheet_person.html" %} {% block header %} -<link rel="stylesheet" href="{{STATIC_URL}}/media/style_basic.css?ver={{VERSION}}" /> {% endblock %} {% block main_head %} {{ block.super }} @@ -10,9 +9,6 @@ Ishtar – {{APP_NAME}} – {{item}} {% endblock %} {%block head_sheet%}{%endblock%} {%block main_foot%} -<div id="pdffooter"> -– <pdf:pagenumber/> – -</div> </body> </html> {%endblock%} diff --git a/ishtar_common/views.py b/ishtar_common/views.py index b8350c62a..8d475aff5 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-2016 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2017 É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 @@ -21,13 +21,7 @@ from tidylib import tidy_document as tidy from copy import copy, deepcopy import csv -import cStringIO as StringIO import datetime - -import reportlab -reportlab.Version = "2.2" # stupid hack for an old library... -import ho.pisa as pisa - import json import logging from markdown import markdown @@ -35,6 +29,8 @@ import optparse import re from tempfile import NamedTemporaryFile import unicodedata +from weasyprint import HTML, CSS +from weasyprint.fonts import FontConfiguration from extra_views import ModelFormSetView @@ -42,6 +38,7 @@ from django.conf import settings from django.contrib.auth import logout from django.contrib.auth.decorators import login_required from django.contrib.postgres.search import SearchQuery +from django.contrib.staticfiles.templatetags.staticfiles import static from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import reverse, NoReverseMatch from django.db.models import Q, ImageField @@ -1333,19 +1330,25 @@ def show_item(model, name, extra_dct=None): elif doc_type == 'pdf': tpl = loader.get_template('ishtar/sheet_%s_pdf.html' % name) context_instance['output'] = 'PDF' - content = tpl.render(context_instance, request) - result = StringIO.StringIO() - html = content.encode('utf-8') - html = html.replace("<table", "<pdf:nextpage/><table repeat='1'") - pdf = pisa.pisaDocument(StringIO.StringIO(html), result, - encoding='utf-8') - response = HttpResponse(result.getvalue(), - content_type='application/pdf') + html = tpl.render(context_instance, request) + font_config = FontConfiguration() + css = CSS(string=''' + @font-face { + font-family: Gentium; + src: url(%s); + } + body{ + font-family: Gentium + } + ''' % (static("gentium/GentiumPlus-R.ttf"))) + css2 = CSS(filename=settings.STATIC_ROOT + '/media/style_basic.css') + pdf = HTML(string=html, base_url=request.build_absolute_uri() + ).write_pdf(stylesheets=[css, css2], + font_config=font_config) + response = HttpResponse(pdf, content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename=%s.pdf' % \ filename - if not pdf.err: - return response - return HttpResponse(content, content_type="application/xhtml") + return response else: tpl = loader.get_template('ishtar/sheet_%s_window.html' % name) content = tpl.render(context_instance, request) diff --git a/requirements.txt b/requirements.txt index 7ef1b5ce2..1e62d3e29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,20 @@ +six>=1.9 psycopg2==2.5.4 django-registration==2.2 django==1.11 Pillow==3.4.2 -pisa==3.0.33 -reportlab==3.1.8 +WeasyPrint==0.41 +html5lib==0.999999999 + dbf==0.96.003 python-memcached==1.57 unicodecsv==0.14.1 pytidylib==0.2.1 lxml==3.4.0 -html5lib==0.999 django-extra-views==0.2.4 -beautifulsoup4==4.3.2 +beautifulsoup4==4.5.3 markdown==2.5.1 django-ajax-selects==1.6.0 django-compressor==2.1 diff --git a/version.py b/version.py index 42b630409..38f3d146e 100644 --- a/version.py +++ b/version.py @@ -1,5 +1,5 @@ -# 1.99.10 -VERSION = (1, 99, 10) +# 1.99.11 +VERSION = (1, 99, 11) def get_version(): |