Skip to content

Commit b03812f

Browse files
committed
fix(spp_simulation): fix metric rendering, CEL profile context, and fallback logic
- Load CEL profile in _get_ideal_population_ids so the executor runs with the correct base domain and model context (matches _execute_targeting) - Fix _compute_metric_results_html to read "rate" and "ratio" keys for coverage and ratio metrics instead of always reading "value" - Fix distribution stats to use explicit None check so zero values render as numbers instead of dashes - Add "scenario_id.target_type" to @api.depends for _compute_summary_html - Set amount_mode = "fixed" in the multiplier-to-fixed fallback branch so the wizard item is created with an explicit mode - Fix aggregate metric to use metric.aggregation as the result key so that sum/avg/min/max aggregations read the correct value from the CEL result
1 parent 831df20 commit b03812f

24 files changed

+907
-486
lines changed

spp_simulation/README.rst

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ OpenSPP Targeting Simulation
2020
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
2121
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
2222
:alt: License: LGPL-3
23-
.. |badge3| image:: https://img.shields.io/badge/github-OpenSPP%2Fopenspp--modules-lightgray.png?logo=github
24-
:target: https://github.com/OpenSPP/openspp-modules/tree/19.0/spp_simulation
25-
:alt: OpenSPP/openspp-modules
23+
.. |badge3| image:: https://img.shields.io/badge/github-OpenSPP%2FOpenSPP2-lightgray.png?logo=github
24+
:target: https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_simulation
25+
:alt: OpenSPP/OpenSPP2
2626

2727
|badge1| |badge2| |badge3|
2828

@@ -35,22 +35,21 @@ compare different targeting strategies before committing to criteria.
3535
Key Features
3636
------------
3737

38-
- **Scenario Builder**: Define targeting criteria using CEL expressions
39-
with live preview counts
40-
- **Template Library**: Pre-built templates for common targeting
41-
patterns (elderly pension, female-headed households, etc.)
42-
- **Distribution Analysis**: Gini coefficient, Lorenz curve, percentile
43-
breakdown
44-
- **Fairness Analysis**: Disparity ratios across gender, disability,
45-
location with traffic-light status indicators
46-
- **Targeting Efficiency**: Confusion matrix, leakage rate,
47-
undercoverage against ideal populations
48-
- **Budget Simulation**: Fixed cap and proportional reduction
49-
strategies
50-
- **Scenario Comparison**: Side-by-side comparison of multiple
51-
targeting approaches with overlap analysis
52-
- **Custom Metrics**: Define CEL-based aggregate, coverage, and ratio
53-
metrics
38+
- **Scenario Builder**: Define targeting criteria using CEL expressions
39+
with live preview counts
40+
- **Template Library**: Pre-built templates for common targeting
41+
patterns (elderly pension, female-headed households, etc.)
42+
- **Distribution Analysis**: Gini coefficient, Lorenz curve, percentile
43+
breakdown
44+
- **Fairness Analysis**: Disparity ratios across gender, disability,
45+
location with traffic-light status indicators
46+
- **Targeting Efficiency**: Confusion matrix, leakage rate,
47+
undercoverage against ideal populations
48+
- **Budget Simulation**: Fixed cap and proportional reduction strategies
49+
- **Scenario Comparison**: Side-by-side comparison of multiple targeting
50+
approaches with overlap analysis
51+
- **Custom Metrics**: Define CEL-based aggregate, coverage, and ratio
52+
metrics
5453

5554
Privacy
5655
-------
@@ -61,24 +60,23 @@ individual beneficiary records are persisted in simulation results.
6160
Models
6261
------
6362

64-
+----------------------------------+----------------------------------+
65-
| Model | Description |
66-
+==================================+==================================+
67-
| ``sp | Pre-built targeting scenario |
68-
| p.simulation.scenario.template`` | templates |
69-
+----------------------------------+----------------------------------+
70-
| ``spp.simulation.scenario`` | Targeting scenario definitions |
71-
+----------------------------------+----------------------------------+
72-
| ``s | Amount calculation rules |
73-
| pp.simulation.entitlement.rule`` | |
74-
+----------------------------------+----------------------------------+
75-
| ``spp.simulation.run`` | Aggregated simulation results |
76-
| | (non-deletable) |
77-
+----------------------------------+----------------------------------+
78-
| ``spp.simulation.comparison`` | Side-by-side run comparisons |
79-
+----------------------------------+----------------------------------+
80-
| ``spp.simulation.metric`` | Custom evaluation metrics |
81-
+----------------------------------+----------------------------------+
63+
+--------------------------------------+----------------------------------+
64+
| Model | Description |
65+
+======================================+==================================+
66+
| ``spp.simulation.scenario.template`` | Pre-built targeting scenario |
67+
| | templates |
68+
+--------------------------------------+----------------------------------+
69+
| ``spp.simulation.scenario`` | Targeting scenario definitions |
70+
+--------------------------------------+----------------------------------+
71+
| ``spp.simulation.entitlement.rule`` | Amount calculation rules |
72+
+--------------------------------------+----------------------------------+
73+
| ``spp.simulation.run`` | Aggregated simulation results |
74+
| | (non-deletable) |
75+
+--------------------------------------+----------------------------------+
76+
| ``spp.simulation.comparison`` | Side-by-side run comparisons |
77+
+--------------------------------------+----------------------------------+
78+
| ``spp.simulation.metric`` | Custom evaluation metrics |
79+
+--------------------------------------+----------------------------------+
8280

