diff options
| -rw-r--r-- | archaeological_context_records/ishtar_menu.py | 1 | ||||
| -rw-r--r-- | archaeological_files/ishtar_menu.py | 2 | ||||
| -rw-r--r-- | archaeological_finds/ishtar_menu.py | 1 | ||||
| -rw-r--r-- | archaeological_finds/models.py | 28 | ||||
| -rw-r--r-- | archaeological_operations/admin.py | 20 | ||||
| -rw-r--r-- | archaeological_operations/forms.py | 47 | ||||
| -rw-r--r-- | archaeological_operations/ishtar_menu.py | 6 | ||||
| -rw-r--r-- | archaeological_operations/models.py | 437 | ||||
| -rw-r--r-- | archaeological_operations/views.py | 3 | ||||
| -rw-r--r-- | archaeological_operations/wizards.py | 8 | ||||
| -rw-r--r-- | archaeological_warehouse/ishtar_menu.py | 1 | ||||
| -rw-r--r-- | example_project/urls.py | 8 | ||||
| -rw-r--r-- | ishtar_common/context_processors.py | 14 | ||||
| -rw-r--r-- | ishtar_common/management/commands/update_specific_importers.py | 7 | ||||
| -rw-r--r-- | ishtar_common/menu_base.py | 31 | ||||
| -rw-r--r-- | ishtar_common/models.py | 57 | ||||
| -rw-r--r-- | ishtar_common/tests.py | 6 | ||||
| -rw-r--r-- | ishtar_common/views.py | 36 | 
18 files changed, 366 insertions, 347 deletions
diff --git a/archaeological_context_records/ishtar_menu.py b/archaeological_context_records/ishtar_menu.py index 826f99b0f..8e8f32218 100644 --- a/archaeological_context_records/ishtar_menu.py +++ b/archaeological_context_records/ishtar_menu.py @@ -27,6 +27,7 @@ import models  MENU_SECTIONS = [      (40, SectionItem('record_management', _(u"Context record"), +     profile_restriction='context_record',       childs=[MenuItem('record_search', _(u"Search"),               model=models.ContextRecord,               access_controls=['view_contextrecord', diff --git a/archaeological_files/ishtar_menu.py b/archaeological_files/ishtar_menu.py index b120d18d1..326fec23b 100644 --- a/archaeological_files/ishtar_menu.py +++ b/archaeological_files/ishtar_menu.py @@ -31,6 +31,7 @@ MENU_SECTIONS = [      (20,       SectionItem(           'file_management', _(u"Archaeological file"), +         profile_restriction='files',           childs=[               MenuItem(                   'file_search', _(u"Search"), @@ -79,6 +80,7 @@ MENU_SECTIONS = [      (100,       SectionItem(           'dashboard', _(u"Dashboard"), +         profile_restriction='files',           childs=[MenuItem('dashboard_main', _(u"General informations"),                            model=models.File,                            access_controls=['change_file', 'change_own_file']), diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index a688adbb4..ea8cd2c1f 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -29,6 +29,7 @@ MENU_SECTIONS = [      (50,       SectionItem(           'find_management', _(u"Find"), +         profile_restriction='find',           childs=[               MenuItem(                   'find_search', _(u"Search"), diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py index f677b1297..8685e8ddd 100644 --- a/archaeological_finds/models.py +++ b/archaeological_finds/models.py @@ -32,11 +32,7 @@ from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \  from archaeological_operations.models import AdministrativeAct  from archaeological_context_records.models import ContextRecord, Dating -WAREHOUSE_AVAILABLE = 'archaeological_warehouse' in settings.INSTALLED_APPS -if WAREHOUSE_AVAILABLE: -    from archaeological_warehouse.models import Warehouse, Container - -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS +from archaeological_warehouse.models import Warehouse, Container  class MaterialType(GeneralType): @@ -309,10 +305,9 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):          verbose_name=_("Downstream treatment"))      datings = models.ManyToManyField(Dating, verbose_name=_(u"Dating"),                                       related_name='find') -    if WAREHOUSE_AVAILABLE: -        container = models.ForeignKey( -            Container, verbose_name=_(u"Container"), blank=True, null=True, -            related_name='finds') +    container = models.ForeignKey( +        Container, verbose_name=_(u"Container"), blank=True, null=True, +        related_name='finds')      is_complete = models.NullBooleanField(_(u"Is complete?"), blank=True,                                            null=True)      object_types = models.ManyToManyField( @@ -559,16 +554,14 @@ class TreatmentType(GeneralType):  class Treatment(BaseHistorizedItem, OwnPerms):      external_id = models.CharField(_(u"External ID"), blank=True, null=True,                                     max_length=120) -    if WAREHOUSE_AVAILABLE: -        container = models.ForeignKey(Container, verbose_name=_(u"Container"), -                                      blank=True, null=True) +    container = models.ForeignKey(Container, verbose_name=_(u"Container"), +                                  blank=True, null=True)      description = models.TextField(_(u"Description"), blank=True, null=True)      comment = models.TextField(_(u"Comment"), blank=True, null=True)      treatment_type = models.ForeignKey(TreatmentType,                                         verbose_name=_(u"Treatment type")) -    if WAREHOUSE_AVAILABLE: -        location = models.ForeignKey(Warehouse, verbose_name=_(u"Location"), -                                     blank=True, null=True) +    location = models.ForeignKey(Warehouse, verbose_name=_(u"Location"), +                                 blank=True, null=True)      other_location = models.CharField(_(u"Other location"), max_length=200,                                        blank=True, null=True)      person = models.ForeignKey( @@ -610,9 +603,8 @@ class TreatmentSource(Source):  class Property(LightHistorizedItem):      find = models.ForeignKey(Find, verbose_name=_(u"Find")) -    if FILES_AVAILABLE: -        administrative_act = models.ForeignKey( -            AdministrativeAct, verbose_name=_(u"Administrative act")) +    administrative_act = models.ForeignKey( +        AdministrativeAct, verbose_name=_(u"Administrative act"))      person = models.ForeignKey(Person, verbose_name=_(u"Person"),                                 related_name='properties')      start_date = models.DateField(_(u"Start date")) diff --git a/archaeological_operations/admin.py b/archaeological_operations/admin.py index 2a0ec652c..34e6da2ca 100644 --- a/archaeological_operations/admin.py +++ b/archaeological_operations/admin.py @@ -24,17 +24,15 @@ from ishtar_common.admin import HistorizedObjectAdmin, GeneralTypeAdmin  import models -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS -if FILES_AVAILABLE: -    class AdministrativeActAdmin(HistorizedObjectAdmin): -        list_display = ('year', 'index', 'operation', 'associated_file', -                        'act_type') -        list_filter = ('act_type',) -        search_fields = ('year', 'index') -        model = models.AdministrativeAct +class AdministrativeActAdmin(HistorizedObjectAdmin): +    list_display = ('year', 'index', 'operation', 'associated_file', +                    'act_type') +    list_filter = ('act_type',) +    search_fields = ('year', 'index') +    model = models.AdministrativeAct -    admin.site.register(models.AdministrativeAct, AdministrativeActAdmin) +admin.site.register(models.AdministrativeAct, AdministrativeActAdmin)  class PeriodAdmin(admin.ModelAdmin): @@ -78,9 +76,7 @@ admin.site.register(models.OperationSource, OperationSourceAdmin)  class ParcelAdmin(HistorizedObjectAdmin): -    list_display = ['section', 'parcel_number', 'operation'] -    if FILES_AVAILABLE: -        list_display.append('associated_file') +    list_display = ['section', 'parcel_number', 'operation', 'associated_file']      search_fields = ('operation__name',)      model = models.Parcel diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py index d18e7cea7..37ccbf277 100644 --- a/archaeological_operations/forms.py +++ b/archaeological_operations/forms.py @@ -34,14 +34,11 @@ from django.utils.translation import ugettext_lazy as _, pgettext_lazy  from django.utils.safestring import mark_safe  from ishtar_common.models import valid_id, PersonType, Person, Town, \ -    DocumentTemplate, Organization, OrganizationType +    DocumentTemplate, Organization, OrganizationType, get_current_profile  from ishtar_common.wizards import MultiValueDict -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS - -if FILES_AVAILABLE: -    from archaeological_files.models import File +from archaeological_files.models import File  import models  from widgets import ParcelWidget, SelectParcelWidget @@ -566,16 +563,16 @@ class OperationCodeInput(forms.TextInput):              'url': reverse_lazy('get_available_operation_code')}          return mark_safe(rendered + js) -if FILES_AVAILABLE: -    class OperationFormFileChoice(forms.Form): -        form_label = _(u"Associated file") -        associated_models = {'associated_file': File, } -        currents = {'associated_file': File} -        associated_file = forms.IntegerField( -            label=_(u"Archaelogical file"), -            widget=widgets.JQueryAutoComplete( -                reverse_lazy('autocomplete-file'), associated_model=File), -            validators=[valid_id(File)], required=False) + +class OperationFormFileChoice(forms.Form): +    form_label = _(u"Associated file") +    associated_models = {'associated_file': File, } +    currents = {'associated_file': File} +    associated_file = forms.IntegerField( +        label=_(u"Archaelogical file"), +        widget=widgets.JQueryAutoComplete( +            reverse_lazy('autocomplete-file'), associated_model=File), +        validators=[valid_id(File)], required=False)  class OperationFormAbstract(forms.Form): @@ -814,14 +811,13 @@ class OperationFormGeneral(forms.Form):  class OperationFormModifGeneral(OperationFormGeneral):      operation_code = forms.IntegerField(label=_(u"Operation code"),                                          required=False) -    if FILES_AVAILABLE: -        currents = {'associated_file': File} -        associated_file = forms.IntegerField( -            label=_(u"Archaelogical file"), -            widget=widgets.JQueryAutoComplete( -                reverse_lazy('autocomplete-file'), -                associated_model=File), -            validators=[valid_id(File)], required=False) +    currents = {'associated_file': File} +    associated_file = forms.IntegerField( +        label=_(u"Archaelogical file"), +        widget=widgets.JQueryAutoComplete( +            reverse_lazy('autocomplete-file'), +            associated_model=File), +        validators=[valid_id(File)], required=False)      def __init__(self, *args, **kwargs):          super(OperationFormModifGeneral, self).__init__(*args, **kwargs) @@ -829,12 +825,13 @@ class OperationFormModifGeneral(OperationFormGeneral):          self.fields.keyOrder.pop(self.fields.keyOrder.index('associated_file'))          self.fields.keyOrder.insert(self.fields.keyOrder.index('in_charge'),                                      'associated_file') +        if not get_current_profile().files: +            self.fields.pop('associated_file')  OperationFormModifGeneral.associated_models = \      OperationFormGeneral.associated_models.copy() -if FILES_AVAILABLE: -    OperationFormModifGeneral.associated_models['associated_file'] = File +OperationFormModifGeneral.associated_models['associated_file'] = File  class OperationFormPreventive(forms.Form): diff --git a/archaeological_operations/ishtar_menu.py b/archaeological_operations/ishtar_menu.py index 60f764ab7..5a22efd05 100644 --- a/archaeological_operations/ishtar_menu.py +++ b/archaeological_operations/ishtar_menu.py @@ -17,17 +17,15 @@  # See the file COPYING for details. -from django.conf import settings  from django.utils.translation import ugettext_lazy as _, pgettext_lazy  from ishtar_common.menu_base import SectionItem, MenuItem +from ishtar_common.models import get_current_profile  import models  # be carreful: each access_controls must be relevant with check_rights in urls -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS -  MENU_SECTIONS = [      (30, SectionItem(          'operation_management', _(u"Operation"), @@ -98,7 +96,7 @@ MENU_SECTIONS = [      ),  ] -if FILES_AVAILABLE: +if get_current_profile().files:      MENU_SECTIONS.insert(          1,          ( diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 448adcd68..5bbe357c0 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -35,8 +35,6 @@ from ishtar_common.models import GeneralType, BaseHistorizedItem, \      Person, Organization, Town, Dashboard, IshtarUser, ValueGetter, \      DocumentTemplate, ShortMenuItem, DashboardFormItem, GeneralRelationType,\      GeneralRecordRelations, post_delete_record_relation, OperationType -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS -FINDS_AVAILABLE = 'archaeological_finds' in settings.INSTALLED_APPS  class RemainType(GeneralType): @@ -137,8 +135,7 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem,      SHOW_URL = 'show-operation'      TABLE_COLS = ['year_index', 'operation_type', 'remains', 'towns',                    'start_date', 'excavation_end_date'] -    if FILES_AVAILABLE: -        TABLE_COLS.insert(4, 'associated_file_short_label') +    TABLE_COLS.insert(4, 'associated_file_short_label')      creation_date = models.DateField(_(u"Creation date"),                                       default=datetime.date.today)      end_date = models.DateField(_(u"Closing date"), null=True, blank=True) @@ -161,11 +158,10 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem,      year = models.IntegerField(_(u"Year"), null=True, blank=True)      operation_code = models.IntegerField(_(u"Operation code"), null=True,                                           blank=True) -    if FILES_AVAILABLE: -        associated_file = models.ForeignKey( -            'archaeological_files.File', -            related_name='operations', verbose_name=_(u"File"), -            blank=True, null=True) +    associated_file = models.ForeignKey( +        'archaeological_files.File', +        related_name='operations', verbose_name=_(u"File"), +        blank=True, null=True)      operation_type = models.ForeignKey(OperationType, related_name='+',                                         verbose_name=_(u"Operation type"))      surface = models.IntegerField(_(u"Surface (m2)"), blank=True, null=True) @@ -286,15 +282,12 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem,          return reverse('show-operation', args=[self.pk, ''])      def has_finds(self): -        if not FINDS_AVAILABLE: -            return          from archaeological_finds.models import BaseFind          return BaseFind.objects.filter(context_record__operation=self).count()      def finds(self): -        if FINDS_AVAILABLE: -            from archaeological_finds.models import BaseFind -            return BaseFind.objects.filter(context_record__operation=self) +        from archaeological_finds.models import BaseFind +        return BaseFind.objects.filter(context_record__operation=self)      def get_reference(self, full=False):          ref = "" @@ -360,7 +353,7 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem,      @property      def associated_file_short_label(self): -        if not FILES_AVAILABLE or not self.associated_file: +        if not self.associated_file:              return ""          return self.associated_file.short_label @@ -453,10 +446,9 @@ def operation_post_save(sender, **kwargs):          operation.fnap_financing = fnap_percent          operation.save()      cached_label_changed(sender, **kwargs) -    if FILES_AVAILABLE and operation.associated_file: +    if operation.associated_file:          operation.associated_file.update_short_menu_class() -    # manage parcel association -    if FILES_AVAILABLE and operation.associated_file: +        # manage parcel association          for parcel in operation.parcels.all():              parcel.copy_to_file()  post_save.connect(operation_post_save, sender=Operation) @@ -548,216 +540,214 @@ class ActType(GeneralType):          verbose_name_plural = _(u"Act types")          ordering = ('label',) -AdministrativeAct = None -if FILES_AVAILABLE: -    class AdministrativeAct(BaseHistorizedItem, OwnPerms, ValueGetter): -        TABLE_COLS = ['full_ref', 'year', 'index', 'act_type', 'act_object', -                      'signature_date', 'associated_file', 'operation', -                      'towns_label'] -        TABLE_COLS_FILE = [ -            'full_ref', 'year', 'index', 'act_type', -            'act_object', 'associated_file', 'towns_label', -        ] -        TABLE_COLS_OPE = ['full_ref', 'year', 'index', 'act_type', 'operation', -                          'act_object', 'towns_label'] -        if settings.COUNTRY == 'fr': -            TABLE_COLS.append('departments_label') -            TABLE_COLS_FILE.append('departments_label') -            TABLE_COLS_OPE.append('departments_label') -        act_type = models.ForeignKey(ActType, verbose_name=_(u"Act type")) -        in_charge = models.ForeignKey( -            Person, blank=True, null=True, -            related_name='adminact_operation_in_charge', -            verbose_name=_(u"Person in charge of the operation"), -            on_delete=models.SET_NULL,) -        index = models.IntegerField(verbose_name=_(u"Index"), blank=True, -                                    null=True) -        operator = models.ForeignKey( -            Organization, blank=True, null=True, -            verbose_name=_(u"Archaeological preventive operator"), -            related_name='adminact_operator', on_delete=models.SET_NULL) -        scientist = models.ForeignKey( -            Person, blank=True, null=True, -            related_name='adminact_scientist', on_delete=models.SET_NULL, -            verbose_name=_(u"Scientist in charge")) -        signatory = models.ForeignKey( -            Person, blank=True, null=True, related_name='signatory', -            verbose_name=_(u"Signatory"), on_delete=models.SET_NULL,) -        operation = models.ForeignKey( -            Operation, blank=True, null=True, -            related_name='administrative_act', verbose_name=_(u"Operation")) -        if FILES_AVAILABLE: -            associated_file = models.ForeignKey( -                'archaeological_files.File', -                blank=True, null=True, -                related_name='administrative_act', -                verbose_name=_(u"Archaelogical file")) -        signature_date = models.DateField(_(u"Signature date"), blank=True, -                                          null=True) -        year = models.IntegerField(_(u"Year"), blank=True, null=True) -        act_object = models.TextField(_(u"Object"), max_length=300, blank=True, + +class AdministrativeAct(BaseHistorizedItem, OwnPerms, ValueGetter): +    TABLE_COLS = ['full_ref', 'year', 'index', 'act_type', 'act_object', +                  'signature_date', 'associated_file', 'operation', +                  'towns_label'] +    TABLE_COLS_FILE = [ +        'full_ref', 'year', 'index', 'act_type', +        'act_object', 'associated_file', 'towns_label', +    ] +    TABLE_COLS_OPE = ['full_ref', 'year', 'index', 'act_type', 'operation', +                      'act_object', 'towns_label'] +    if settings.COUNTRY == 'fr': +        TABLE_COLS.append('departments_label') +        TABLE_COLS_FILE.append('departments_label') +        TABLE_COLS_OPE.append('departments_label') +    act_type = models.ForeignKey(ActType, verbose_name=_(u"Act type")) +    in_charge = models.ForeignKey( +        Person, blank=True, null=True, +        related_name='adminact_operation_in_charge', +        verbose_name=_(u"Person in charge of the operation"), +        on_delete=models.SET_NULL,) +    index = models.IntegerField(verbose_name=_(u"Index"), blank=True, +                                null=True) +    operator = models.ForeignKey( +        Organization, blank=True, null=True, +        verbose_name=_(u"Archaeological preventive operator"), +        related_name='adminact_operator', on_delete=models.SET_NULL) +    scientist = models.ForeignKey( +        Person, blank=True, null=True, +        related_name='adminact_scientist', on_delete=models.SET_NULL, +        verbose_name=_(u"Scientist in charge")) +    signatory = models.ForeignKey( +        Person, blank=True, null=True, related_name='signatory', +        verbose_name=_(u"Signatory"), on_delete=models.SET_NULL,) +    operation = models.ForeignKey( +        Operation, blank=True, null=True, +        related_name='administrative_act', verbose_name=_(u"Operation")) +    associated_file = models.ForeignKey( +        'archaeological_files.File', +        blank=True, null=True, +        related_name='administrative_act', +        verbose_name=_(u"Archaelogical file")) +    signature_date = models.DateField(_(u"Signature date"), blank=True,                                        null=True) -        if settings.COUNTRY == 'fr': -            ref_sra = models.CharField(u"Référence SRA", max_length=15, -                                       blank=True, null=True) -            departments_label = models.TextField( -                _(u"Departments"), blank=True, null=True, -                help_text=_(u"Cached values get from associated departments")) -        towns_label = models.TextField( -            _(u"Towns"), blank=True, null=True, -            help_text=_(u"Cached values get from associated towns")) -        history = HistoricalRecords() -        _prefix = 'adminact_' - -        class Meta: -            ordering = ('year', 'signature_date', 'index', 'act_type') -            verbose_name = _(u"Administrative act") -            verbose_name_plural = _(u"Administrative acts") -            permissions = ( -                ("view_administrativeact", -                 ugettext(u"Can view all Administrative act")), -                ("view_own_administrativeact", -                 ugettext(u"Can view own Administrative act")), -                ("add_own_administrativeact", -                 ugettext(u"Can add own Administrative act")), -                ("change_own_administrativeact", -                 ugettext(u"Can change own Administrative act")), -                ("delete_own_administrativeact", -                 ugettext(u"Can delete own Administrative act")), -            ) +    year = models.IntegerField(_(u"Year"), blank=True, null=True) +    act_object = models.TextField(_(u"Object"), max_length=300, blank=True, +                                  null=True) +    if settings.COUNTRY == 'fr': +        ref_sra = models.CharField(u"Référence SRA", max_length=15, +                                   blank=True, null=True) +        departments_label = models.TextField( +            _(u"Departments"), blank=True, null=True, +            help_text=_(u"Cached values get from associated departments")) +    towns_label = models.TextField( +        _(u"Towns"), blank=True, null=True, +        help_text=_(u"Cached values get from associated towns")) +    history = HistoricalRecords() +    _prefix = 'adminact_' + +    class Meta: +        ordering = ('year', 'signature_date', 'index', 'act_type') +        verbose_name = _(u"Administrative act") +        verbose_name_plural = _(u"Administrative acts") +        permissions = ( +            ("view_administrativeact", +             ugettext(u"Can view all Administrative act")), +            ("view_own_administrativeact", +             ugettext(u"Can view own Administrative act")), +            ("add_own_administrativeact", +             ugettext(u"Can add own Administrative act")), +            ("change_own_administrativeact", +             ugettext(u"Can change own Administrative act")), +            ("delete_own_administrativeact", +             ugettext(u"Can delete own Administrative act")), +        ) + +    def __unicode__(self): +        return settings.JOINT.join( +            [unicode(item) for item in [ +                self.operation, self.associated_file, self.act_object] +             if item]) -        def __unicode__(self): -            return settings.JOINT.join( -                [unicode(item) for item in [ -                    self.operation, self.associated_file, self.act_object] -                 if item]) - -        full_ref_lbl = _(u"Ref.") - -        @property -        def full_ref(self): -            lbl = [] -            if self.year: -                lbl.append(unicode(self.year)) -            if self.index: -                lbl.append(u"n°%d" % self.index) -            if settings.COUNTRY == 'fr' and self.ref_sra: -                lbl.append(u"[%s]" % self.ref_sra) -            return u" ".join(lbl) - -        @property -        def towns(self): -            if self.associated_file: -                return self.associated_file.towns.all() -            elif self.operation: -                return self.operation.towns.all() -            return [] - -        @property -        def departments(self): -            if settings.COUNTRY != 'fr': -                return '' -            q = None -            if self.associated_file: -                q = self.associated_file.towns.all() -            elif self.operation: -                q = self.operation.towns.all() -            if not q: -                return '' -            dpts = [] -            for town in q: -                dpt = town.numero_insee[:2] -                if dpt not in dpts: -                    dpts.append(dpt) -            return ', '.join(list(sorted(dpts))) - -        @property -        def related_item(self): -            return self.operation if self.operation else self.associated_file - -        def get_filename(self): -            filename = self.related_item.associated_filename -            filename = u"-".join(filename.split('-')[:-1])  # remove date -            if self.act_type.code: -                filename += u"-" + self.act_type.code -            if self.signature_date and self.index: -                filename += u"-%d-%d" % (self.signature_date.year, -                                         self.index) -            if self.signature_date: -                filename += u"-" + self.signature_date.strftime('%Y%m%d') -            return filename - -        def publish(self, template_pk=None): -            if not self.act_type.associated_template.count(): +    full_ref_lbl = _(u"Ref.") + +    @property +    def full_ref(self): +        lbl = [] +        if self.year: +            lbl.append(unicode(self.year)) +        if self.index: +            lbl.append(u"n°%d" % self.index) +        if settings.COUNTRY == 'fr' and self.ref_sra: +            lbl.append(u"[%s]" % self.ref_sra) +        return u" ".join(lbl) + +    @property +    def towns(self): +        if self.associated_file: +            return self.associated_file.towns.all() +        elif self.operation: +            return self.operation.towns.all() +        return [] + +    @property +    def departments(self): +        if settings.COUNTRY != 'fr': +            return '' +        q = None +        if self.associated_file: +            q = self.associated_file.towns.all() +        elif self.operation: +            q = self.operation.towns.all() +        if not q: +            return '' +        dpts = [] +        for town in q: +            dpt = town.numero_insee[:2] +            if dpt not in dpts: +                dpts.append(dpt) +        return ', '.join(list(sorted(dpts))) + +    @property +    def related_item(self): +        return self.operation if self.operation else self.associated_file + +    def get_filename(self): +        filename = self.related_item.associated_filename +        filename = u"-".join(filename.split('-')[:-1])  # remove date +        if self.act_type.code: +            filename += u"-" + self.act_type.code +        if self.signature_date and self.index: +            filename += u"-%d-%d" % (self.signature_date.year, +                                     self.index) +        if self.signature_date: +            filename += u"-" + self.signature_date.strftime('%Y%m%d') +        return filename + +    def publish(self, template_pk=None): +        if not self.act_type.associated_template.count(): +            return +        if not template_pk: +            template = self.act_type.associated_template.all()[0] +        else: +            q = self.act_type.associated_template.filter(pk=template_pk) +            if not q.count():                  return -            if not template_pk: -                template = self.act_type.associated_template.all()[0] -            else: -                q = self.act_type.associated_template.filter(pk=template_pk) -                if not q.count(): -                    return -                template = q.all()[0] -            return template.publish(self) - -        def _get_index(self): -            if not self.index: -                c_index = 1 -                q = AdministrativeAct.objects.filter( -                    act_type__indexed=True, signature_date__year=self.year, -                    index__isnull=False).order_by("-index") -                if q.count(): -                    c_index = q.all()[0].index + 1 -                self.index = c_index -            conflict = AdministrativeAct.objects.filter( +            template = q.all()[0] +        return template.publish(self) + +    def _get_index(self): +        if not self.index: +            c_index = 1 +            q = AdministrativeAct.objects.filter(                  act_type__indexed=True, signature_date__year=self.year, -                index=self.index) +                index__isnull=False).order_by("-index") +            if q.count(): +                c_index = q.all()[0].index + 1 +            self.index = c_index +        conflict = AdministrativeAct.objects.filter( +            act_type__indexed=True, signature_date__year=self.year, +            index=self.index) +        if self.pk: +            conflict = conflict.exclude(pk=self.pk) +        if conflict.count():              if self.pk: -                conflict = conflict.exclude(pk=self.pk) -            if conflict.count(): -                if self.pk: -                    raise ValidationError(_(u"This index already exists for " -                                            u"this year")) -                else: -                    self._get_index() - -        def clean(self, *args, **kwargs): -            if not self.signature_date: -                return super(AdministrativeAct, self).clean(*args, **kwargs) -            self.year = self.signature_date.year -            if not self.act_type.indexed: -                return super(AdministrativeAct, self).clean(*args, **kwargs) -            self._get_index() -            super(AdministrativeAct, self).clean(*args, **kwargs) +                raise ValidationError(_(u"This index already exists for " +                                        u"this year")) +            else: +                self._get_index() + +    def clean(self, *args, **kwargs): +        if not self.signature_date: +            return super(AdministrativeAct, self).clean(*args, **kwargs) +        self.year = self.signature_date.year +        if not self.act_type.indexed: +            return super(AdministrativeAct, self).clean(*args, **kwargs) +        self._get_index() +        super(AdministrativeAct, self).clean(*args, **kwargs) -        def save(self, *args, **kwargs): -            if settings.COUNTRY == 'fr': -                self.departments_label = self.departments -            self.towns_label = u", ".join( -                list(sorted([unicode(town) for town in self.towns]))) +    def save(self, *args, **kwargs): +        if settings.COUNTRY == 'fr': +            self.departments_label = self.departments +        self.towns_label = u", ".join( +            list(sorted([unicode(town) for town in self.towns]))) -            force = False -            if 'force' in kwargs: -                force = kwargs.pop('force') +        force = False +        if 'force' in kwargs: +            force = kwargs.pop('force') -            if not self.signature_date: -                return super(AdministrativeAct, self).save(*args, **kwargs) -            self.year = self.signature_date.year +        if not self.signature_date: +            return super(AdministrativeAct, self).save(*args, **kwargs) +        self.year = self.signature_date.year -            if not self.act_type.indexed: -                return super(AdministrativeAct, self).save(*args, **kwargs) +        if not self.act_type.indexed: +            return super(AdministrativeAct, self).save(*args, **kwargs) -            if not force: +        if not force: +            self._get_index() +        else: +            try:                  self._get_index() -            else: -                try: -                    self._get_index() -                except: -                    pass +            except: +                pass -            super(AdministrativeAct, self).save(*args, **kwargs) -            if hasattr(self, 'associated_file') and self.associated_file: -                self.associated_file.update_has_admin_act() -                self.associated_file.update_short_menu_class() +        super(AdministrativeAct, self).save(*args, **kwargs) +        if hasattr(self, 'associated_file') and self.associated_file: +            self.associated_file.update_has_admin_act() +            self.associated_file.update_short_menu_class()  def strip_zero(value): @@ -768,11 +758,10 @@ def strip_zero(value):  class Parcel(LightHistorizedItem): -    if FILES_AVAILABLE: -        associated_file = models.ForeignKey( -            'archaeological_files.File', -            related_name='parcels', verbose_name=_(u"File"), -            blank=True, null=True) +    associated_file = models.ForeignKey( +        'archaeological_files.File', +        related_name='parcels', verbose_name=_(u"File"), +        blank=True, null=True)      operation = models.ForeignKey(          Operation, related_name='parcels', blank=True, null=True,          verbose_name=_(u"Operation")) @@ -867,7 +856,7 @@ class Parcel(LightHistorizedItem):      def long_label(self):          items = [unicode(self.operation) or -                 (FILES_AVAILABLE and unicode(self.associated_file)) or ""] +                 unicode(self.associated_file) or ""]          items += [unicode(item) for item in [self.section, self.parcel_number]                    if item]          return settings.JOINT.join(items) @@ -931,12 +920,10 @@ def parcel_post_save(sender, **kwargs):      if parcel.operation and parcel.operation.pk and \         parcel.town not in list(parcel.operation.towns.all()):          parcel.operation.towns.add(parcel.town) -    if FILES_AVAILABLE and parcel.associated_file and \ +    if parcel.associated_file and \         parcel.associated_file.pk and \         parcel.town not in list(parcel.associated_file.towns.all()):          parcel.associated_file.towns.add(parcel.town) -    if not FILES_AVAILABLE: -        return      if parcel.operation and parcel.associated_file:          # parcels are copied between files and operations          parcel.copy_to_operation() diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index 5299b7131..22d820b5b 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -30,6 +30,7 @@ from ishtar_common.wizards import SearchWizard, check_rights_condition  from ishtar_common.forms import ClosingDateFormSelection  from ishtar_common.forms_common import AuthorFormset, TownFormset, \      SourceDeletionForm +from ishtar_common.models import get_current_profile  from wizards import *  from forms import *  import models @@ -243,7 +244,7 @@ wizard_steps = [      ('relations-operation_creation', RecordRelationsFormSet),      ('abstract-operation_creation', OperationFormAbstract),      ('final-operation_creation', FinalForm)] -if FILES_AVAILABLE: +if get_current_profile().files:      wizard_steps.insert(0, ('filechoice-operation_creation',                              OperationFormFileChoice)) diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py index 6e512e826..c90b6fa8a 100644 --- a/archaeological_operations/wizards.py +++ b/archaeological_operations/wizards.py @@ -31,9 +31,7 @@ from ishtar_common.wizards import Wizard, ClosingWizard, DeletionWizard, \  import models  from forms import GenerateDocForm -FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS -if FILES_AVAILABLE: -    from archaeological_files.models import File +from archaeological_files.models import File  class OperationWizard(Wizard): @@ -59,7 +57,7 @@ class OperationWizard(Wizard):      def get_current_file(self):          step = self.steps.current -        if not FILES_AVAILABLE or not step: +        if not step:              return          file_form_key = 'general-' + self.url_name          if self.url_name == 'operation_creation': @@ -104,8 +102,6 @@ class OperationWizard(Wizard):          """          Get available towns          """ -        if not FILES_AVAILABLE: -            return -1          towns = []          file = self.get_current_file()          if not file: diff --git a/archaeological_warehouse/ishtar_menu.py b/archaeological_warehouse/ishtar_menu.py index 3551fab00..f9f0daf33 100644 --- a/archaeological_warehouse/ishtar_menu.py +++ b/archaeological_warehouse/ishtar_menu.py @@ -28,6 +28,7 @@ from archaeological_finds.models import Treatment  MENU_SECTIONS = [      (60, SectionItem('find_management', _(u"Find"), +     profile_restriction='warehouse',       childs=[          MenuItem('warehouse_packaging', _(u"Packaging"),                   model=Treatment, diff --git a/example_project/urls.py b/example_project/urls.py index 203c44d4d..62a6b1e04 100644 --- a/example_project/urls.py +++ b/example_project/urls.py @@ -14,10 +14,10 @@ APP_LIST = ['archaeological_files_pdl', 'archaeological_files',              'archaeological_operations', 'archaeological_context_records',              'archaeological_warehouse', 'archaeological_finds']  for app in APP_LIST: -    if app in settings.INSTALLED_APPS: -        urlpatterns += patterns( -            '', ('', include(app + '.urls')), -        ) +    # filter by activated apps? +    urlpatterns += patterns( +        '', ('', include(app + '.urls')), +    )  urlpatterns += patterns(      '', ('', include('ishtar_common.urls')), diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py index ce303c344..03ba9bc36 100644 --- a/ishtar_common/context_processors.py +++ b/ishtar_common/context_processors.py @@ -25,18 +25,20 @@ from ishtar_common.utils import shortify  from menus import Menu +from ishtar_common.models import get_current_profile  from archaeological_operations.models import Operation +from archaeological_files.models import File +from archaeological_context_records.models import ContextRecord +from archaeological_finds.models import Find +profile = get_current_profile()  CURRENT_ITEMS = [] -if 'archaeological_files' in settings.INSTALLED_APPS: -    from archaeological_files.models import File +if profile.files:      CURRENT_ITEMS.append((_(u"Archaeological file"), File))  CURRENT_ITEMS.append((_(u"Operation"), Operation)) -if 'archaeological_context_records' in settings.INSTALLED_APPS: -    from archaeological_context_records.models import ContextRecord +if profile.context_record:      CURRENT_ITEMS.append((_(u"Context record"), ContextRecord)) -if 'archaeological_finds' in settings.INSTALLED_APPS: -    from archaeological_finds.models import Find +if profile.find:      CURRENT_ITEMS.append((_(u"Find"), Find)) diff --git a/ishtar_common/management/commands/update_specific_importers.py b/ishtar_common/management/commands/update_specific_importers.py index c5445eb0b..9a13e3f3e 100644 --- a/ishtar_common/management/commands/update_specific_importers.py +++ b/ishtar_common/management/commands/update_specific_importers.py @@ -4,14 +4,11 @@  from optparse import make_option  from django.core.management.base import BaseCommand -from django.conf import settings  IMPORTERS = [] - -if 'archaeological_files' in settings.INSTALLED_APPS: -    from archaeological_files.data_importer import FileImporterSraPdL -    IMPORTERS.append(FileImporterSraPdL) +from archaeological_files.data_importer import FileImporterSraPdL +IMPORTERS.append(FileImporterSraPdL)  class Command(BaseCommand): diff --git a/ishtar_common/menu_base.py b/ishtar_common/menu_base.py index ab0a43d41..eb08d8c78 100644 --- a/ishtar_common/menu_base.py +++ b/ishtar_common/menu_base.py @@ -17,16 +17,28 @@  # See the file COPYING for details. +from ishtar_common.models import get_current_profile +  class SectionItem: -    def __init__(self, idx, label, childs=[]): +    def __init__(self, idx, label, childs=[], profile_restriction=None):          self.idx = idx          self.label = label          self.childs = childs          self.available = False          self.items = {} +        self.profile_restriction = profile_restriction + +    def check_profile_restriction(self): +        if self.profile_restriction: +            profile = get_current_profile() +            if not getattr(profile, self.profile_restriction): +                return False +        return True      def can_be_available(self, user, session=None): +        if not self.check_profile_restriction(): +            return False          for child in self.childs:              if child.can_be_available(user, session=session):                  return True @@ -50,14 +62,27 @@ class SectionItem:  class MenuItem: -    def __init__(self, idx, label, model=None, access_controls=[]): +    def __init__(self, idx, label, model=None, access_controls=[], +                 profile_restriction=None):          self.idx = idx          self.label = label          self.model = model          self.access_controls = access_controls          self.available = False +        self.profile_restriction = profile_restriction +        if not self.check_profile_restriction(): +            return False + +    def check_profile_restriction(self): +        if self.profile_restriction: +            profile = get_current_profile() +            if not getattr(profile, self.profile_restriction): +                return False +        return True      def can_be_available(self, user, session=None): +        if not self.check_profile_restriction(): +            return False          if not self.access_controls:              return True          prefix = (self.model._meta.app_label + '.') if self.model else '' @@ -75,6 +100,8 @@ class MenuItem:          return False      def is_available(self, user, obj=None, session=None): +        if not self.check_profile_restriction(): +            return False          if not self.access_controls:              return True          prefix = (self.model._meta.app_label + '.') if self.model else '' diff --git a/ishtar_common/models.py b/ishtar_common/models.py index bcd1881d6..f5c6ed223 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -250,13 +250,16 @@ class OwnPerms:  class Cached(object): +    slug_field = 'txt_idx' +      @classmethod      def get_cache(cls, slug):          cache_key, value = get_cache(cls, slug)          if value:              return value          try: -            obj = cls.objects.get(txt_idx=slug) +            k = {cls.slug_field: slug} +            obj = cls.objects.get(**k)              cache.set(cache_key, obj, settings.CACHE_TIMEOUT)              return obj          except cls.DoesNotExist: @@ -768,6 +771,7 @@ class LightHistorizedItem(BaseHistorizedItem):  class IshtarSiteProfile(models.Model, Cached): +    slug_field = 'slug'      label = models.TextField(_(u"Name"))      slug = models.SlugField(_(u"Slug"), unique=True)      description = models.TextField(_(u"Description"), null=True, blank=True) @@ -817,6 +821,20 @@ class IshtarSiteProfile(models.Model, Cached):          return obj +def get_current_profile(): +    cache_key, value = get_cache(IshtarSiteProfile, 'is-current-profile') +    if value: +        return value +    q = IshtarSiteProfile.objects.filter(active=True) +    if not q.count(): +        obj = IshtarSiteProfile.objects.create( +            label="Default profile", slug='default', active=True) +    else: +        obj = q.all()[0] +    cache.set(cache_key, obj, settings.CACHE_TIMEOUT) +    return obj + +  class GlobalVar(models.Model, Cached):      slug = models.SlugField(_(u"Variable name"), unique=True)      description = models.TextField(_(u"Description of the variable"), @@ -1214,29 +1232,29 @@ class OrganizationType(GeneralType):          verbose_name_plural = _(u"Organization types")          ordering = ('label',) -MODELS = [ -    ('archaeological_operations.models.Operation', _(u"Operation")), -    ('archaeological_operations.models.ArchaeologicalSite', -     _(u"Archaeological site")), -    ('archaeological_operations.models.Parcel', _(u"Parcels")), -    ('archaeological_operations.models.OperationSource', -     _(u"Operation source")), -] -  IMPORTER_CLASSES = {} -if 'archaeological_files' in settings.INSTALLED_APPS: -    MODELS = [('archaeological_files.models.File', _(u"Archaeological files"))]\ -        + MODELS -    IMPORTER_CLASSES.update({ -        'sra-pdl-files': -        'archaeological_files.data_importer.FileImporterSraPdL'}) -if 'archaeological_context_records' in settings.INSTALLED_APPS: +IMPORTER_CLASSES.update({ +    'sra-pdl-files': +    'archaeological_files.data_importer.FileImporterSraPdL'}) + + +def get_importer_models(): +    MODELS = [ +        ('archaeological_operations.models.Operation', _(u"Operation")), +        ('archaeological_operations.models.ArchaeologicalSite', +         _(u"Archaeological site")), +        ('archaeological_operations.models.Parcel', _(u"Parcels")), +        ('archaeological_operations.models.OperationSource', +         _(u"Operation source")), +    ] +    MODELS = [('archaeological_files.models.File', +              _(u"Archaeological files"))] + MODELS      MODELS = [('archaeological_context_records.models.ContextRecord',                _(u"Context records")), ] + MODELS -if 'archaeological_finds' in settings.INSTALLED_APPS:      MODELS = [('archaeological_finds.models.BaseFind',                _(u"Finds")), ] + MODELS +    return MODELS  def get_model_fields(model): @@ -1274,7 +1292,8 @@ class ImporterType(models.Model):      users = models.ManyToManyField('IshtarUser', verbose_name=_(u"Users"),                                     blank=True, null=True)      associated_models = models.CharField(_(u"Associated model"), -                                         max_length=200, choices=MODELS) +                                         max_length=200, +                                         choices=get_importer_models())      is_template = models.BooleanField(_(u"Is template"), default=False)      unicity_keys = models.CharField(_(u"Unicity keys (separator \";\")"),                                      blank=True, null=True, max_length=500) diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index 4e800b0d5..e2c9b233f 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -182,3 +182,9 @@ class IshtarSiteProfileTest(TestCase):          profile2.warehouse = True          profile2 = profile2.save()          self.assertTrue(profile2.context_record and profile2.find) + +    def testDefaultProfile(self): +        self.assertFalse(models.IshtarSiteProfile.objects.count()) +        profile = models.get_current_profile() +        self.assertTrue(profile) +        self.assertTrue(models.IshtarSiteProfile.objects.count()) diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 6f95e070a..1c944441f 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -51,7 +51,12 @@ from xhtml2odt import xhtml2odt  from menus import menu +from archaeological_files.models import File +from archaeological_context_records.models import ContextRecord +from archaeological_finds.models import Find +  from archaeological_operations.forms import DashboardForm as DashboardFormOpe +from archaeological_files.forms import DashboardForm as DashboardFormFile  from ishtar_common.forms import FinalForm, FinalDeleteForm  from ishtar_common import forms_common as forms @@ -927,22 +932,20 @@ def dashboard_main(request, dct, obj_id=None, *args, **kwargs):      Main dashboard      """      app_list = [] -    if 'archaeological_files' in settings.INSTALLED_APPS: +    profile = models.get_current_profile() +    if profile.files:          app_list.append((_(u"Archaeological files"), 'files'))      app_list.append((_(u"Operations"), 'operations')) -    if 'archaeological_context_records' in settings.INSTALLED_APPS: +    if profile.context_record:          app_list.append((_(u"Context records"), 'contextrecords')) -    if 'archaeological_finds' in settings.INSTALLED_APPS: +    if profile.find:          app_list.append((_(u"Finds"), 'finds'))      dct = {'app_list': app_list}      return render_to_response('ishtar/dashboards/dashboard_main.html', dct,                                context_instance=RequestContext(request))  DASHBOARD_FORMS = {} -if 'archaeological_files' in settings.INSTALLED_APPS: -    from archaeological_files.forms import DashboardForm as DashboardFormFile -    DASHBOARD_FORMS['files'] = DashboardFormFile - +DASHBOARD_FORMS['files'] = DashboardFormFile  DASHBOARD_FORMS['operations'] = DashboardFormOpe @@ -957,8 +960,8 @@ def dashboard_main_detail(request, item_name):              dct, context_instance=RequestContext(request))      form = None      slicing, date_source, fltr, show_detail = 'year', None, {}, False -    if (item_name == 'files' and -        'archaeological_files' in settings.INSTALLED_APPS) \ +    profile = models.get_current_profile() +    if (item_name == 'files' and profile.files) \              or item_name == 'operations':          slicing = 'month'      if item_name in DASHBOARD_FORMS: @@ -974,32 +977,25 @@ def dashboard_main_detail(request, item_name):          else:              form = DASHBOARD_FORMS[item_name]()      lbl, dashboard = None, None -    if (item_name == 'files' and -        'archaeological_files' in settings.INSTALLED_APPS) \ +    if (item_name == 'files' and profile.files) \              or item_name == 'operations':          dashboard_kwargs = {'slice': slicing, 'fltr': fltr,                              'show_detail': show_detail}          # date_source is only relevant when the form has set one          if date_source:              dashboard_kwargs['date_source'] = date_source -    if item_name == 'files' and \ -            'archaeological_files' in settings.INSTALLED_APPS: -        from archaeological_files.models import File +    if item_name == 'files' and profile.files:          lbl, dashboard = (_(u"Archaeological files"),                            models.Dashboard(File, **dashboard_kwargs))      if item_name == 'operations':          from archaeological_operations.models import Operation          lbl, dashboard = (_(u"Operations"),                            models.Dashboard(Operation, **dashboard_kwargs)) -    if item_name == 'contextrecords' and \ -            'archaeological_context_records' in settings.INSTALLED_APPS: -        from archaeological_context_records.models import ContextRecord +    if item_name == 'contextrecords' and profile.context_record:          lbl, dashboard = (              _(u"Context records"),              models.Dashboard(ContextRecord, slice=slicing, fltr=fltr)) -    if item_name == 'finds' and \ -            'archaeological_finds' in settings.INSTALLED_APPS: -        from archaeological_finds.models import Find +    if item_name == 'finds' and profile.find:          lbl, dashboard = (_(u"Finds"), models.Dashboard(Find,                                                          slice=slicing,                                                          fltr=fltr))  | 
