Skip to content

Commit 8b8d818

Browse files
committed
feat(spp_dci_demo,spp_mis_demo_v2): add Conditional Child Grant and demo household
- Add Masters household (Adam + Mary) as demo data for DCI CR flow - Hide Contact Information and Relationship fields in add-member form - Target Conditional Child Grant program in post_init_hook - Add Conditional Child Grant program with first-1,000-days eligibility - Add Health Visit event type for compliance tracking - Configure compliance manager with CEL expression support
1 parent 6390773 commit 8b8d818

8 files changed

Lines changed: 241 additions & 46 deletions

File tree

spp_dci_demo/__manifest__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"data/vocabulary_data.xml",
1818
"data/dci_data_source.xml",
1919
"data/system_parameters.xml",
20+
"data/demo_household.xml",
2021
"views/cr_detail_add_member_view.xml",
2122
"views/change_request_view.xml",
2223
],
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo noupdate="1">
3+
<!-- Masters Household for DCI demo: parent adds child via CR -->
4+
5+
<!-- Father -->
6+
<record id="partner_adam_masters" model="res.partner">
7+
<field name="name">MASTERS, Adam</field>
8+
<field name="given_name">Adam</field>
9+
<field name="family_name">Masters</field>
10+
<field name="birthdate">1995-08-14</field>
11+
<field name="gender_id" ref="spp_vocabulary.code_gender_male" />
12+
<field name="is_registrant" eval="True" />
13+
<field name="is_group" eval="False" />
14+
</record>
15+
16+
<!-- Mother -->
17+
<record id="partner_mary_masters" model="res.partner">
18+
<field name="name">MASTERS, Mary</field>
19+
<field name="given_name">Mary</field>
20+
<field name="family_name">Masters</field>
21+
<field name="birthdate">2002-02-01</field>
22+
<field name="gender_id" ref="spp_vocabulary.code_gender_female" />
23+
<field name="is_registrant" eval="True" />
24+
<field name="is_group" eval="False" />
25+
</record>
26+
27+
<!-- Household -->
28+
<record id="group_masters_household" model="res.partner">
29+
<field name="name">Masters Household</field>
30+
<field name="is_registrant" eval="True" />
31+
<field name="is_group" eval="True" />
32+
</record>
33+
34+
<!-- Memberships -->
35+
<record id="membership_adam_masters" model="spp.group.membership">
36+
<field name="group" ref="group_masters_household" />
37+
<field name="individual" ref="partner_adam_masters" />
38+
<field
39+
name="membership_type_ids"
40+
eval="[(4, ref('spp_vocabulary.code_membership_type_head'))]"
41+
/>
42+
</record>
43+
44+
<record id="membership_mary_masters" model="spp.group.membership">
45+
<field name="group" ref="group_masters_household" />
46+
<field name="individual" ref="partner_mary_masters" />
47+
</record>
48+
</odoo>

spp_dci_demo/hooks.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ def post_init_hook(env):
1818
_logger.info("spp.program model not available, skipping enrollment program setup")
1919
return
2020

21-
# Find the first program
22-
program = env["spp.program"].search([], limit=1)
21+
# Find the Conditional Child Grant program (the target for DCI demo enrollment)
22+
program = env["spp.program"].search([("name", "=", "Conditional Child Grant")], limit=1)
23+
if not program:
24+
# Fall back to any program if not found
25+
program = env["spp.program"].search([], limit=1)
2326
if not program:
2427
_logger.info("No programs found, enrollment_program_id not configured")
2528
return

spp_dci_demo/views/cr_detail_add_member_view.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@
99
ref="spp_change_request_v2.spp_cr_detail_add_member_form"
1010
/>
1111
<field name="arch" type="xml">
12+
<!-- Hide Contact Information section for demo -->
13+
<xpath
14+
expr="//field[@name='phone']/parent::group/parent::group"
15+
position="attributes"
16+
>
17+
<attribute name="invisible">1</attribute>
18+
</xpath>
19+
20+
<!-- Hide Relationship to Head for demo -->
21+
<xpath expr="//field[@name='relationship_id']" position="attributes">
22+
<attribute name="invisible">1</attribute>
23+
</xpath>
24+
1225
<!-- Add Birth Verification section before the Result group -->
1326
<xpath expr="//field[@name='created_individual_id']/.." position="before">
1427
<group string="Birth Verification" name="birth_verification">

spp_mis_demo_v2/data/event_types.xml

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,26 @@
2020
<!-- EVENT TYPE DEFINITIONS -->
2121
<!-- ═══════════════════════════════════════════════════════════════════════ -->
2222

