Skip to content

Commit fbb2baf

Browse files
committed
feat(spp_mis_demo_v2): add demo API client and statistics data
Add demo data files for API testing and statistics indicators: - demo_api_client.xml: pre-configured QGIS API client with GIS scopes - demo_statistics.xml: 9 CEL variables + statistics for GIS/dashboard - test_demo_statistics.py: tests for statistics loading and aggregation Add spp_statistic, spp_aggregation, spp_studio as dependencies.
1 parent a72ada0 commit fbb2baf

File tree

5 files changed

+478
-0
lines changed

5 files changed

+478
-0
lines changed

spp_mis_demo_v2/__manifest__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
"spp_demo",
2121
# GIS Reports for geographic visualization
2222
"spp_gis_report",
23+
# Statistics and aggregation for demo indicators
24+
"spp_statistic",
25+
"spp_aggregation",
26+
"spp_studio",
2327
# QR Credentials (Claim 169)
2428
"spp_claim_169",
2529
# Demo-specific extensions
@@ -38,6 +42,8 @@
3842
"data/change_request_types.xml",
3943
"data/demo_change_requests_ux.xml",
4044
"data/demo_gis_reports.xml",
45+
"data/demo_statistics.xml",
46+
"data/demo_api_client.xml",
4147
"views/mis_demo_wizard_view.xml",
4248
],
4349
"assets": {},
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!--
3+
Demo API Client for QGIS Plugin Testing
4+
5+
This creates a pre-configured API client with GIS scopes for testing
6+
the QGIS plugin integration. The client_secret is displayed in the UI
7+
after installation - use it to configure the QGIS plugin.
8+
9+
Scopes granted:
10+
- gis:read - View layers, catalog, and query statistics
11+
- gis:all - Full GIS access including geofence management
12+
13+
IMPORTANT: This is demo data for testing only. In production,
14+
create API clients through the UI with proper access controls.
15+
-->
16+
<odoo>
17+
<data noupdate="1">
18+
<!-- Demo API Client for QGIS Plugin -->
19+
<record id="demo_api_client_qgis" model="spp.api.client">
20+
<field name="name">QGIS Demo Client</field>
21+
<field
22+
name="description"
23+
>Demo API client for testing QGIS plugin integration. Grants read access to GIS layers, reports, and statistics queries.</field>
24+
<field name="partner_id" ref="base.main_partner" />
25+
<field name="organization_type_id" ref="spp_consent.org_type_government" />
26+
<field name="active" eval="True" />
27+
</record>
28+
29+
<!-- GIS Read Scope - View layers, catalog, statistics -->
30+
<record id="demo_api_client_qgis_scope_gis_read" model="spp.api.client.scope">
31+
<field name="client_id" ref="demo_api_client_qgis" />
32+
<field name="resource">gis</field>
33+
<field name="action">read</field>
34+
<field
35+
name="description"
36+
>Read access to GIS layers, reports catalog, and spatial statistics queries.</field>
37+
</record>
38+
39+
<!-- GIS All Scope - Full GIS access including geofences -->
40+
<record id="demo_api_client_qgis_scope_gis_all" model="spp.api.client.scope">
41+
<field name="client_id" ref="demo_api_client_qgis" />
42+
<field name="resource">gis</field>
43+
<field name="action">all</field>
44+
<field
45+
name="description"
46+
>Full GIS access including creating and managing geofences.</field>
47+
</record>
48+
</data>
49+
</odoo>
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!--
3+
Demo Statistics for GIS and Dashboard
4+
5+
This file creates:
6+
1. CEL variables that define the computation logic
7+
2. Statistics (spp.statistic) that publish those variables to GIS/dashboards
8+
9+
The separation allows the same underlying variable to be published
10+
to multiple contexts with different presentation settings.
11+
-->
12+
<odoo noupdate="0">
13+
<!-- ═══════════════════════════════════════════════════════════════════════
14+
CEL VARIABLES - Define the computation logic
15+
═══════════════════════════════════════════════════════════════════════ -->
16+
17+
<!-- Total Members - Aggregate count of all members -->
18+
<record id="cel_var_total_members" model="spp.cel.variable">
19+
<field name="name">demo_total_members</field>
20+
<field name="cel_accessor">total_members</field>
21+
<field name="source_type">aggregate</field>
22+
<field name="aggregate_type">count</field>
23+
<field name="aggregate_target">members</field>
24+
<field name="aggregate_filter">true</field>
25+
<field name="value_type">number</field>
26+
<field name="applies_to">group</field>
27+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
28+
<field name="state">active</field>
29+
<field name="sequence">10</field>
30+
</record>
31+
32+
<!-- Children Under 5: use spp_studio.var_children_under_5 (same cel_accessor + applies_to) -->
33+
34+
<!-- Children Under 18 -->
35+
<record id="cel_var_children_under_18" model="spp.cel.variable">
36+
<field name="name">demo_children_under_18</field>
37+
<field name="cel_accessor">children_under_18</field>
38+
<field name="source_type">aggregate</field>
39+
<field name="aggregate_type">count</field>
40+
<field name="aggregate_target">members</field>
41+
<field name="aggregate_filter">age_years(m.birthdate) &lt; 18</field>
42+
<field name="value_type">number</field>
43+
<field name="applies_to">group</field>
44+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
45+
<field name="state">active</field>
46+
<field name="sequence">30</field>
47+
</record>
48+
49+
<!-- Elderly 60+ -->
50+
<record id="cel_var_elderly_60_plus" model="spp.cel.variable">
51+
<field name="name">demo_elderly_60_plus</field>
52+
<field name="cel_accessor">elderly_60_plus</field>
53+
<field name="source_type">aggregate</field>
54+
<field name="aggregate_type">count</field>
55+
<field name="aggregate_target">members</field>
56+
<field name="aggregate_filter">age_years(m.birthdate) >= 60</field>
57+
<field name="value_type">number</field>
58+
<field name="applies_to">group</field>
59+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
60+
<field name="state">active</field>
61+
<field name="sequence">40</field>
62+
</record>
63+
64+
<!-- Disabled Members -->
65+
<record id="cel_var_disabled_members" model="spp.cel.variable">
66+
<field name="name">demo_disabled_members</field>
67+
<field name="cel_accessor">disabled_members</field>
68+
<field name="source_type">aggregate</field>
69+
<field name="aggregate_type">count</field>
70+
<field name="aggregate_target">members</field>
71+
<field name="aggregate_filter">m.disabled != null</field>
72+
<field name="value_type">number</field>
73+
<field name="applies_to">group</field>
74+
<field name="category_id" ref="spp_studio.variable_category_characteristics" />
75+
<field name="state">active</field>
76+
<field name="sequence">50</field>
77+
</record>
78+
79+
<!-- Female Members -->
80+
<record id="cel_var_female_members" model="spp.cel.variable">
81+
<field name="name">demo_female_members</field>
82+
<field name="cel_accessor">female_members</field>
83+
<field name="source_type">aggregate</field>
84+
<field name="aggregate_type">count</field>
85+
<field name="aggregate_target">members</field>
86+
<field name="aggregate_filter">is_female(m.gender_id)</field>
87+
<field name="value_type">number</field>
88+
<field name="applies_to">group</field>
89+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
90+
<field name="state">active</field>
91+
<field name="sequence">45</field>
92+
</record>
93+
94+
<!-- Male Members -->
95+
<record id="cel_var_male_members" model="spp.cel.variable">
96+
<field name="name">demo_male_members</field>
97+
<field name="cel_accessor">male_members</field>
98+
<field name="source_type">aggregate</field>
99+
<field name="aggregate_type">count</field>
100+
<field name="aggregate_target">members</field>
101+
<field name="aggregate_filter">is_male(m.gender_id)</field>
102+
<field name="value_type">number</field>
103+
<field name="applies_to">group</field>
104+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
105+
<field name="state">active</field>
106+
<field name="sequence">46</field>
107+
</record>
108+
109+
<!-- Total Households (computed - returns true for counting) -->
110+
<record id="cel_var_total_households" model="spp.cel.variable">
111+
<field name="name">demo_total_households</field>
112+
<field name="cel_accessor">total_households</field>
113+
<field name="source_type">computed</field>
114+
<field name="cel_expression">true</field>
115+
<field name="value_type">number</field>
116+
<field name="applies_to">group</field>
117+
<field name="category_id" ref="spp_studio.variable_category_demographics" />
118+
<field name="state">active</field>
119+
<field name="sequence">5</field>
120+
</record>
121+
122+
<!-- Program Enrollment (queries spp.program.membership via CEL enrollments symbol) -->
123+
<record id="cel_var_enrolled_any_program" model="spp.cel.variable">
124+
<field name="name">demo_enrolled_any_program</field>
125+
<field name="cel_accessor">enrolled_any_program</field>
126+
<field name="source_type">computed</field>
127+
<field name="cel_expression">enrollments.exists(true)</field>
128+
<field name="value_type">number</field>
129+
<field name="applies_to">group</field>
130+
<field name="category_id" ref="spp_studio.variable_category_program" />
131+
<field name="state">active</field>
132+
<field name="sequence">60</field>
133+
</record>
134+
135+
<!-- ═══════════════════════════════════════════════════════════════════════
136+
STATISTICS - Publish variables to GIS, dashboards, etc.
137+
═══════════════════════════════════════════════════════════════════════ -->
138+
139+
<!-- Total Households -->
140+
<record id="stat_total_households" model="spp.statistic">
141+
<field name="name">total_households</field>
142+
<field name="label">Total Households</field>
143+
<field name="description">Count of household groups in the selected area</field>
144+
<field name="variable_id" ref="cel_var_total_households" />
145+
<field name="format">count</field>
146+
<field name="unit">households</field>
147+
<field name="category_id" ref="spp_statistic.category_demographics" />
148+
<field name="sequence">10</field>
149+
<field name="is_published_gis" eval="True" />
150+
<field name="is_published_dashboard" eval="True" />
151+
<field name="is_published_api" eval="True" />
152+
</record>
153+
154+
<!-- Total Members -->
155+
<record id="stat_total_members" model="spp.statistic">
156+
<field name="name">total_members</field>
157+
<field name="label">Total Members</field>
158+
<field name="description">Total count of individual household members</field>
159+
<field name="variable_id" ref="cel_var_total_members" />
160+
<field name="format">count</field>
161+
<field name="unit">people</field>
162+
<field name="category_id" ref="spp_statistic.category_demographics" />
163+
<field name="sequence">15</field>
164+
<field name="is_published_gis" eval="True" />
165+
<field name="is_published_dashboard" eval="True" />
166+
</record>
167+
168+
<!-- Children Under 5 -->
169+
<record id="stat_children_under_5" model="spp.statistic">
170+
<field name="name">children_under_5</field>
171+
<field name="label">Children Under 5</field>
172+
<field name="description">Count of children under 5 years old</field>
173+
<field name="variable_id" ref="spp_studio.var_children_under_5" />
174+
<field name="format">count</field>
175+
<field name="unit">children</field>
176+
<field name="category_id" ref="spp_statistic.category_demographics" />
177+
<field name="sequence">20</field>
178+
<field name="is_published_gis" eval="True" />
179+
<field name="is_published_dashboard" eval="True" />
180+
</record>
181+
182+
<!-- Children Under 18 -->
183+
<record id="stat_children_under_18" model="spp.statistic">
184+
<field name="name">children_under_18</field>
185+
<field name="label">Children Under 18</field>
186+
<field name="description">Count of children under 18 years old</field>
187+
<field name="variable_id" ref="cel_var_children_under_18" />
188+
<field name="format">count</field>
189+
<field name="unit">children</field>
190+
<field name="category_id" ref="spp_statistic.category_demographics" />
191+
<field name="sequence">30</field>
192+
<field name="is_published_gis" eval="True" />
193+
<field name="is_published_dashboard" eval="True" />
194+
</record>
195+
196+
<!-- Elderly 60+ -->
197+
<record id="stat_elderly_60_plus" model="spp.statistic">
198+
<field name="name">elderly_60_plus</field>
199+
<field name="label">Elderly (60+)</field>
200+
<field name="description">Count of elderly persons aged 60 and above</field>
201+
<field name="variable_id" ref="cel_var_elderly_60_plus" />
202+
<field name="format">count</field>
203+
<field name="unit">people</field>
204+
<field name="category_id" ref="spp_statistic.category_demographics" />
205+
<field name="sequence">40</field>
206+
<field name="is_published_gis" eval="True" />
207+
<field name="is_published_dashboard" eval="True" />
208+
</record>
209+
210+
<!-- Female Members -->
211+
<record id="stat_female_members" model="spp.statistic">
212+
<field name="name">female_members</field>
213+
<field name="label">Female Members</field>
214+
<field name="description">Count of female household members</field>
215+
<field name="variable_id" ref="cel_var_female_members" />
216+
<field name="format">count</field>
217+
<field name="unit">people</field>
218+
<field name="category_id" ref="spp_statistic.category_demographics" />
219+
<field name="sequence">45</field>
220+
<field name="is_published_gis" eval="True" />
221+
<field name="is_published_dashboard" eval="True" />
222+
</record>
223+
224+
<!-- Male Members -->
225+
<record id="stat_male_members" model="spp.statistic">
226+
<field name="name">male_members</field>
227+
<field name="label">Male Members</field>
228+
<field name="description">Count of male household members</field>
229+
<field name="variable_id" ref="cel_var_male_members" />
230+
<field name="format">count</field>
231+
<field name="unit">people</field>
232+
<field name="category_id" ref="spp_statistic.category_demographics" />
233+
<field name="sequence">46</field>
234+
<field name="is_published_gis" eval="True" />
235+
<field name="is_published_dashboard" eval="True" />
236+
</record>
237+
238+
<!-- Disabled Members -->
239+
<record id="stat_disabled_members" model="spp.statistic">
240+
<field name="name">disabled_members</field>
241+
<field name="label">Disabled Members</field>
242+
<field name="description">Count of household members with disabilities</field>
243+
<field name="variable_id" ref="cel_var_disabled_members" />
244+
<field name="format">count</field>
245+
<field name="unit">people</field>
246+
<field name="category_id" ref="spp_statistic.category_vulnerability" />
247+
<field name="sequence">50</field>
248+
<field name="is_published_gis" eval="True" />
249+
<field name="is_published_dashboard" eval="True" />
250+
</record>
251+
252+
<!-- Program Enrollment -->
253+
<record id="stat_enrolled_any_program" model="spp.statistic">
254+
<field name="name">enrolled_any_program</field>
255+
<field name="label">Enrolled (Any Program)</field>
256+
<field
257+
name="description"
258+
>Count of households enrolled in at least one program</field>
259+
<field name="variable_id" ref="cel_var_enrolled_any_program" />
260+
<field name="format">count</field>
261+
<field name="unit">households</field>
262+
<field name="category_id" ref="spp_statistic.category_programs" />
263+
<field name="sequence">60</field>
264+
<field name="is_published_gis" eval="True" />
265+
<field name="is_published_dashboard" eval="True" />
266+
</record>
267+
</odoo>

spp_mis_demo_v2/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
from . import test_formula_configuration
99
from . import test_mis_demo_generator
1010
from . import test_registry_variables
11+
from . import test_demo_statistics

0 commit comments

Comments
 (0)