129 lines
5.0 KiB
Python
129 lines
5.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
PolyNum
|
|
|
|
Définition des entités administratives
|
|
"""
|
|
|
|
from django.db import models
|
|
from django.db.models import Q
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
class EntityType(models.Model):
|
|
|
|
class Meta:
|
|
app_label = 'base'
|
|
verbose_name = _(u"Type d'entité administrative")
|
|
verbose_name_plural = _(u"Type d'entités administratives")
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
name = models.CharField(max_length=128, verbose_name=_(u'Nom'))
|
|
description = models.TextField(verbose_name=_(u'Description'), blank=True)
|
|
|
|
class EntityManager(models.Manager):
|
|
def rebuild_bounds(self, start=0):
|
|
'''Reallocate left and right bounds, starting at start'''
|
|
def rec(start, entity):
|
|
entity.left_bound = start
|
|
start += 1
|
|
for child_entity in self.filter(parent=entity):
|
|
start = rec(start, child_entity)
|
|
entity.right_bound = start
|
|
entity.save()
|
|
return start + 1
|
|
return rec(start, self.get(parent__isnull=True))
|
|
|
|
class Entity(models.Model):
|
|
objects = EntityManager()
|
|
|
|
class Meta:
|
|
app_label = 'base'
|
|
verbose_name = _(u'Entité administrative')
|
|
verbose_name_plural = _(u'Entités administratives')
|
|
ordering = ('left_bound',)
|
|
|
|
def __unicode__(self):
|
|
return self.get_name()
|
|
|
|
code = models.CharField(max_length=64, verbose_name=_(u'Code'), db_index=True)
|
|
is_active = models.BooleanField(verbose_name=_(u'Active'), default=True, blank=True, db_index=True)
|
|
name = models.CharField(max_length=128, verbose_name=_(u'Nom'), blank=True, db_index=True)
|
|
description = models.TextField(verbose_name=_(u'Description'), blank=True, db_index=True)
|
|
entity_type = models.ForeignKey(EntityType, null=True, blank=True, related_name='+', on_delete=models.PROTECT)
|
|
name_override = models.CharField(max_length=128, verbose_name=_(u'Nom spécifique PolyNum'), blank=True, db_index=True)
|
|
description_override = models.TextField(verbose_name=_(u'Description spécifique PolyNum'), blank=True, db_index=True)
|
|
depth = models.PositiveIntegerField(verbose_name=_('Niveau'), default=0, db_index=True)
|
|
left_bound = models.PositiveIntegerField(unique=True, db_index=True)
|
|
right_bound = models.PositiveIntegerField(unique=True, db_index=True)
|
|
parent = models.ForeignKey('Entity', verbose_name=_(u'Entité parente'), blank=True, null=True, related_name='children_set')
|
|
|
|
def children(self, included=False):
|
|
if included:
|
|
return Entity.objects.filter(left_bound__lt=self.right_bound, left_bound__gte=self.left_bound)
|
|
else:
|
|
return Entity.objects.filter(left_bound__lt=self.right_bound, left_bound__gt=self.left_bound)
|
|
|
|
def parents(self, included=False):
|
|
if included:
|
|
return Entity.objects.filter(left_bound__lte=self.left_bound, right_bound__gte=self.right_bound)
|
|
else:
|
|
return Entity.objects.filter(left_bound__lt=self.left_bound, right_bound__gt=self.right_bound)
|
|
|
|
def parents_and_their_children(self):
|
|
parents = self.parents().order_by('depth')
|
|
filters = []
|
|
for parent in parents:
|
|
filters.append(
|
|
Q(left_bound__lt=parent.right_bound,
|
|
left_bound__gte=parent.left_bound,
|
|
depth__lte=parent.depth+1))
|
|
qs = Entity.objects.filter(
|
|
reduce(Q.__or__, filters)).order_by('depth')
|
|
return qs
|
|
|
|
def accounting_codes(self):
|
|
'''
|
|
return a set of "accounting" codes: one of the entity and those of all its parents
|
|
'''
|
|
for parent in self.parents(included=True).order_by('-depth').prefetch_related('accountingcode_set'):
|
|
if parent.accountingcode_set.all():
|
|
return parent.accountingcode_set.all()
|
|
return AccountingCode.objects.none()
|
|
|
|
def parent_of_type(self, type_name):
|
|
parent = self.parent
|
|
while parent:
|
|
if parent.entity_type.name == type_name:
|
|
break
|
|
parent = parent.parent
|
|
return parent
|
|
|
|
def get_name(self):
|
|
return self.name_override or self.name
|
|
get_name.short_description = _(u'Nom')
|
|
|
|
def get_description(self):
|
|
return self.description_override or self.description
|
|
get_description.short_description = _(u'Description')
|
|
|
|
def level1_parent(self):
|
|
'''
|
|
Show parent of level between 1 or 3 if found, self return the current entity.
|
|
'''
|
|
parents = self.parents()
|
|
if len(parents) > 3:
|
|
return parents[3]
|
|
return self
|
|
|
|
class AccountingCode(models.Model):
|
|
class Meta:
|
|
app_label = 'base'
|
|
verbose_name = _(u'Code de comptabilité/financier')
|
|
verbose_name_plural = _(u'Codes de comptabilité/financier')
|
|
ordering = ('entity', 'code')
|
|
|
|
entity = models.ForeignKey(Entity)
|
|
code = models.CharField(max_length=32, verbose_name=_('Engagement provisionnel'), db_index=True)
|