23+
<!-- Health Visit Event Type (compliance tracking) -->
24+
<record id="event_type_health_visit" model="spp.event.type">
25+
<field name="name">Health Visit</field>
26+
<field name="code">health_visit</field>
27+
<field
28+
name="description"
29+
>Health checkup visits for children under 5, required for Conditional Child Grant compliance. Tracks immunization and growth monitoring.</field>
30+
<field name="category">visit</field>
31+
<field name="target_type">both</field>
32+
<field name="source_type">internal</field>
33+
<field name="sequence">5</field>
34+
</record>
35+
2336
<!-- Training Event Type -->
2437
<record id="event_type_training" model="spp.event.type">
2538
<field name="name">Training Session</field>
2639
<field name="code">training</field>
27-
<field name="description">Training sessions for beneficiaries including agricultural practices, financial literacy, and program orientation.</field>
40+
<field
41+
name="description"
42+
>Training sessions for beneficiaries including agricultural practices, financial literacy, and program orientation.</field>
2843
<field name="category">visit</field>
2944
<field name="target_type">both</field>
3045
<field name="source_type">internal</field>
@@ -35,7 +50,9 @@
3550
<record id="event_type_extension_visit" model="spp.event.type">
3651
<field name="name">Extension Visit</field>
3752
<field name="code">extension_visit</field>
38-
<field name="description">Field extension visits by agricultural officers to provide technical assistance and monitor progress.</field>
53+
<field
54+
name="description"
55+
>Field extension visits by agricultural officers to provide technical assistance and monitor progress.</field>
3956
<field name="category">visit</field>
4057
<field name="target_type">both</field>
4158
<field name="source_type">internal</field>
@@ -46,7 +63,9 @@
4663
<record id="event_type_verification" model="spp.event.type">
4764
<field name="name">Verification Visit</field>
4865
<field name="code">verification</field>
49-
<field name="description">Field verification visits to confirm eligibility and registration information.</field>
66+
<field
67+
name="description"
68+
>Field verification visits to confirm eligibility and registration information.</field>
5069
<field name="category">visit</field>
5170
<field name="target_type">both</field>
5271
<field name="source_type">internal</field>
@@ -57,7 +76,9 @@
5776
<record id="event_type_vulnerability_assessment" model="spp.event.type">
5877
<field name="name">Vulnerability Assessment</field>
5978
<field name="code">vulnerability_assessment</field>
60-
<field name="description">Assessment to determine vulnerability level and eligibility for targeted programs.</field>
79+
<field
80+
name="description"
81+
>Assessment to determine vulnerability level and eligibility for targeted programs.</field>
6182
<field name="category">survey</field>
6283
<field name="target_type">both</field>
6384
<field name="source_type">odk</field>
@@ -82,7 +103,7 @@
82103

83104
<!-- Direct mapping: Registrant ID -->
84105
<record id="mapping_vuln_registrant_id" model="spp.event.type.mapping">
85-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
106+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
86107
<field name="sequence">10</field>
87108
<field name="external_field">beneficiary_id</field>
88109
<field name="internal_field">registrant_id</field>
@@ -91,7 +112,7 @@
91112

92113
<!-- Date parsing: Assessment date -->
93114
<record id="mapping_vuln_assessment_date" model="spp.event.type.mapping">
94-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
115+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
95116
<field name="sequence">20</field>
96117
<field name="external_field">survey_date</field>
97118
<field name="internal_field">event_date</field>
@@ -102,39 +123,49 @@
102123
Formula: (income_score * 0.3) + (housing_score * 0.25) + (health_score * 0.25) + (education_score * 0.2)
103124
Demonstrates: arithmetic operations, weighted averages -->
104125
<record id="mapping_vuln_score_calculated" model="spp.event.type.mapping">
105-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
126+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
106127
<field name="sequence">30</field>
107-
<field name="external_field">income_score,housing_score,health_score,education_score</field>
128+
<field
129+
name="external_field"
130+
>income_score,housing_score,health_score,education_score</field>
108131
<field name="internal_field">vulnerability_score</field>
109132
<field name="transform">expression</field>
110-
<field name="transform_expression">(int(income_score) * 0.3) + (int(housing_score) * 0.25) + (int(health_score) * 0.25) + (int(education_score) * 0.2)</field>
133+
<field
134+
name="transform_expression"
135+
>(int(income_score) * 0.3) + (int(housing_score) * 0.25) + (int(health_score) * 0.25) + (int(education_score) * 0.2)</field>
111136
</record>
112137

