Data model
Contents
Data model#
For: developers
This page describes the core data entities in OpenSPP and how they relate to each other. Understanding these models is essential for building modules that interact with the registry, programs, or entitlements.
Registrants#
OpenSPP does not define its own registrant model from scratch. Instead, it extends Odoo's built-in res.partner model using _inherit. This means all registrant data lives in the res_partner table alongside regular Odoo contacts.
Individuals and groups#
Both individuals and groups are res.partner records, distinguished by flags:
Field |
Individual |
Group |
|---|---|---|
|
|
|
|
|
|
Individual fields (defined in spp_registry/models/individual.py):
Field |
Type |
Description |
|---|---|---|
|
Char |
Last name |
|
Char |
First name |
|
Char |
Additional/middle name |
|
Date |
Date of birth |
|
Selection |
Gender |
|
Char |
Place of birth |
Group fields (defined in spp_registry/models/group.py):
Field |
Type |
Description |
|---|---|---|
|
Many2one |
Reference to group type vocabulary |
|
Many2one |
Group kind (deprecated, use group_type_id) |
Group membership#
The link between individuals and groups is managed by spp.group.membership:
Field |
Type |
Description |
|---|---|---|
|
Many2one ( |
The group |
|
Many2one ( |
The individual member |
|
Many2many |
Membership roles (head of household, spouse, etc.) |
|
Date |
When membership began |
|
Date |
When membership ended (if applicable) |
Identifiers#
Registrants can have multiple IDs (national ID, passport, etc.) stored in spp.registry.id:
Field |
Type |
Description |
|---|---|---|
|
Many2one ( |
The registrant |
|
Many2one ( |
Type of ID (e.g., national ID, passport) |
|
Char |
The ID number |
|
Date |
Expiration date |
ID types (spp.id.type) support namespace URIs for interoperability (e.g., urn:gov:ph:psa:philsys for Philippines PhilSys IDs), enabling cross-system identifier matching.
Relationships#
Registrants can have relationships with each other via spp.registry.relationship:
Field |
Type |
Description |
|---|---|---|
|
Many2one ( |
Source registrant |
|
Many2one ( |
Related registrant |
|
Many2one ( |
Relationship type |
Programs#
Programs are the central entity for social protection delivery. A program manages the full lifecycle from enrollment to payment.
Program model (spp.program)#
Key fields:
Field |
Type |
Description |
|---|---|---|
|
Char |
Program name |
|
Selection |
|
|
Selection |
|
|
One2many |
Enrolled beneficiaries |
|
One2many |
Program cycles |
Managers (configuration)#
Each program has managers that encapsulate domain logic. Instead of hardcoding business rules, programs delegate decisions to pluggable managers using the strategy pattern. Each manager type handles a specific concern:
Field |
Manager type |
Purpose |
|---|---|---|
|
Eligibility |
Who qualifies for the program |
|
Cycle |
How cycles are created and managed |
|
Entitlement |
What beneficiaries receive |
|
Payment |
How payments are processed |
|
Program |
Program lifecycle management |
|
Deduplication |
Duplicate detection |
|
Notification |
Beneficiary communications |
Managers are linked to programs via Many2many fields. Each slot uses a wrapper/implementation model pattern that allows different implementation types (e.g., cash vs. in-kind entitlements) through a single reference field. See Custom program managers for a full explanation of the manager pattern and how to build custom managers.
Program membership (spp.program.membership)#
Links registrants to programs:
Field |
Type |
Description |
|---|---|---|
|
Many2one ( |
The beneficiary |
|
Many2one ( |
The program |
|
Selection |
|
|
Date |
When enrolled |
|
Date |
When exited (if applicable) |
Cycles#
Cycles represent distribution periods within a program (e.g., monthly, quarterly).
Cycle model (spp.cycle)#
Field |
Type |
Description |
|---|---|---|
|
Char |
Cycle name |
|
Many2one ( |
Parent program |
|
Selection |
|
|
Date |
Cycle start |
|
Date |
Cycle end |
|
One2many |
Beneficiaries in this cycle |
Entitlements#
Entitlements represent what a beneficiary receives in a given cycle.
Entitlement model (spp.entitlement)#
Field |
Type |
Description |
|---|---|---|
|
Many2one ( |
The beneficiary |
|
Many2one ( |
The cycle |
|
Selection |
|
|
Float |
Calculated entitlement amount |
Program lifecycle#
Understanding how programs, cycles, and entitlements move through their states is essential for developers extending the system. Here is the end-to-end flow:
1. Program setup#
spp.program: active
A program is created and configured with managers (eligibility, entitlement, cycle, payment). Programs start in active state.
2. Beneficiary enrollment#
Program.import_eligible_registrants() → creates memberships in "draft"
Program.enroll_eligible_registrants() → moves memberships to "enrolled"
Program.verify_eligibility() → re-checks enrolled members, removes ineligible
Membership state |
Meaning |
|---|---|
|
Imported but not yet enrolled |
|
Actively participating |
|
Temporarily suspended |
|
Left the program |
|
Failed eligibility check |
|
Identified as duplicate |
3. Cycle creation and processing#
Program.create_new_cycle() → new cycle in "draft"
Cycle.copy_beneficiaries_from_program() → copies enrolled members into cycle
Cycle.prepare_entitlement() → creates entitlements via entitlement manager
Cycle (button: "To Approve") → cycle moves to "to_approve"
Cycle.approve() / CycleManager.approve_cycle() → cycle moves to "approved"
Cycle.validate_entitlement() → entitlements move to "pending_validation"
Cycle state |
Meaning |
|---|---|
|
Newly created, being prepared |
|
Submitted for approval |
|
Approved, entitlements can be validated |
|
Payments completed |
|
Cancelled |
|
Cycle period ended |
4. Entitlement approval and payment#
Entitlement.approve_entitlement() → moves to "approved"
(Payment manager processes payment) → moves to "trans2FSP" then "rdpd2ben"
Entitlement state |
Meaning |
|---|---|
|
Created by entitlement manager |
|
Awaiting approval |
|
Approved for payment |
|
Transferred to financial service provider |
|
Redeemed/paid to beneficiary |
|
Rejected (multiple reasons) |
|
Cancelled |
Flow summary#
Program (active)
|
+-- import_eligible_registrants() → Memberships (draft)
+-- enroll_eligible_registrants() → Memberships (enrolled)
|
+-- create_new_cycle() → Cycle (draft)
|
+-- copy_beneficiaries_from_program()
+-- prepare_entitlement() → Entitlements (draft)
+-- "To Approve" → Cycle (to_approve)
+-- approve() → Cycle (approved)
+-- validate_entitlement() → Entitlements (pending_validation)
|
+-- approve_entitlement() → Entitlements (approved)
+-- (payment) → Entitlements (trans2FSP → rdpd2ben)
Each step in this flow is delegated to the appropriate manager. The eligibility manager handles import_eligible_registrants, the entitlement manager handles prepare_entitlement, the cycle manager handles cycle state transitions, and the payment manager handles the payment steps.
Supporting entities#
These entities support the core pipeline. They are described briefly here — refer to the source code for full field definitions.
Vocabularies#
Controlled code lists used throughout OpenSPP for standardized values (ID types, relationship types, group types, etc.).
Model |
Purpose |
Module |
|---|---|---|
|
A vocabulary (e.g., "ID Types", "Relationship Types") |
|
|
A code within a vocabulary (e.g., "National ID", "Passport") |
|
|
Deployment-specific subset of codes to expose |
|
|
Deployment profile (Agriculture, Social Protection, etc.) |
|
Vocabularies are referenced by many models. For example, spp.id.type uses vocabulary codes for ID type definitions, and group types reference vocabulary codes for classification.
Areas#
Hierarchical geographic areas for targeting and reporting (country → region → district → sub-district).
Model |
Purpose |
Module |
|---|---|---|
|
Geographic area with parent/child hierarchy |
|
|
Tags for area classification |
|
|
Bulk area import from shapefiles or CSV |
|
Areas are linked to registrants, programs, and service points for geographic targeting and reporting.
Service points#
Physical locations where beneficiaries receive services or collect entitlements.
Model |
Purpose |
Module |
|---|---|---|
|
A service delivery location (office, distribution center, etc.) |
|
Service points are linked to areas and can be assigned to programs for distribution planning.
Change requests#
Data modification requests that go through an approval workflow before being applied to the registry.
Model |
Purpose |
Module |
|---|---|---|
|
A change request (create, update, or delete registrant data) |
|
|
Defines a type of change request and its configuration |
|
|
Abstract base for CR detail models (custom data per CR type) |
|
|
Maps CR type fields to target model fields |
|
|
Rules for detecting conflicting concurrent changes |
|
See Custom change request types for building custom CR types.
Event data#
Records of field visits, surveys, or other data collection events linked to registrants.
Model |
Purpose |
Module |
|---|---|---|
|
An event record (survey response, field visit, etc.) |
|
|
Defines an event type and its fields |
|
|
A field definition within an event type |
|
Events are linked to registrants via res.partner and can trigger program membership changes or entitlement recalculations.
Approval workflows#
Multi-tier approval system used by programs, change requests, and other workflows.
Model |
Purpose |
Module |
|---|---|---|
|
Defines an approval workflow (tiers, groups, conditions) |
|
|
A tier within an approval workflow |
|
|
A review instance tracking approval progress |
|
|
Abstract mixin — add to any model to make it approvable |
|
|
Global approval configuration |
|
Models that need approval workflows inherit from spp.approval.mixin, which adds approval state fields and workflow methods.
Entity relationship summary#
res.partner (registrants)
|
+-- spp.group.membership (individual ↔ group links)
+-- spp.registry.id (identity documents)
+-- spp.registry.relationship (inter-registrant relationships)
+-- spp.phone.number (phone numbers)
+-- spp.event.data (field data collection)
+-- spp.change.request (data modification requests)
|
+-- spp.program.membership (enrollment in programs)
|
+-- spp.program (program definition)
| +-- managers (eligibility, entitlements, cycles, payments)
| +-- spp.approval.definition (approval workflows)
|
+-- spp.cycle (distribution periods)
| +-- spp.area (geographic targeting)
|
+-- spp.entitlement (what beneficiaries receive)
+-- spp.service.point (delivery locations)
spp.vocabulary (code systems — referenced by many models)
+-- spp.vocabulary.code (individual codes within a vocabulary)
Source code locations#
Core entities#
Model |
Module |
File |
|---|---|---|
Registrant (base) |
|
|
Individual |
|
|
Group |
|
|
Group membership |
|
|
Registry ID |
|
|
Relationships |
|
|
Program |
|
|
Program membership |
|
|
Cycle |
|
|
Entitlement |
|
|
Managers |
|
|
Supporting entities#
Model |
Module |
File |
|---|---|---|
Vocabulary |
|
|
Vocabulary code |
|
|
Area |
|
|
Service point |
|
|
Change request |
|
|
CR type |
|
|
Event data |
|
|
Event type |
|
|
Approval definition |
|
|
Approval mixin |
|
|
openspp.org