8381
Security Groups
8482
---------------
@@ -112,10 +110,10 @@ Templates / Custom Metrics
112110
Bug Tracker
113111
===========
114112

115-
Bugs are tracked on `GitHub Issues <https://github.com/OpenSPP/openspp-modules/issues>`_.
113+
Bugs are tracked on `GitHub Issues <https://github.com/OpenSPP/OpenSPP2/issues>`_.
116114
In case of trouble, please check there if your issue has already been reported.
117115
If you spotted it first, help us to smash it by providing a detailed and welcomed
118-
`feedback <https://github.com/OpenSPP/openspp-modules/issues/new?body=module:%20spp_simulation%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
116+
`feedback <https://github.com/OpenSPP/OpenSPP2/issues/new?body=module:%20spp_simulation%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
119117

120118
Do not contact contributors directly about support or help with technical issues.
121119

@@ -138,6 +136,6 @@ Current maintainer:
138136

139137
|maintainer-jeremi|
140138

141-
This module is part of the `OpenSPP/openspp-modules <https://github.com/OpenSPP/openspp-modules/tree/19.0/spp_simulation>`_ project on GitHub.
139+
This module is part of the `OpenSPP/OpenSPP2 <https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_simulation>`_ project on GitHub.
142140

143141
You are welcome to contribute.
Lines changed: 82 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,88 @@
1-
<?xml version="1.0" encoding="utf-8"?>
2-
<odoo>
3-
<data noupdate="1">
4-
<record id="template_elderly_pension" model="spp.simulation.scenario.template">
5-
<field name="name">Elderly Pension (Age 60+)</field>
6-
<field name="description">Target elderly individuals aged 60 and above for pension benefits.</field>
7-
<field name="category">age</field>
8-
<field name="target_type">individual</field>
9-
<field name="targeting_expression">age_years(r.birthdate) >= 60</field>
10-
<field name="default_amount">1000</field>
11-
<field name="default_amount_mode">fixed</field>
12-
<field name="icon">fa-hourglass-half</field>
13-
<field name="sequence">10</field>
14-
</record>
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo noupdate="1">
3+
<record id="template_elderly_pension" model="spp.simulation.scenario.template">
4+
<field name="name">Elderly Pension (Age 60+)</field>
5+
<field
6+
name="description"
7+
>Target elderly individuals aged 60 and above for pension benefits.</field>
8+
<field name="category">age</field>
9+
<field name="target_type">individual</field>
10+
<field name="targeting_expression">age_years(r.birthdate) >= 60</field>
11+
<field name="default_amount">1000</field>
12+
<field name="default_amount_mode">fixed</field>
13+
<field name="icon">fa-hourglass-half</field>
14+
<field name="sequence">10</field>
15+
</record>
1516

16-
<record id="template_children_under_5" model="spp.simulation.scenario.template">
17-
<field name="name">Households with Children Under 5</field>
18-
<field name="description">Target households that have at least one child under 5 years of age.</field>
19-
<field name="category">age</field>
20-
<field name="target_type">group</field>
21-
<field name="targeting_expression">members.any(m, age_years(m.birthdate) &lt; 5)</field>
22-
<field name="default_amount">500</field>
23-
<field name="default_amount_mode">fixed</field>
24-
<field name="icon">fa-child</field>
25-
<field name="sequence">20</field>
26-
</record>
17+
<record id="template_children_under_5" model="spp.simulation.scenario.template">
18+
<field name="name">Households with Children Under 5</field>
19+
<field
20+
name="description"
21+
>Target households that have at least one child under 5 years of age.</field>
22+
<field name="category">age</field>
23+
<field name="target_type">group</field>
24+
<field
25+
name="targeting_expression"
26+
>members.any(m, age_years(m.birthdate) &lt; 5)</field>
27+
<field name="default_amount">500</field>
28+
<field name="default_amount_mode">fixed</field>
29+
<field name="icon">fa-child</field>
30+
<field name="sequence">20</field>
31+
</record>
2732

