---
myst:
html_meta:
"title": "Program entitlements"
"description": "Learn how to customize entitlement calculation logic and management in OpenSPP through custom module development"
"keywords": "OpenSPP, entitlements, program entitlements, entitlement calculation, benefit calculation, module development"
---
# Program entitlements
In OpenSPP, program benefits are defined and calculated through a flexible system called **Entitlement Managers**.
An Entitlement Manager is a self-contained component that defines the logic for how much a {term}`beneficiary` is entitled to receive in a given program cycle.
This allows for creating reusable and complex benefit calculation rules that can be easily attached to any program.
This guide will walk you through creating a custom Entitlement Manager module from scratch.
We will use the {doc}`spp_entitlement_cash ` module as a practical reference to build a new manager that calculates cash-based entitlements with flexible rules.
By the end of this guide, you will be able to:
- Understand the role and structure of an Entitlement Manager.
- Create a new model for your custom entitlement rules.
- Implement the core logic to calculate and create entitlements.
- Create a user interface for configuring your manager.
- Register your new manager so it can be used in any program.
- Extend the Program Creation Wizard to pre-configure your manager.
- Set up the necessary security access for your new model.
## Prerequisites
- Solid understanding of Odoo 17 module development, including Python, XML, and XPath.
- Familiarity with the OpenG2P and OpenSPP core modules, especially `OpenG2P Programs` ({doc}`g2p_programs `), `OpenSPP Programs` ({doc}`spp_programs `), and `G2P Registry (Base)` ({doc}`g2p_registry_base `).
- To set up OpenSPP for development, please refer to the {doc}`Development Setup Guide <../setup>`.
## Module Structure
A typical Entitlement Manager module follows the standard Odoo module structure.
Here's the complete structure of our reference module, {doc}`spp_entitlement_cash `:
```text
spp_entitlement_cash/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── entitlement_manager.py # The core manager logic & registration
├── security/
│ └── ir.model.access.csv
├── views/
│ └── entitlement_manager_view.xml # The manager's UI
└── wizard/
├── __init__.py
└── create_program_wizard.py # Extends the program creation wizard
```
---
## Step-by-Step Guide
### Create the Module Scaffold
Start by creating a new directory for your module (e.g., `spp_custom_entitlement_manager`) and populate it with the basic Odoo module files and the directory structure shown above.
### Define the Manifest (`__manifest__.py`)
The manifest file declares your module's metadata and dependencies.
It's crucial to list all the modules your customization will interact with.
Our cash entitlement manager depends on {doc}`g2p_programs ` and {doc}`spp_programs ` for the base manager framework.
```python
# From: spp_entitlement_cash/__manifest__.py
{
"name": "OpenSPP Cash Entitlement",
"summary": "Manage cash-based entitlements for beneficiaries within social protection programs, including defining calculation rules, automating disbursement, and tracking payments.",
"category": "OpenSPP",
"version": "17.0.1.3.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/openspp-modules",
"license": "LGPL-3",
"development_status": "Production/Stable",
"maintainers": ["jeremi", "gonzalesedwin1123"],
"depends": [
"base",
"g2p_registry_base",
"g2p_programs",
"spp_programs",
],
"data": [
"security/ir.model.access.csv",
"views/entitlement_manager_view.xml",
"wizard/create_program_wizard.xml",
],
"application": True,
"installable": True,
"auto_install": False,
}
```
### Create the Entitlement Manager Model
This is the core of your module.
You will create a new model that holds the specific configuration for your entitlement rules and contains the logic to calculate and generate entitlements.
1. **Create the model file**: In your `models/` directory, create a Python file named `entitlement_manager.py`. Remember to import it in `models/__init__.py`.
2. **Define the model**:
- The model name (`_name`) should be descriptive, like `g2p.program.entitlement.manager.cash`.
- Inherit from `g2p.base.program.entitlement.manager`. This provides the essential framework for an entitlement manager.
- Define fields to store the configuration. In this case, we have a one-to-many field to a separate model, `g2p.program.entitlement.manager.cash.item`, which holds the individual calculation rules.
```python
# From: spp_entitlement_cash/models/entitlement_manager.py
class G2PCashEntitlementManager(models.Model):
_name = "g2p.program.entitlement.manager.cash"
_inherit = [
"g2p.base.program.entitlement.manager",
"g2p.manager.source.mixin",
]
_description = "Cash Entitlement Manager"
entitlement_item_ids = fields.One2many(
"g2p.program.entitlement.manager.cash.item",
"entitlement_id",
"Entitlement Items",
)
max_amount = fields.Monetary(...)
# ... other fields
def prepare_entitlements(self, cycle, beneficiaries):
"""Prepare Cash Entitlements."""
# ... (logic to iterate through items and beneficiaries) ...
for beneficiary_id in beneficiaries_with_entitlements_to_create:
# ... (calculate amount based on rules) ...
new_entitlements_to_create[beneficiary_id.id] = {
"cycle_id": cycle.id,
"partner_id": beneficiary_id.id,
"initial_amount": amount,
# ... other entitlement values
}
# ... (create g2p.entitlement records) ...
```
The `prepare_entitlements` method is the most critical part.
It is called by the system to generate the `g2p.entitlement` records for a given cycle and set of beneficiaries, based on the rules defined in the manager.
### Register the New Manager
To make OpenSPP aware of your new manager, you must add it to the list of available entitlement managers.
1. **Extend the `g2p.program.entitlement.manager` model**: In the same file, `models/entitlement_manager.py`, inherit from `g2p.program.entitlement.manager`.
2. **Extend the selection method**: Override the `_selection_manager_ref_id` method to add your new manager's model name and a user-friendly label to the selection list.
```python
# From: spp_entitlement_cash/models/entitlement_manager.py
class EntitlementManager(models.Model):
_inherit = "g2p.program.entitlement.manager"
@api.model
def _selection_manager_ref_id(self):
selection = super()._selection_manager_ref_id()
new_manager = ("g2p.program.entitlement.manager.cash", "Cash")
if new_manager not in selection:
selection.append(new_manager)
return selection
```
### Create the User Interface
Create a form view so that program administrators can configure the rules for your new manager.
```xml
view_entitlement_manager_cash_form
g2p.program.entitlement.manager.cash
```
### Extend the Program Creation Wizard
To improve user experience, add configuration fields directly to the "Create Program" wizard.
1. **Extend the wizard model**: In `wizard/create_program_wizard.py`, inherit from `g2p.program.create.wizard`, add an `entitlement_kind` selection for your new manager, and override `_get_entitlement_manager` to handle its creation.
```python
# In: wizard/create_program_wizard.py
class G2PCreateNewProgramWiz(models.TransientModel):
_inherit = "g2p.program.create.wizard"
entitlement_kind = fields.Selection(selection_add=[("cash", "Cash")])
entitlement_cash_item_ids = fields.One2many(...)
def _get_entitlement_manager(self, program_id):
res = super()._get_entitlement_manager(program_id)
if self.entitlement_kind == "cash":
# Logic to create 'g2p.program.entitlement.manager.cash'
# and link it to the program via 'g2p.program.entitlement.manager'
# ...
return res
```
2. **Extend the wizard view**: In `wizard/create_program_wizard.xml`, extend the form to show your new fields when the "Cash" entitlement kind is selected.
### Set Up Security
Grant users access to your new models in `security/ir.model.access.csv`.
```csv
# From: spp_entitlement_cash/security/ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
g2p_program_entitlement_manager_cash_admin,Program Entitlement Manager Cash Admin Access,spp_entitlement_cash.model_g2p_program_entitlement_manager_cash,g2p_registry_base.group_g2p_admin,1,1,1,1
g2p_program_entitlement_manager_cash_program_manager,Program Entitlement Manager Cash Program Manager Access,spp_entitlement_cash.model_g2p_program_entitlement_manager_cash,g2p_programs.g2p_program_manager,1,1,1,0
```
### Install and Test
1. Install or upgrade the module through the Apps menu.
2. Navigate to **Programs** and click **Create Program**.
3. In the wizard, under the **Entitlement** page, select your new **"Cash"** manager type from the **Manager** dropdown.
4. The fields for your manager will appear, allowing you to define entitlement rules directly in the wizard.
5. Click **Create**.
A new program will be created, and an instance of your entitlement manager will be automatically created and configured.
## References
For more information on extending OpenSPP modules, refer to:
- [Odoo 17 Developer Documentation](https://www.odoo.com/documentation/17.0/developer/)
- [OpenSPP Programs Module Source](https://github.com/OpenSPP/openspp-modules/tree/17.0/spp_programs)