@@ -17,6 +17,17 @@ class SPPRegistrant(models.Model):
1717 inkind_entitlement_ids = fields .One2many ("spp.entitlement.inkind" , "partner_id" , "In-kind Entitlements" )
1818
1919 # Statistics
20+ cycle_membership_count = fields .Integer (
21+ string = "# Cycles" ,
22+ compute = "_compute_cycle_membership_count" ,
23+ store = True ,
24+ )
25+ non_compliant_cycle_count = fields .Integer (
26+ string = "# Non-Compliant" ,
27+ compute = "_compute_cycle_membership_count" ,
28+ store = True ,
29+ )
30+
2031 program_membership_count = fields .Integer (
2132 string = "# Program Memberships" ,
2233 compute = "_compute_program_membership_count" ,
@@ -34,6 +45,40 @@ class SPPRegistrant(models.Model):
3445 compute = "_compute_total_entitlements_count" ,
3546 )
3647
48+ @api .depends ("cycle_ids" , "cycle_ids.state" )
49+ def _compute_cycle_membership_count (self ):
50+ """Batch-efficient cycle membership and non-compliant counts."""
51+ if not self :
52+ return
53+
54+ registrants = self .filtered ("is_registrant" )
55+ for partner in self - registrants :
56+ partner .cycle_membership_count = 0
57+ partner .non_compliant_cycle_count = 0
58+
59+ if not registrants :
60+ return
61+
62+ # Total cycle memberships
63+ total_data = self .env ["spp.cycle.membership" ]._read_group (
64+ domain = [("partner_id" , "in" , registrants .ids )],
65+ groupby = ["partner_id" ],
66+ aggregates = ["__count" ],
67+ )
68+ total_counts = {partner .id : count for partner , count in total_data }
69+
70+ # Non-compliant count
71+ nc_data = self .env ["spp.cycle.membership" ]._read_group (
72+ domain = [("partner_id" , "in" , registrants .ids ), ("state" , "=" , "non_compliant" )],
73+ groupby = ["partner_id" ],
74+ aggregates = ["__count" ],
75+ )
76+ nc_counts = {partner .id : count for partner , count in nc_data }
77+
78+ for partner in registrants :
79+ partner .cycle_membership_count = total_counts .get (partner .id , 0 )
80+ partner .non_compliant_cycle_count = nc_counts .get (partner .id , 0 )
81+
3782 @api .depends ("entitlements_count" , "inkind_entitlements_count" )
3883 def _compute_total_entitlements_count (self ):
3984 """Compute combined count of cash and in-kind entitlements."""
@@ -152,6 +197,33 @@ def action_view_program_memberships(self):
152197 "context" : {"default_partner_id" : self .id },
153198 }
154199
200+ def action_view_cycle_memberships (self ):
201+ """Open cycle memberships for this registrant."""
202+ self .ensure_one ()
203+ return {
204+ "name" : _ ("Cycle Memberships - %s" ) % self .name ,
205+ "type" : "ir.actions.act_window" ,
206+ "res_model" : "spp.cycle.membership" ,
207+ "view_mode" : "list,form" ,
208+ "domain" : [("partner_id" , "=" , self .id )],
209+ "context" : {"create" : False },
210+ }
211+
212+ def action_view_non_compliant_cycles (self ):
213+ """Open non-compliant cycle memberships for this registrant."""
214+ self .ensure_one ()
215+ return {
216+ "name" : _ ("Non-Compliant Cycles - %s" ) % self .name ,
217+ "type" : "ir.actions.act_window" ,
218+ "res_model" : "spp.cycle.membership" ,
219+ "view_mode" : "list,form" ,
220+ "domain" : [
221+ ("partner_id" , "=" , self .id ),
222+ ("state" , "=" , "non_compliant" ),
223+ ],
224+ "context" : {"create" : False },
225+ }
226+
155227 def action_view_all_entitlements (self ):
156228 """Open all entitlements (cash + in-kind) for this registrant."""
157229 self .ensure_one ()
0 commit comments