113138
<!-- CEL Expression: Determine vulnerability category based on score
114139
Demonstrates: conditional expressions (ternary), threshold comparisons -->
115140
<record id="mapping_vuln_category" model="spp.event.type.mapping">
116-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
141+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
117142
<field name="sequence">40</field>
118143
<field name="external_field">vulnerability_score</field>
119144
<field name="internal_field">vulnerability_category</field>
120145
<field name="transform">expression</field>
121-
<field name="transform_expression">int(vulnerability_score) >= 75 ? 'critical' : (int(vulnerability_score) >= 50 ? 'high' : (int(vulnerability_score) >= 25 ? 'medium' : 'low'))</field>
146+
<field
147+
name="transform_expression"
148+
>int(vulnerability_score) >= 75 ? 'critical' : (int(vulnerability_score) >= 50 ? 'high' : (int(vulnerability_score) >= 25 ? 'medium' : 'low'))</field>
122149
</record>
123150

124151
<!-- CEL Expression: Check program eligibility based on multiple criteria
125152
Demonstrates: boolean logic, compound conditions -->
126153
<record id="mapping_vuln_eligibility" model="spp.event.type.mapping">
127-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
154+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
128155
<field name="sequence">50</field>
129-
<field name="external_field">vulnerability_score,household_size,has_children</field>
156+
<field
157+
name="external_field"
158+
>vulnerability_score,household_size,has_children</field>
130159
<field name="internal_field">is_eligible</field>
131160
<field name="transform">expression</field>
132-
<field name="transform_expression">(int(vulnerability_score) >= 50) || (int(household_size) >= 5 &amp;&amp; has_children == 'yes')</field>
161+
<field
162+
name="transform_expression"
163+
>(int(vulnerability_score) >= 50) || (int(household_size) >= 5 &amp;&amp; has_children == 'yes')</field>
133164
</record>
134165

135166
<!-- Direct mapping: Assessor notes -->
136167
<record id="mapping_vuln_notes" model="spp.event.type.mapping">
137-
<field name="event_type_id" ref="event_type_vulnerability_assessment"/>
168+
<field name="event_type_id" ref="event_type_vulnerability_assessment" />
138169
<field name="sequence">60</field>
139170
<field name="external_field">assessor_notes</field>
140171
<field name="internal_field">notes</field>
@@ -149,7 +180,7 @@
149180

150181
<!-- Direct mapping: Training topic -->
151182
<record id="mapping_training_topic" model="spp.event.type.mapping">
152-
<field name="event_type_id" ref="event_type_training"/>
183+
<field name="event_type_id" ref="event_type_training" />
153184
<field name="sequence">10</field>
154185
<field name="external_field">training_topic</field>
155186
<field name="internal_field">topic</field>
@@ -159,23 +190,29 @@
159190
<!-- CEL Expression: Calculate training completion score
160191
Demonstrates: attendance weighting, score normalization -->
161192
<record id="mapping_training_score" model="spp.event.type.mapping">
162-
<field name="event_type_id" ref="event_type_training"/>
193+
<field name="event_type_id" ref="event_type_training" />
163194
<field name="sequence">20</field>
164-
<field name="external_field">pre_test_score,post_test_score,attendance_days,total_days</field>
195+
<field
196+
name="external_field"
197+
>pre_test_score,post_test_score,attendance_days,total_days</field>
165198
<field name="internal_field">completion_score</field>
166199
<field name="transform">expression</field>
167-
<field name="transform_expression">((int(post_test_score) - int(pre_test_score)) * 0.6) + ((int(attendance_days) / int(total_days)) * 40.0)</field>
200+
<field
201+
name="transform_expression"
202+
>((int(post_test_score) - int(pre_test_score)) * 0.6) + ((int(attendance_days) / int(total_days)) * 40.0)</field>
168203
</record>
169204

170205
<!-- CEL Expression: Determine if participant passed training
171206
Demonstrates: threshold check with multiple conditions -->
172207
<record id="mapping_training_passed" model="spp.event.type.mapping">
173-
<field name="event_type_id" ref="event_type_training"/>
208+
<field name="event_type_id" ref="event_type_training" />
174209
<field name="sequence">30</field>
175210
<field name="external_field">post_test_score,attendance_days,total_days</field>
176211
<field name="internal_field">is_passed</field>
177212
<field name="transform">expression</field>
178-
<field name="transform_expression">int(post_test_score) >= 60 &amp;&amp; (int(attendance_days) / int(total_days)) >= 0.8</field>
213+
<field
214+
name="transform_expression"
215+
>int(post_test_score) >= 60 &amp;&amp; (int(attendance_days) / int(total_days)) >= 0.8</field>
179216
</record>
180217

