Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9b2d034
feat(spp_attendance): import module from openspp-modules
gonzalesedwin1123 Aug 18, 2026
3cf85a5
chore(spp_attendance): OpenSPP2 packaging
gonzalesedwin1123 Aug 18, 2026
075b639
fix(spp_attendance): never fabricate gender as Male
gonzalesedwin1123 Aug 18, 2026
80618ee
fix(spp_attendance): store client secrets as scrypt hashes, shown once
gonzalesedwin1123 Aug 18, 2026
8e6bc69
test(spp_attendance): full suite for a module that shipped none
gonzalesedwin1123 Aug 18, 2026
f26437a
fix(spp_attendance): Odoo 19 json_default import; test corrections
gonzalesedwin1123 Aug 18, 2026
b6d7b04
fix(spp_attendance): wizard error-path bugs caught by the new tests
gonzalesedwin1123 Aug 18, 2026
ea0edc4
test(spp_attendance): single exception class for Odoo assertRaises
gonzalesedwin1123 Aug 18, 2026
4c8bd44
fix(spp_attendance): satisfy OpenSPP2 lint gates; registry co-install…
gonzalesedwin1123 Aug 18, 2026
185c396
chore(spp_attendance): semgrep suppressions with justification; CI RE…
gonzalesedwin1123 Aug 18, 2026
aa17fcb
docs(spp_attendance): changelog covers every fix shipped in this PR
gonzalesedwin1123 Aug 18, 2026
5395a6b
chore(spp_attendance): shorten nosemgrep notes (E501); apply CI READM…
gonzalesedwin1123 Aug 18, 2026
d1e1ac2
docs(spp_attendance): un-corrupt README; avoid log-masker trap in USAGE
gonzalesedwin1123 Aug 18, 2026
2e0aacf
docs(spp_attendance): true up README wrap to CI generator rendering
gonzalesedwin1123 Aug 18, 2026
5dfc416
fix(spp_attendance): review round — true up token-mint suppression no…
gonzalesedwin1123 Aug 24, 2026
5e10de8
docs(spp_attendance): apply CI generator README rendering for updated…
gonzalesedwin1123 Aug 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pyproj
python-dateutil
python-magic
python-multipart
pytz
qrcode
requests
schwifty
Expand Down
250 changes: 250 additions & 0 deletions spp_attendance/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
==================
OpenSPP Attendance
==================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f14cdc55cd485da151349989e21bdafb68dcad327eef90ac39756a284a0d3779
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OpenSPP%2FOpenSPP2-lightgray.png?logo=github
:target: https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_attendance
:alt: OpenSPP/OpenSPP2

|badge1| |badge2| |badge3|

Tracks participant attendance for social protection program activities.
Records presence/absence with date, time, location, and activity type.
Provides OAuth-secured API endpoints for external systems to submit
attendance data and import participants from external registries.

**Positioning vs ``spp_session_tracking``:** this module is a
standalone, API-first attendance service — it keeps its own participant
registry (synced from an external registry) and receives attendance
events from external systems over REST, so it can run on a bare instance
without the program stack. ``spp_session_tracking`` covers the
complementary case: attendance at sessions and trainings managed
*inside* a program instance. The two do not share models and can
coexist.

Key Capabilities
~~~~~~~~~~~~~~~~

- Record attendance with date, time, type, location, and category
(present/absent)
- Query attendance history via ``get_attendance_list()`` with filtering
by date range, type, and location
- Import participants from external registries via configurable field
mapping
- Generate OAuth client credentials for external API access
- Enforce configurable uniqueness constraints (date/time/type/location)
to prevent duplicate records

Key Models
~~~~~~~~~~

+------------------------------------------+----------------------------------+
| Model | Description |
+==========================================+==================================+
| ``spp.attendance.subscriber`` | Participant registry, inherits |
| | res.partner |
+------------------------------------------+----------------------------------+
| ``spp.attendance.list`` | Attendance record with date, |
| | time, type, location |
+------------------------------------------+----------------------------------+
| ``spp.attendance.type`` | Configurable attendance event |
| | types |
+------------------------------------------+----------------------------------+
| ``spp.attendance.location`` | Configurable attendance |
| | locations |
+------------------------------------------+----------------------------------+
| ``spp.attendance.api.client.credential`` | OAuth credentials for external |
| | API clients |
+------------------------------------------+----------------------------------+
| ``spp.import.attendance.wizard`` | Wizard for importing from |
| | external registries |
+------------------------------------------+----------------------------------+

Configuration
~~~~~~~~~~~~~

After installing:

1. Navigate to **Settings > SPP Attendance Settings** to configure:

- Uniqueness constraints (date/time/type/location)
- Server URL and API endpoints
- Field mappings for import (personal information, identifiers,
contact details)

2. Create attendance types: **Attendance > Configuration > Attendance
Type**
3. Create locations: **Attendance > Configuration > Attendance
Location**
4. Generate OAuth credentials: **Settings > Attendance API Client
Credentials**

UI Location
~~~~~~~~~~~

- **Main Menu**: Attendance > Subscriber
- **Configuration**: Attendance > Configuration (Attendance Type,
Attendance Location)
- **API Credentials**: Settings > Attendance API Client Credentials
- **Settings**: Settings > SPP Attendance Settings
- **Subscriber Form**: Contains "Attendance" and "Person Information"
tabs

Security
~~~~~~~~

=========================================== =========
Group Access
=========================================== =========
``spp_attendance.group_attendance_viewer`` Read
``spp_attendance.group_attendance_manager`` Full CRUD
=========================================== =========