28-
<record id="template_female_headed" model="spp.simulation.scenario.template">
29-
<field name="name">Female-Headed Households</field>
30-
<field name="description">Target households where the head of household is female.</field>
31-
<field name="category">vulnerability</field>
32-
<field name="target_type">group</field>
33-
<field name="targeting_expression">is_female(head.gender_id)</field>
34-
<field name="default_amount">750</field>
35-
<field name="default_amount_mode">fixed</field>
36-
<field name="icon">fa-female</field>
37-
<field name="sequence">30</field>
38-
</record>
33+
<record id="template_female_headed" model="spp.simulation.scenario.template">
34+
<field name="name">Female-Headed Households</field>
35+
<field
36+
name="description"
37+
>Target households where the head of household is female.</field>
38+
<field name="category">vulnerability</field>
39+
<field name="target_type">group</field>
40+
<field name="targeting_expression">is_female(head.gender_id)</field>
41+
<field name="default_amount">750</field>
42+
<field name="default_amount_mode">fixed</field>
43+
<field name="icon">fa-female</field>
44+
<field name="sequence">30</field>
45+
</record>
3946

40-
<record id="template_rural_households" model="spp.simulation.scenario.template">
41-
<field name="name">Rural Households</field>
42-
<field name="description">Target households located in rural areas.</field>
43-
<field name="category">geographic</field>
44-
<field name="target_type">group</field>
45-
<field name="targeting_expression">has_area_tag('RURAL')</field>
46-
<field name="default_amount">600</field>
47-
<field name="default_amount_mode">fixed</field>
48-
<field name="icon">fa-tree</field>
49-
<field name="sequence">40</field>
50-
</record>
47+
<record id="template_rural_households" model="spp.simulation.scenario.template">
48+
<field name="name">Rural Households</field>
49+
<field name="description">Target households located in rural areas.</field>
50+
<field name="category">geographic</field>
51+
<field name="target_type">group</field>
52+
<field name="targeting_expression">has_area_tag('RURAL')</field>
53+
<field name="default_amount">600</field>
54+
<field name="default_amount_mode">fixed</field>
55+
<field name="icon">fa-tree</field>
56+
<field name="sequence">40</field>
57+
</record>
5158

52-
<record id="template_disability_targeted" model="spp.simulation.scenario.template">
53-
<field name="name">Disability-Targeted</field>
54-
<field name="description">Target households with at least one member with a disability.</field>
55-
<field name="category">vulnerability</field>
56-
<field name="target_type">group</field>
57-
<field name="targeting_expression">members.any(m, m.disability_id != false)</field>
58-
<field name="default_amount">800</field>
59-
<field name="default_amount_mode">fixed</field>
60-
<field name="icon">fa-wheelchair</field>
61-
<field name="sequence">50</field>
62-
</record>
59+
<record id="template_disability_targeted" model="spp.simulation.scenario.template">
60+
<field name="name">Disability-Targeted</field>
61+
<field
62+
name="description"
63+
>Target households with at least one member with a disability.</field>
64+
<field name="category">vulnerability</field>
65+
<field name="target_type">group</field>
66+
<field
67+
name="targeting_expression"
68+
>members.any(m, m.disability_id != false)</field>
69+
<field name="default_amount">800</field>
70+
<field name="default_amount_mode">fixed</field>
71+
<field name="icon">fa-wheelchair</field>
72+
<field name="sequence">50</field>
73+
</record>
6374

64-
<record id="template_large_households" model="spp.simulation.scenario.template">
65-
<field name="name">Large Households (5+ Members)</field>
66-
<field name="description">Target households with 5 or more members. Amount scales with household size.</field>
67-
<field name="category">categorical</field>
68-
<field name="target_type">group</field>
69-
<field name="targeting_expression">size(members) >= 5</field>
70-
<field name="default_amount">200</field>
71-
<field name="default_amount_mode">multiplier</field>
72-
<field name="icon">fa-users</field>
73-
<field name="sequence">60</field>
74-
</record>
75-
</data>
75+
<record id="template_large_households" model="spp.simulation.scenario.template">
76+
<field name="name">Large Households (5+ Members)</field>
77+
<field
78+
name="description"
79+
>Target households with 5 or more members. Amount scales with household size.</field>
80+
<field name="category">categorical</field>
81+
<field name="target_type">group</field>
82+
<field name="targeting_expression">size(members) >= 5</field>
83+
<field name="default_amount">200</field>
84+
<field name="default_amount_mode">multiplier</field>
85+
<field name="icon">fa-users</field>
86+
<field name="sequence">60</field>
87+
</record>
7688
</odoo>

0 commit comments

Comments
 (0)