181218
<!--
@@ -187,23 +224,31 @@
187224
<!-- CEL Expression: Calculate visit quality score
188225
Based on: completeness of data, farm conditions, recommendations made -->
189226
<record id="mapping_extension_quality" model="spp.event.type.mapping">
190-
<field name="event_type_id" ref="event_type_extension_visit"/>
227+
<field name="event_type_id" ref="event_type_extension_visit" />
191228
<field name="sequence">10</field>
192-
<field name="external_field">data_completeness,farm_condition_score,recommendations_count</field>
229+
<field
230+
name="external_field"
231+
>data_completeness,farm_condition_score,recommendations_count</field>
193232
<field name="internal_field">visit_quality_score</field>
194233
<field name="transform">expression</field>
195-
<field name="transform_expression">(int(data_completeness) * 0.4) + (int(farm_condition_score) * 0.4) + (int(recommendations_count) * 2.0)</field>
234+
<field
235+
name="transform_expression"
236+
>(int(data_completeness) * 0.4) + (int(farm_condition_score) * 0.4) + (int(recommendations_count) * 2.0)</field>
196237
</record>
197238

198239
<!-- CEL Expression: Determine if follow-up visit needed
199240
Demonstrates: complex boolean logic for decision making -->
200241
<record id="mapping_extension_followup" model="spp.event.type.mapping">
201-
<field name="event_type_id" ref="event_type_extension_visit"/>
242+
<field name="event_type_id" ref="event_type_extension_visit" />
202243
<field name="sequence">20</field>
203-
<field name="external_field">farm_condition_score,issues_identified,recommendations_count</field>
244+
<field
245+
name="external_field"
246+
>farm_condition_score,issues_identified,recommendations_count</field>
204247
<field name="internal_field">needs_followup</field>
205248
<field name="transform">expression</field>
206-
<field name="transform_expression">int(farm_condition_score) &lt; 50 || int(issues_identified) > 3 || int(recommendations_count) > 5</field>
249+
<field
250+
name="transform_expression"
251+
>int(farm_condition_score) &lt; 50 || int(issues_identified) > 3 || int(recommendations_count) > 5</field>
207252
</record>
208253

209254
<!--
@@ -215,23 +260,28 @@
215260
<!-- CEL Expression: Calculate verification confidence score
216261
Based on: document verification, interview score, observation score -->
217262
<record id="mapping_verification_confidence" model="spp.event.type.mapping">
218-
<field name="event_type_id" ref="event_type_verification"/>
263+
<field name="event_type_id" ref="event_type_verification" />
219264
<field name="sequence">10</field>
220-
<field name="external_field">document_score,interview_score,observation_score</field>
265+
<field
266+
name="external_field"
267+
>document_score,interview_score,observation_score</field>
221268
<field name="internal_field">confidence_score</field>
222269
<field name="transform">expression</field>
223-
<field name="transform_expression">(int(document_score) * 0.4) + (int(interview_score) * 0.35) + (int(observation_score) * 0.25)</field>
270+
<field
271+
name="transform_expression"
272+
>(int(document_score) * 0.4) + (int(interview_score) * 0.35) + (int(observation_score) * 0.25)</field>
224273
</record>
225274

226275
<!-- CEL Expression: Determine verification status
227276
Demonstrates: multi-level conditional -->
228277
<record id="mapping_verification_status" model="spp.event.type.mapping">
229-
<field name="event_type_id" ref="event_type_verification"/>
278+
<field name="event_type_id" ref="event_type_verification" />
230279
<field name="sequence">20</field>
231280
<field name="external_field">confidence_score,discrepancies_found</field>
232281
<field name="internal_field">verification_status</field>
233282
<field name="transform">expression</field>
234-
<field name="transform_expression">int(discrepancies_found) > 2 ? 'rejected' : (int(confidence_score) >= 80 ? 'verified' : 'pending_review')</field>
283+
<field
284+
name="transform_expression"
285+
>int(discrepancies_found) > 2 ? 'rejected' : (int(confidence_score) >= 80 ? 'verified' : 'pending_review')</field>
235286
</record>
236-
237287
</odoo>

0 commit comments

Comments
 (0)