Extension Points
~~~~~~~~~~~~~~~~

- Override ``get_attendance_list()`` on ``spp.attendance.subscriber`` to
customize attendance queries
- Inherit ``spp.attendance.list`` to add domain-specific attendance
metadata
- Extend ``_import_attendance()`` in wizard to customize import logic

Dependencies
~~~~~~~~~~~~

``base``, ``spp_oauth``, ``spp_security``

.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.

**Table of contents**

.. contents::
:local:

Usage
=====

Syncing participants from a registry
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The participant import (Settings > SPP Attendance Settings, used by the
*Import Attendance* wizard) is fully configuration-driven: an auth
endpoint, a search endpoint, and JSON-path mappings into the response.
The shipped defaults target the SPDCI-style interface of a legacy
openspp-modules registry (``/oauth2/client/token`` +
``/registry/sync/search``).

To sync from an **OpenSPP2** registry instead, point the settings at the
DCI server modules (``spp_dci_server`` + ``spp_dci_server_social`` must
be installed on the registry instance):

+-----------------+----------------------------------------------------+
| Setting | Value for an OpenSPP2 registry |
+=================+====================================================+
| Server URL | ``https://<registry-host>`` |
+-----------------+----------------------------------------------------+
| Auth Endpoint | ``/api/v2/spp/oauth/token`` (spp_api_v2 |
| | client-credentials endpoint) |
+-----------------+----------------------------------------------------+
| Import Endpoint | ``/dci_api/v1/registry/sync/search`` |
+-----------------+----------------------------------------------------+

The JSON-path mappings (personal information, identifier, names, contact
fields) must match the DCI search response envelope of the target
registry; adjust them from the defaults as needed.

API access for external systems
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. Create client credentials under **Attendance > Configuration > API
Clients**. The client secret is displayed **once** at creation (and
on regeneration) — store it securely; only a hash is kept.
2. Obtain a token: ``POST /auth/token`` with
``client_id``/``client_secret``.
3. Call the attendance endpoints with the token in the ``Authorization``
header (``Bearer`` scheme).

Signing keys come from ``spp_oauth`` (Settings > General Settings >
OpenSPP OAuth); the RSA keypair must be configured before tokens can be
issued.

Changelog
=========

19.0.2.0.0
~~~~~~~~~~

- Initial migration to OpenSPP2
- fix(security): store API client secrets as scrypt hashes instead of
plaintext. Each secret is shown once via the Show Credentials dialog
and cannot be read back after that display (until the dialog is used,
the stored plaintext remains readable by attendance managers). Secrets
that existed before the upgrade are hashed in place by a migration.
Clients keep authenticating with their unchanged secrets. The
Attendance Viewer group's read access to the credential model is
removed.
- fix(security): the one-time credential display wizard is readable only
by the user who opened it — previously any attendance manager could
read a secret another manager had just issued
- fix: the REST API works on Odoo 19 again — every response with a body
crashed with ``AttributeError`` because ``date_utils.json_default``
was removed from Odoo
- fix: gender is never fabricated as "Male" — the res.partner field
default, the subscriber related-field default, the registry-import
fallback and the subscriber-create fallback all stamped it when gender
was unknown; the value now comes only from source data
- fix(wizard): a missing sync-configuration parameter raises the
intended error message instead of crashing with ``KeyError``; access
tokens already carrying a ``Basic`` scheme are no longer
double-prefixed
- fix(wizard): registry sync requests carry a 30s timeout so a hung
remote registry cannot freeze the worker

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OpenSPP/OpenSPP2/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OpenSPP/OpenSPP2/issues/new?body=module:%20spp_attendance%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* OpenSPP.org

Maintainers
-----------

.. |maintainer-reichie020212| image:: https://github.com/reichie020212.png?size=40px
:target: https://github.com/reichie020212
:alt: reichie020212

Current maintainer:

|maintainer-reichie020212|

This module is part of the `OpenSPP/OpenSPP2 <https://github.com/OpenSPP/OpenSPP2/tree/19.0/spp_attendance>`_ project on GitHub.

You are welcome to contribute.
3 changes: 3 additions & 0 deletions spp_attendance/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import controllers
from . import models
from . import wizard
34 changes: 34 additions & 0 deletions spp_attendance/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# pylint: disable=pointless-statement
{
"name": "OpenSPP Attendance",
"category": "OpenSPP",
"version": "19.0.2.0.0",
"summary": "This module accurately tracks participant attendance for social protection program activities, capturing essential details like date, time, location, and activity type. It integrates attendance records to inform conditional benefit eligibility and leverages spp_oauth to secure API endpoints for external data submission.",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
"license": "LGPL-3",
"development_status": "Alpha",
"maintainers": ["reichie020212"],
"depends": ["base", "spp_oauth", "spp_security"],
"external_dependencies": {"python": ["pytz"]},
"data": [
"data/ir_config_parameter_data.xml",
"security/privileges.xml",
"security/security.xml",
"security/ir.model.access.csv",
"views/main_views.xml",
"views/attendance_views.xml",
"views/attendance_api_client_views.xml",
"views/res_config_view.xml",
"views/attendance_type_views.xml",
"views/attendance_location_views.xml",
"wizard/import_attendance_view.xml",
],
"assets": {},
"demo": [],
"images": [],
"application": True,
"installable": True,
"auto_install": False,
}
1 change: 1 addition & 0 deletions spp_attendance/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import controllers
Loading
Loading