You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This guide provides details on implementing the [Registry Addon Odoo](https://github.com/OpenG2P/openg2p-pbms-odoo-extensions) Module for integration with PBMS Odoo.
Copy file name to clipboardExpand all lines: pbms/developer-zone/tech-guides/registry-connectors.md
+300-1Lines changed: 300 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,5 +15,304 @@ layout:
15
15
visible: true
16
16
---
17
17
18
-
# Registry Connectors
18
+
# Registry Connector
19
19
20
+
This guide provides details on implementing the [Registry Connectors Interface](https://github.com/OpenG2P/openg2p-pbms-bg-tasks-extensions) for integration with PBMS Background Tasks.
21
+
22
+
## Overview
23
+
24
+
The `RegistryInterface` defines a standardized contract for interacting with various **G2P Registries** within the PBMS. It ensures consistent behavior across different registry integrations, including eligibility checks, summary computation, entitlement processing, and beneficiary search functionalities.
25
+
26
+
Custom implementations of this interface allow developers to integrate new registry types (for example, `farmer`, `student`, or `worker` registries) without modifying the PBMS core logic.
27
+
28
+
**Interface Code:**[Registry Interface](https://app.gitbook.com/u/21UJpMbIpqP7PKcbN5AOu80ESpo1) in OpenG2P PBMS Background Tasks Extensions\
The `RegistryInterface` defines methods for summary, eligibility and entitlement computation, registry access, and query construction. See the attached Key details of the same are mentioned below
34
+
35
+
### Computations
36
+
37
+
**`get_summary`**
38
+
39
+
**Purpose:** Asynchronously retrieves summary statistics for a given beneficiary list.\
40
+
Used primarily in background tasks or async workflows.
41
+
42
+
**Arguments:**
43
+
44
+
*`beneficiary_list_id (str)`: The ID of the beneficiary list to summarize.
45
+
*`bg_task_session (AsyncSession)`: Async SQLAlchemy session for background operations.
46
+
*`formated (bool, optional)`: Whether to return formatted summary data. Defaults to `False`.
47
+
48
+
**Returns:**\
49
+
`BeneficiaryListSummaryPayload` — Contains computed summary metrics for the list.
50
+
51
+
***
52
+
53
+
**`get_summary_sync`**
54
+
55
+
**Purpose:** Retrieves summary statistics synchronously for a beneficiary list (non-async execution).
56
+
57
+
**Arguments:**
58
+
59
+
*`beneficiary_list_id (str)`: The beneficiary list identifier.
**Purpose:** Generates a SQL query to check if a registrant meets entitlement conditions.
212
+
213
+
**Arguments:**
214
+
215
+
*`registrant_id (str)`: The registrant’s unique ID.
216
+
*`target_registry (str)`: Registry name.
217
+
*`sql_query (str)`: Base eligibility SQL.
218
+
219
+
**Returns:**`TextClause` - SQL query ready for execution with parameters.
220
+
221
+
***
222
+
223
+
## Data Models, Schemas and Dependencies
224
+
225
+
To implement this interface, the following models and schemas are typically imported from the G2P [PBMS](https://app.gitbook.com/u/21UJpMbIpqP7PKcbN5AOu80ESpo1) and [PBMS Background Task](https://github.com/OpenG2P/openg2p-pbms-bg-tasks/tree/3.0/openg2p-bg-task-models/src/openg2p_bg_task_models) ecosystem:
226
+
227
+
*`G2PRegistry`: Core registry ORM model.
228
+
*`BeneficiaryListDetails`: Details of beneficiaries linked to lists.
229
+
*`BeneficiaryListSummaryPayload`: Schema for summary statistics.
230
+
*`BeneficiarySearchResponsePayload`: Schema for search results.
231
+
*`Disbursement`: Disbursement data schema.
232
+
233
+
_Additional dependencies include `sqlalchemy`, `sqlalchemy.ext.asyncio`, and `abc` for abstract base class definition._
234
+
235
+
{% hint style="info" %}
236
+
New data models and schemas created during custom implementation are expected to inherit their corresponding parent model/schema
237
+
{% endhint %}
238
+
239
+
## Example Implementation Workflow
240
+
241
+
The [`RegistryFarmer` class](https://github.com/OpenG2P/openg2p-pbms-bg-tasks-extensions/blob/3.0/openg2p-bg-task-registry-adapters/src/openg2p_bg_task_registry_adapters/computations/registry_farmer.py) demonstrates a **custom implementation** of the `RegistryInterface`, tailored for integrating with a [**Farmer Registry**](https://github.com/OpenG2P/openg2p-pbms-bg-tasks-extensions/blob/3.0/openg2p-bg-task-registry-adapters/src/openg2p_bg_task_registry_adapters/models/registry_farmer.py) data source.
242
+
243
+
Below is the typical workflow for building a similar registry connector:
244
+
245
+
### Define a Custom Registry Class and Update Factory
246
+
247
+
Create a class (e.g., `RegistryFarmer`) that **inherits from**`RegistryInterface`.\
248
+
This ensures the connector implements all abstract methods required by the PBMS framework — including summaries, searches, and entitlement computations.
249
+
250
+
```python
251
+
classRegistryFarmer(RegistryInterface):
252
+
```
253
+
254
+
Update the `/factory/registry_factory.py` file to include this new registry class
255
+
256
+
```python
257
+
classRegistryFactory:
258
+
"""Get the appropriate summary computation class based on the registrant type"""
259
+
260
+
@staticmethod
261
+
defget_registry_class(
262
+
target_registry,
263
+
) -> RegistryInterface:
264
+
if target_registry == G2PRegistryType.FARMER.value:
### Create Custom Schema (`/schemas`) and Model Definitions (`/models`)
274
+
275
+
Define a pydantic schema to structure registry-specific summary data. Each registry schema extends the base `BeneficiaryListSummaryPayload` to ensure the payload integrates seamlessly with existing response models.
276
+
277
+
```python
278
+
# /schemas/beneficiary_list_summary_farmer.py
279
+
from typing import Optional
280
+
from pydantic import BaseModel
281
+
from .beneficiary_list_summary import BeneficiaryListSummaryPayload
282
+
283
+
classBeneficiaryListSummaryFarmer(BaseModel):
284
+
# ... registry-specific stats ...
285
+
# computaion logic is expected in registry connector implementation
Extend the base SQLAlchemy model `BeneficiaryListSummary` to persist registry-specific statistics. The inheritance ensures all common fields (e.g., `beneficiary_list_id`, timestamps) are available automatically.
292
+
293
+
```python
294
+
# /models/beneficiary_list_summary_farmer.py
295
+
from openg2p_bg_task_models.models import BeneficiaryListSummary
# computaion logic is expected in registry connector implementation
308
+
```
309
+
310
+
After new model creation you are expected to update the migration script in [`migrate.py`](https://github.com/OpenG2P/openg2p-pbms-bg-tasks-extensions/blob/3.0/openg2p-bg-task-registry-adapters/src/openg2p_bg_task_registry_adapters/migrate.py) with the new models.
311
+
312
+
Implement the computation and registry methods, you can use the SQL utility methods provided in the interface by passing `target_registry` string to get a `TextClause` SQL query. Refer the Code Anatomy for Registry Connector Interface below to populate your custom interface with the current interface template.
313
+
314
+
<table data-full-width="false"><thead><tr><th>Method Name</th><th width="82">Type</th><th>Purpose</th><th width="148">Key Arguments</th><th>Returns</th><th>Implementation Notes</th></tr></thead><tbody><tr><td><code>get_summary</code></td><td>Async</td><td>Retrieves summary statistics for a given beneficiary list asynchronously.</td><td><code>beneficiary_list_id: str</code>, <code>bg_task_session: AsyncSession</code>, <code>formated: bool</code></td><td><code>BeneficiaryListSummaryPayload</code></td><td>Used in API calls; fetches formatted summary metrics from summary table.</td></tr><tr><td><code>get_summary_sync</code></td><td>Sync</td><td>Same as <code>get_summary</code> but executed synchronously (for Celery or background tasks).</td><td><code>beneficiary_list_id: str</code>, <code>bg_task_session: Session</code></td><td><code>BeneficiaryListSummaryPayload</code></td><td>Ideal for heavy computation where async isn’t needed.</td></tr><tr><td><code>compute_eligibility_statistics</code></td><td>Sync</td><td>Computes eligibility-based summary metrics for beneficiaries.</td><td><code>beneficiary_list_details: List[BeneficiaryListDetails]</code>, <code>base_summary</code>, <code>sr_session</code>, <code>bg_task_session</code></td><td>None</td><td>Uses NumPy for percentile and mean computations; updates summary model.</td></tr><tr><td><code>compute_entitlement_statistics</code></td><td>Sync</td><td>Computes entitlement statistics (e.g., payment distribution by gender).</td><td><code>beneficiary_list_id: str</code>, <code>bg_task_session: Session</code>, <code>sr_session: Session</code></td><td>None</td><td>Groups entitlements by <code>benefit_code_id</code>; calculates mean, Q1, Q2, Q3.</td></tr><tr><td><code>get_registrants_by_ids</code></td><td>Sync</td><td>Fetches registrant data from the registry database.</td><td><code>registrant_ids: List[str]</code>, <code>sr_session: Session</code></td><td><code>List[G2PRegistry]</code></td><td>Uses chunked loading (<code>yield_per(500)</code>) for performance on large datasets.</td></tr><tr><td><code>get_is_registant_entitled</code></td><td>Sync</td><td>Checks if a registrant satisfies entitlement criteria using a SQL query.</td><td><code>registrant_id: str</code>, <code>sql_query: str</code>, <code>sr_session: Session</code></td><td><code>bool</code></td><td>Constructs validated dynamic SQL using <code>construct_get_is_registrant_entitled_sql_query</code>.</td></tr><tr><td><code>get_entitlement_multiplier</code></td><td>Sync</td><td>Retrieves multiplier value for entitlement scaling.</td><td><code>multiplier: str</code>, <code>registrant_id: str</code>, <code>sr_session: Session</code></td><td><code>int</code></td><td>Executes a SQL query; defaults to <code>1</code> if not found or multiplier is <code>"none"</code>.</td></tr><tr><td><code>search_beneficiaries</code></td><td>Async</td><td>Performs paginated and filtered beneficiary searches.</td><td><code>bg_task_session: AsyncSession</code>, <code>sr_session: AsyncSession</code>, <code>beneficiary_list_id: str</code>, <code>target_registry: str</code>, <code>search_query</code>, <code>page</code>, <code>page_size</code>, <code>order_by</code></td><td><code>BeneficiarySearchResponsePayload</code></td><td>Builds dynamic SQL queries with <code>construct_beneficiary_search_sql_query</code> and applies caching.</td></tr><tr><td><code>construct_multiplier_sql_query</code></td><td>Utility</td><td>Builds SQL query to fetch multiplier column from registry table.</td><td><code>multiplier: str</code>, <code>target_registry: str</code></td><td><code>TextClause</code></td><td>Returns a prepared SQLAlchemy <code>text()</code> object.</td></tr><tr><td><code>construct_beneficiary_search_sql_query</code></td><td>Utility</td><td>Constructs SQL for paginated search with WHERE and ORDER BY.</td><td><code>registrant_ids: List[str]</code>, <code>target_registry: str</code>, <code>where_clause: str</code>, <code>order_by: str</code>, <code>page_size: int</code>, <code>page: int</code></td><td><code>(TextClause, Dict[str, Any])</code></td><td>Replaces curly quotes in filters; dynamically injects pagination params.</td></tr><tr><td><code>construct_beneficiary_search_count_sql_query</code></td><td>Utility</td><td>Builds SQL query to count total search results.</td><td><code>registrant_ids: List[str]</code>, <code>target_registry: str</code>, <code>where_clause: str</code></td><td><code>(TextClause, Dict[str, Any])</code></td><td>Mirrors main query but replaces <code>SELECT *</code> with <code>SELECT COUNT(*)</code>.</td></tr><tr><td><code>construct_get_is_registrant_entitled_sql_query</code></td><td>Utility</td><td>Prepares validated entitlement SQL query with a dynamic <code>WHERE</code> clause.</td><td><code>registrant_id: str</code>, <code>target_registry: str</code>, <code>sql_query: str</code></td><td><code>TextClause</code></td><td>Validates SQL starts with <code>SELECT</code>; appends correct registry table reference.</td></tr></tbody></table>
315
+
316
+
After pushing this custom adapter code to GitHub, you can proceed to create a custom Docker image for your setup. Simply follow the existing [Docker creation guide](../pbms-docker.md#background-tasks) for **PBMS Background Tasks**, updating the path for the extensions package.
317
+
318
+
This approach ensures your environment remains consistent with the PBMS deployment standards while allowing flexibility to integrate your custom logic and components seamlessly.
0 commit comments