def get_cached_context_data(self): sum_dict = lambda *ds: { k: sum(d.get(k, 0) or 0 for d in ds) for k in ds[0] } context = self.get_aggregate_data() context['top_progetti'] = context.pop('top_progetti_per_costo') context[ 'territori_piu_finanziati_pro_capite'] = self.top_comuni_pro_capite( filters={'progetto__soggetto_set__pk': self.object.pk}) # == COLLABORATORI CON CUI SI SPARTISCONO PIÙ SOLDI ======================================= top_collaboratori = Soggetto.objects.filter( progetto__ruolo__soggetto=self.object).exclude( pk=self.object.pk).values('pk').annotate( totale=Count('pk')).order_by('-totale')[:5] soggetto_by_pk = Soggetto.objects.in_bulk(x['pk'] for x in top_collaboratori) context['top_collaboratori'] = [] for c in top_collaboratori: soggetto = soggetto_by_pk[c['pk']] soggetto.totale = c['totale'] context['top_collaboratori'].append(soggetto) # == TOTALI PER REGIONI (E NAZIONI) ======================================================= progetti = self.get_progetti_queryset() # i progetti del soggetto localizzati in più territori (vengono considerati a parte per evitare di contarli più volte nelle aggregazioni) progetti_multilocalizzati_pks = [ x['pk'] for x in progetti.values('pk').annotate( cnt=Count('territorio_set__cod_reg', distinct=True)).filter( cnt__gt=1) ] totali_non_multilocalizzati = { x.pop('id'): x for x in progetti.exclude(pk__in=progetti_multilocalizzati_pks). totali_group_by('territorio_set__cod_reg') } totali_multilocalizzati_nazionali = {} totali_multilocalizzati_non_nazionali = {} for progetto in Progetto.objects.filter( pk__in=progetti_multilocalizzati_pks).prefetch_related( 'territorio_set'): totali_progetto = { 'totale_costi': float(progetto.fin_totale_pubblico or 0), 'totale_pagamenti': float(progetto.pagamento or 0), 'totale_progetti': 1 } if any(t.is_nazionale for t in progetto.territori) and not any( t.is_estero for t in progetto.territori ): # con almeno una localizzazione nazionale e nessuna estera totali_multilocalizzati_nazionali = sum_dict( totali_progetto, totali_multilocalizzati_nazionali) else: totali_multilocalizzati_non_nazionali = sum_dict( totali_progetto, totali_multilocalizzati_non_nazionali) if any(totali_multilocalizzati_nazionali.viewvalues()): totali_non_multilocalizzati[0] = sum_dict( totali_multilocalizzati_nazionali, totali_non_multilocalizzati.get(0, {})) # totali_non_multilocalizzati = {key: tots for key, tots in totali_non_multilocalizzati.items() if any(tots.viewvalues())} context['territori'] = [] for territorio in Territorio.objects.regioni(with_nation=True).filter( cod_reg__in=totali_non_multilocalizzati.keys()).order_by( '-territorio', 'denominazione').defer('geom'): territorio.totali = totali_non_multilocalizzati[territorio.cod_reg] context['territori'].append(territorio) # assegno a un territorio fittizio i progetti multilocalizzati senza localizzazione nazionale if any(totali_multilocalizzati_non_nazionali.viewvalues()): territorio = Territorio(denominazione=u'In più territori', territorio='X') territorio.totali = totali_multilocalizzati_non_nazionali context['territori'].append(territorio) # == TOTALI PER RUOLO ===================================================================== totali_by_ruolo_by_progetto = defaultdict(dict) for ruolo in dict(Ruolo.RUOLO).keys(): for totali in Ruolo.objects.filter( soggetto=self.object, ruolo=ruolo, progetto__active_flag=True, progetto__visualizzazione_flag='0').values( 'progetto_id').annotate( totale_costi=Sum('progetto__fin_totale_pubblico'), totale_pagamenti=Sum('progetto__pagamento'), totale_progetti=Count('progetto')): totali_by_ruolo_by_progetto[totali.pop( 'progetto_id')][ruolo] = totali totali_by_ruolo = defaultdict(dict) for totaliprogetto_by_ruolo in totali_by_ruolo_by_progetto.values(): codice = ''.join( totaliprogetto_by_ruolo.keys() ) # in caso di più ruoli per uno stesso progetto si crea un nuovo codice totali = totaliprogetto_by_ruolo.values( )[0] # prendo il primo dei totali per ruolo, tanto DEVONO essere tutti uguali totali_by_ruolo[codice] = sum_dict(totali, totali_by_ruolo[codice]) context['ruoli'] = [{ 'nome': '/'.join(sorted([dict(Ruolo.RUOLO)[r] for r in codice])), 'codice': codice, 'totali': totali } for codice, totali in totali_by_ruolo.items()] return context