1- from datetime import datetime
1+ from datetime import datetime , tzinfo
22from typing import Dict , List , Union
33
44from django .conf import settings
77from django .utils .timezone import now
88from django .utils .translation import gettext_lazy as _
99
10- from donations .models .ngos import Ngo
10+ from donations .views .dashboard .stats_helpers .chart import donors_for_month
11+ from donations .views .dashboard .stats_helpers .metrics import (
12+ all_redirections ,
13+ all_registered_ngos ,
14+ current_year_redirections ,
15+ ngos_active_in_current_year ,
16+ ngos_with_ngo_hub ,
17+ )
18+ from donations .views .dashboard .stats_helpers .yearly import get_stats_for_year
1119from redirectioneaza .common .cache import cache_decorator
1220
13- from ...models .donors import Donor
1421from .helpers import (
1522 generate_donations_per_month_chart ,
1623 get_current_year_range ,
1926
2027ADMIN_DASHBOARD_CACHE_KEY = "ADMIN_DASHBOARD"
2128ADMIN_DASHBOARD_STATS_CACHE_KEY = "ADMIN_DASHBOARD_STATS"
29+ ADMIN_DASHBOARD_HEADER_CACHE_KEY = "ADMIN_DASHBOARD_HEADER"
2230
2331
24- def callback (request , context ) -> Dict :
32+ def callback (_ , context ) -> Dict :
2533 context .update (_get_admin_stats ())
26-
2734 return context
2835
2936
30- @cache_decorator (timeout = settings .TIMEOUT_CACHE_NORMAL , cache_key = ADMIN_DASHBOARD_STATS_CACHE_KEY )
3137def _get_admin_stats () -> Dict :
32- today = now ()
3338 years_range_ascending = get_current_year_range ()
3439
35- header_stats : List [List [Dict [str , Union [str , int ]]]] = _get_header_stats (today )
40+ header_stats : List [List [Dict [str , Union [str , int ]]]] = _get_header_stats ()
3641
3742 yearly_stats : List [Dict ] = _get_yearly_stats (years_range_ascending )
3843
@@ -45,72 +50,79 @@ def _get_admin_stats() -> Dict:
4550 }
4651
4752
48- def _get_header_stats (today ) -> List [List [Dict [str , Union [str , int | datetime ]]]]:
49- current_year = today .year
53+ @cache_decorator (timeout = settings .TIMEOUT_CACHE_SHORT , cache_key = ADMIN_DASHBOARD_HEADER_CACHE_KEY )
54+ def _get_header_stats () -> List [List [Dict [str , Union [str , int | datetime ]]]]:
55+ today : datetime = now ()
5056
51- current_year_range = get_encoded_current_year_range (current_year , today .tzinfo )
57+ current_year : int = today .year
58+ tz_info : tzinfo = today .tzinfo
59+
60+ current_year_range = get_encoded_current_year_range (current_year , tz_info )
5261
5362 return [
5463 [
5564 {
5665 "title" : _ ("Donations this year" ),
5766 "icon" : "edit_document" ,
58- "metric" : Donor . available . filter ( date_created__year = current_year ). count (),
67+ "metric" : current_year_redirections (),
5968 "footer" : _create_stat_link (
60- url = f"{ reverse ('admin:donations_donor_changelist' )} ?{ current_year_range } " , text = _ ("View all" )
69+ url = f"{ reverse ('admin:donations_donor_changelist' )} ?{ current_year_range } " ,
70+ text = _ ("View all" ),
6171 ),
62- "timestamp" : now (),
6372 },
6473 {
6574 "title" : _ ("Donations all-time" ),
6675 "icon" : "edit_document" ,
67- "metric" : Donor .available .count (),
68- "footer" : _create_stat_link (url = reverse ("admin:donations_donor_changelist" ), text = _ ("View all" )),
69- "timestamp" : now (),
76+ "metric" : all_redirections (),
77+ "footer" : _create_stat_link (
78+ url = reverse ("admin:donations_donor_changelist" ),
79+ text = _ ("View all" ),
80+ ),
7081 },
7182 {
7283 "title" : _ ("NGOs registered" ),
7384 "icon" : "foundation" ,
74- "metric" : Ngo . active . count (),
85+ "metric" : all_registered_ngos (),
7586 "footer" : _create_stat_link (
76- url = f"{ reverse ('admin:donations_ngo_changelist' )} ?is_active=1" , text = _ ("View all" )
87+ url = f"{ reverse ('admin:donations_ngo_changelist' )} ?is_active=1" ,
88+ text = _ ("View all" ),
7789 ),
78- "timestamp" : now (),
7990 },
8091 {
8192 "title" : _ ("Functioning NGOs" ),
8293 "icon" : "foundation" ,
83- "metric" : Ngo .with_forms_this_year .count (),
84- "footer" : _create_stat_link (url = f"{ reverse ('admin:donations_ngo_changelist' )} " , text = _ ("View all" )),
85- "timestamp" : now (),
94+ "metric" : ngos_active_in_current_year (),
95+ "footer" : _create_stat_link (
96+ url = f"{ reverse ('admin:donations_ngo_changelist' )} " ,
97+ text = _ ("View all" ),
98+ ),
8699 },
87100 {
88101 "title" : _ ("NGOs from NGO Hub" ),
89102 "icon" : "foundation" ,
90- "metric" : Ngo . ngo_hub . count (),
103+ "metric" : ngos_with_ngo_hub (),
91104 "footer" : _create_stat_link (
92- url = f"{ reverse ('admin:donations_ngo_changelist' )} ?is_active=1&has_ngohub=1" , text = _ ("View all" )
105+ url = f"{ reverse ('admin:donations_ngo_changelist' )} ?is_active=1&has_ngohub=1" ,
106+ text = _ ("View all" ),
93107 ),
94- "timestamp" : now (),
95108 },
96109 ]
97110 ]
98111
99112
100113def _create_chart_statistics () -> Dict [str , str ]:
101114 default_border_width : int = 3
115+ current_year = now ().year
102116
103- donations_per_month_queryset = [
104- Donor . available . filter ( date_created__month = month ) for month in range (1 , settings .DONATIONS_LIMIT .month + 1 )
117+ donations_per_month_queryset : List [ int ] = [
118+ donors_for_month ( month , current_year )[ "metric" ] for month in range (1 , settings .DONATIONS_LIMIT .month + 1 )
105119 ]
106120
107- forms_per_month_chart = generate_donations_per_month_chart (default_border_width , donations_per_month_queryset )
108-
109- return forms_per_month_chart
121+ return generate_donations_per_month_chart (default_border_width , donations_per_month_queryset )
110122
111123
112124def _get_yearly_stats (years_range_ascending ) -> List [Dict [str , Union [int , List [Dict ]]]]:
113- statistics = [_get_stats_for_year (year ) for year in years_range_ascending ]
125+ statistics = [get_stats_for_year (year ) for year in years_range_ascending ]
114126
115127 for index , statistic in enumerate (statistics ):
116128 if index == 0 :
@@ -129,24 +141,6 @@ def _get_yearly_stats(years_range_ascending) -> List[Dict[str, Union[int, List[D
129141 return sorted (final_statistics , key = lambda x : x ["year" ], reverse = True )
130142
131143
132- # TODO: This cache seems useless because we already cache the entire dashboard stats
133- @cache_decorator (timeout = settings .TIMEOUT_CACHE_NORMAL , cache_key_prefix = ADMIN_DASHBOARD_CACHE_KEY )
134- def _get_stats_for_year (year : int ) -> Dict [str , int | datetime ]:
135- donations : int = Donor .available .filter (date_created__year = year ).count ()
136- ngos_registered : int = Ngo .objects .filter (date_created__year = year ).count ()
137- ngos_with_forms : int = Donor .available .filter (date_created__year = year ).values ("ngo_id" ).distinct ().count ()
138-
139- statistic = {
140- "year" : year ,
141- "donations" : donations ,
142- "ngos_registered" : ngos_registered ,
143- "ngos_with_forms" : ngos_with_forms ,
144- "timestamp" : now (),
145- }
146-
147- return statistic
148-
149-
150144def _format_yearly_stats (statistics ) -> List [Dict [str , Union [int , List [Dict ]]]]:
151145 return [
152146 {
@@ -191,5 +185,5 @@ def _format_yearly_stats(statistics) -> List[Dict[str, Union[int, List[Dict]]]]:
191185 ]
192186
193187
194- def _create_stat_link (url : str , text : str ) -> str :
188+ def _create_stat_link (url : str , text ) -> str :
195189 return mark_safe (f'<a href="{ url } " class="text-orange-700 font-semibold">{ text } </a>' )
0 commit comments