diff options
Diffstat (limited to 'ishtar/ishtar_base/models.py')
-rw-r--r-- | ishtar/ishtar_base/models.py | 165 |
1 files changed, 164 insertions, 1 deletions
diff --git a/ishtar/ishtar_base/models.py b/ishtar/ishtar_base/models.py index 2a8248804..cbf362b83 100644 --- a/ishtar/ishtar_base/models.py +++ b/ishtar/ishtar_base/models.py @@ -27,7 +27,7 @@ from django.core.validators import validate_slug from django.utils.translation import ugettext_lazy as _, ugettext from django.db.utils import DatabaseError from django.utils.safestring import SafeUnicode, mark_safe -from django.db.models import Q, Max +from django.db.models import Q, Max, Count from django.db.models.signals import m2m_changed from django.contrib.auth.models import User @@ -348,6 +348,77 @@ class LightHistorizedItem(BaseHistorizedItem): super(LightHistorizedItem, self).save(*args, **kwargs) return True +class Dashboard: + def __init__(self, model): + self.model = model + self.total_number = model.get_total_number() + # years + self.years = model.get_years() + self.years.sort() + if not self.total_number or not self.years: + return + self.values = [('year', _(u"Year"), reversed(self.years))] + # numbers + self.numbers = [model.get_by_year(year).count() for year in self.years] + self.values += [('number', _(u"Number"), reversed(self.numbers))] + # calculate + self.average = self.get_average() + self.variance = self.get_variance() + self.standard_deviation = self.get_standard_deviation() + self.median = self.get_median() + self.mode = self.get_mode() + # by operation + if not hasattr(model, 'get_by_operation'): + return + operations = model.get_operations() + operation_numbers = [model.get_by_operation(op).count() + for op in operations] + # calculate + self.operation_average = self.get_average(operation_numbers) + self.operation_variance = self.get_variance(operation_numbers) + self.operation_standard_deviation = self.get_standard_deviation( + operation_numbers) + self.operation_median = self.get_median(operation_numbers) + operation_mode_pk = self.get_mode(dict(zip(operations, + operation_numbers))) + if operation_mode_pk: + self.operation_mode = unicode(Operation.objects.get( + pk=operation_mode_pk)) + + def get_average(self, vals=[]): + if not vals: + vals = self.numbers + return sum(vals)/len(vals) + + def get_variance(self, vals=[]): + if not vals: + vals = self.numbers + avrg = self.get_average(vals) + return self.get_average([(x-avrg)**2 for x in vals]) + + def get_standard_deviation(self, vals=[]): + if not vals: + vals = self.numbers + return round(self.get_variance(vals)**0.5, 3) + + def get_median(self, vals=[]): + if not vals: + vals = self.numbers + len_vals = len(vals) + vals.sort() + if (len_vals % 2) == 1: + return vals[len_vals/2] + else: + return (vals[len_vals/2-1] + vals[len_vals/2])/2.0 + + def get_mode(self, vals={}): + if not vals: + vals = dict(zip(self.years, self.numbers)) + mx = max(vals.values()) + for v in vals: + if vals[v] == mx: + return v + class Departement(models.Model): label = models.CharField(_(u"Label"), max_length=30) number = models.CharField(_(u"Number"), unique=True, max_length=3) @@ -571,6 +642,19 @@ class File(BaseHistorizedItem, OwnPerms): ) ordering = ['-year', '-numeric_reference'] + @classmethod + def get_years(cls): + return [res['year'] for res in list(cls.objects.values('year').annotate( + Count("id")).order_by())] + + @classmethod + def get_by_year(cls, year): + return cls.objects.filter(year=year) + + @classmethod + def get_total_number(cls): + return cls.objects.count() + def __unicode__(self): items = [unicode(_('Intercommunal'))] if self.towns.count() == 1: @@ -686,6 +770,19 @@ class Operation(BaseHistorizedItem, OwnPerms): unicode(self.operation_code)))) return JOINT.join(items) + @classmethod + def get_years(cls): + return [res['year'] for res in list(cls.objects.values('year').annotate( + Count("id")).order_by())] + + @classmethod + def get_by_year(cls, year): + return cls.objects.filter(year=year) + + @classmethod + def get_total_number(cls): + return cls.objects.count() + year_index_lbl = _(u"Operation code") @property def year_index(self): @@ -930,6 +1027,32 @@ class ContextRecord(BaseHistorizedItem, OwnPerms): return JOINT.join([unicode(lbl) for lbl in [self.parcel.operation.year, self.parcel.operation.operation_code, self.label] if lbl]) + + @classmethod + def get_years(cls): + years = set() + for res in list(cls.objects.values('operation__start_date')): + yr = res['operation__start_date'].year + years.add(yr) + return list(years) + + @classmethod + def get_by_year(cls, year): + return cls.objects.filter(operation__start_date__year=year) + + @classmethod + def get_operations(cls): + return [dct['operation__pk'] + for dct in cls.objects.values('operation__pk').distinct()] + + @classmethod + def get_by_operation(cls, operation_id): + return cls.objects.filter(operation__pk=operation_id) + + @classmethod + def get_total_number(cls): + return cls.objects.filter(operation__start_date__isnull=False).count() + class ContextRecordSource(Source): class Meta: verbose_name = _(u"Context record documentation") @@ -1036,6 +1159,46 @@ class Item(BaseHistorizedItem, OwnPerms): blank=True, null=True, related_name='items') history = HistoricalRecords() + @classmethod + def get_years(cls): + years = set() + items = cls.objects.filter(downstream_treatment__isnull=True) + for item in items: + bi = item.base_items.all() + if not bi: + continue + bi = bi[0] + yr = bi.context_record.operation.start_date.year + years.add(yr) + return list(years) + + @classmethod + def get_by_year(cls, year): + return cls.objects.filter(downstream_treatment__isnull=True, + base_items__context_record__operation__start_date__year=year) + + @classmethod + def get_operations(cls): + operations = set() + items = cls.objects.filter(downstream_treatment__isnull=True) + for item in items: + bi = item.base_items.all() + if not bi: + continue + bi = bi[0] + pk = bi.context_record.operation.pk + operations.add(pk) + return list(operations) + + @classmethod + def get_by_operation(cls, operation_id): + return cls.objects.filter(downstream_treatment__isnull=True, + base_items__context_record__operation__pk=operation_id) + + @classmethod + def get_total_number(cls): + return cls.objects.filter(downstream_treatment__isnull=True).count() + def duplicate(self, user): dct = dict([(attr, getattr(self, attr)) for attr in ('order', 'label', 'description', 'material_type', 'volume', 'weight', |