Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions spp_drims/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ Dependencies
Changelog
=========

19.0.2.1.0
~~~~~~~~~~

- feat: incident areas expose ``effective_severity_id`` (area override
or incident severity) and a numeric 1-5 ``severity_numeric`` derived
from CAP severity codes for choropleth visualization (re-land from
#76, follows the spp_hazard severity vocabulary change).

19.0.2.0.0
~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion spp_drims/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"and distribution tracking. Links to hazard incidents with multi-tier "
"approval workflows and warehouse operations.",
"category": "OpenSPP/Inventory",
"version": "19.0.2.0.0",
"version": "19.0.2.1.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
Expand Down
35 changes: 20 additions & 15 deletions spp_drims/models/hazard_incident_area.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models

# Map CAP severity vocabulary codes to a 1-5 numeric scale (higher = more
# severe) for choropleth map visualization.
CAP_SEVERITY_NUMERIC = {
"extreme": 5,
"severe": 4,
"moderate": 3,
"minor": 2,
"unknown": 1,
}


class HazardIncidentArea(models.Model):
"""Extend incident area with GIS polygon for map visualization."""
Expand All @@ -17,17 +27,12 @@ class HazardIncidentArea(models.Model):
)

# Computed severity that falls back to incident severity
effective_severity = fields.Selection(
[
("1", "Level 1 - Minor"),
("2", "Level 2 - Moderate"),
("3", "Level 3 - Significant"),
("4", "Level 4 - Severe"),
("5", "Level 5 - Catastrophic"),
],
effective_severity_id = fields.Many2one(
"spp.vocabulary.code",
string="Effective Severity",
compute="_compute_effective_severity",
store=True,
help="Area-specific severity or inherited from incident",
help="Area-specific severity override, or inherited from the incident",
)

# Additional fields for GIS popup display and grouping
Expand Down Expand Up @@ -61,14 +66,14 @@ class HazardIncidentArea(models.Model):
help="Numeric severity (1-5) for choropleth map visualization",
)

@api.depends("severity_override", "incident_id.severity")
@api.depends("severity_override_id", "incident_id.severity_id")
def _compute_effective_severity(self):
"""Compute effective severity from override or incident default."""
"""Compute effective severity from area override or incident default."""
for rec in self:
rec.effective_severity = rec.severity_override or rec.incident_id.severity or "3"
rec.effective_severity_id = rec.severity_override_id or rec.incident_id.severity_id

@api.depends("effective_severity")
@api.depends("effective_severity_id")
def _compute_severity_numeric(self):
"""Compute numeric severity from selection value for choropleth."""
"""Compute numeric severity from the CAP severity code for choropleth."""
for rec in self:
rec.severity_numeric = int(rec.effective_severity) if rec.effective_severity else 3
rec.severity_numeric = CAP_SEVERITY_NUMERIC.get(rec.effective_severity_id.code, 0)
4 changes: 4 additions & 0 deletions spp_drims/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 19.0.2.1.0

- feat: incident areas expose `effective_severity_id` (area override or incident severity) and a numeric 1-5 `severity_numeric` derived from CAP severity codes for choropleth visualization (re-land from #76, follows the spp_hazard severity vocabulary change).

### 19.0.2.0.0

- Initial migration to OpenSPP2
9 changes: 9 additions & 0 deletions spp_drims/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,15 @@ <h2><a class="toc-backref" href="#toc-entry-1">Changelog</a></h2>
</div>
</div>
<div class="section" id="section-1">
<h1>19.0.2.1.0</h1>
<ul class="simple">
<li>feat: incident areas expose <tt class="docutils literal">effective_severity_id</tt> (area override
or incident severity) and a numeric 1-5 <tt class="docutils literal">severity_numeric</tt> derived
from CAP severity codes for choropleth visualization (re-land from
#76, follows the spp_hazard severity vocabulary change).</li>
</ul>
</div>
<div class="section" id="section-2">
<h1>19.0.2.0.0</h1>
<ul class="simple">
<li>Initial migration to OpenSPP2</li>
Expand Down
1 change: 1 addition & 0 deletions spp_drims/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from . import test_coordination
from . import test_donation
from . import test_incident
from . import test_incident_area_severity
from . import test_personnel
from . import test_request
from . import test_request_from_template_wizard
Expand Down
50 changes: 50 additions & 0 deletions spp_drims/tests/test_incident_area_severity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
from .common import DrimsTestCommon


class TestIncidentAreaSeverity(DrimsTestCommon):
"""Effective severity / numeric severity for the GIS choropleth.

Guards the spp_hazard severity migration (Selection -> CAP vocabulary
Many2one): spp_drims extends spp.hazard.incident.area and must follow the
new severity_id / severity_override_id fields.
"""

@classmethod
def setUpClass(cls):
super().setUpClass()
VocabCode = cls.env["spp.vocabulary.code"]
ns = "urn:oasis:names:tc:cap:severity"
cls.sev_extreme = VocabCode.get_code(ns, "extreme")
cls.sev_severe = VocabCode.get_code(ns, "severe")
cls.sev_moderate = VocabCode.get_code(ns, "moderate")

def _make_area(self, severity_override_id=False):
return self.env["spp.hazard.incident.area"].create(
{
"incident_id": self.incident.id,
"area_id": self.area.id,
"severity_override_id": severity_override_id,
}
)

def test_effective_severity_uses_override(self):
"""Area override takes precedence over the incident severity."""
self.incident.severity_id = self.sev_moderate
area = self._make_area(severity_override_id=self.sev_extreme.id)
self.assertEqual(area.effective_severity_id, self.sev_extreme)
self.assertEqual(area.severity_numeric, 5)

def test_effective_severity_falls_back_to_incident(self):
"""Without an override, severity is inherited from the incident."""
self.incident.severity_id = self.sev_severe
area = self._make_area()
self.assertEqual(area.effective_severity_id, self.sev_severe)
self.assertEqual(area.severity_numeric, 4)

def test_severity_numeric_zero_when_unset(self):
"""No override and no incident severity -> numeric 0 (no choropleth value)."""
self.incident.severity_id = False
area = self._make_area()
self.assertFalse(area.effective_severity_id)
self.assertEqual(area.severity_numeric, 0)
7 changes: 7 additions & 0 deletions spp_drims_sl_demo/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ Dependencies
Changelog
=========

19.0.2.0.1
~~~~~~~~~~

- fix: demo generator resolves scenario severity levels to CAP severity
vocabulary codes (follows the spp_hazard severity vocabulary change,
re-land from #76).

19.0.2.0.0
~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion spp_drims_sl_demo/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"summary": "Demo data generator for DRIMS Sri Lanka implementation. "
"Creates sample incidents, donations, requests, and stock for demonstrations.",
"category": "OpenSPP/Inventory",
"version": "19.0.2.0.0",
"version": "19.0.2.0.1",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
Expand Down
4 changes: 4 additions & 0 deletions spp_drims_sl_demo/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 19.0.2.0.1

- fix: demo generator resolves scenario severity levels to CAP severity vocabulary codes (follows the spp_hazard severity vocabulary change, re-land from #76).

### 19.0.2.0.0

- Initial migration to OpenSPP2
8 changes: 8 additions & 0 deletions spp_drims_sl_demo/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,14 @@ <h2><a class="toc-backref" href="#toc-entry-1">Changelog</a></h2>
</div>
</div>
<div class="section" id="section-1">
<h1>19.0.2.0.1</h1>
<ul class="simple">
<li>fix: demo generator resolves scenario severity levels to CAP severity
vocabulary codes (follows the spp_hazard severity vocabulary change,
re-land from #76).</li>
</ul>
</div>
<div class="section" id="section-2">
<h1>19.0.2.0.0</h1>
<ul class="simple">
<li>Initial migration to OpenSPP2</li>
Expand Down
24 changes: 22 additions & 2 deletions spp_drims_sl_demo/wizard/drims_demo_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ def _simplify_geometry(geometry, tolerance=0.001):
return mapping(simplified)


# Severity is stored as a CAP vocabulary code (spp.vocabulary.code). The demo
# scenarios describe severity with the legacy 1-5 scale, mapped here to the
# equivalent CAP severity code.
CAP_SEVERITY_NS = "urn:oasis:names:tc:cap:severity"
_LEGACY_SEVERITY_TO_CAP = {
"5": "extreme",
"4": "severe",
"3": "moderate",
"2": "minor",
"1": "unknown",
Comment on lines +56 to +61

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 This legacy 1→5 → CAP mapping diverges from the migration's

spp_hazard/migrations/19.0.2.1.0/post-migration.py maps the same legacy scale differently:

legacy migration here (demo) old label
1 minor unknown Minor
2 moderate minor Moderate
3 severe moderate Significant
4 severe severe Severe
5 extreme extreme Catastrophic

They only agree on 4 and 5. So a "level 3" incident becomes CAP severe on an upgraded DB but CAP moderate on a fresh demo install — and 2→minor / 3→moderate here also contradicts the original Selection labels. Recommend reconciling to the migration's label-faithful mapping, or adding a comment justifying why the demo path intentionally differs (it round-trips with spp_drims's CAP_SEVERITY_NUMERIC).

}


class DrimsDemoGenerator(models.TransientModel):
_name = "spp.drims.demo.generator"
_description = "DRIMS Demo Data Generator"
Expand Down Expand Up @@ -653,6 +666,13 @@ def _add_warehouse_gps_coordinates(self):
)
_logger.debug("Added GPS coordinates to warehouse %s", wh_name)

def _resolve_severity(self, legacy_value):
"""Resolve a legacy 1-5 severity string to a CAP severity vocab code."""
code = _LEGACY_SEVERITY_TO_CAP.get(legacy_value)
if not code:
return self.env["spp.vocabulary.code"]
return self.env["spp.vocabulary.code"].get_code(CAP_SEVERITY_NS, code)

def _generate_incidents(self):
"""Generate demo hazard incidents."""
Incident = self.env["spp.hazard.incident"]
Expand Down Expand Up @@ -792,7 +812,7 @@ def _generate_incidents(self):
area_details.append(
{
"area_id": area.id,
"severity_override": area_info.get("severity"),
"severity_override_id": self._resolve_severity(area_info.get("severity")).id,
"affected_population_estimate": area_info.get("population", 0),
"notes": f"Affected area in {scenario['name']}",
}
Expand All @@ -805,7 +825,7 @@ def _generate_incidents(self):
"name": scenario["name"],
"code": scenario["code"],
"category_id": scenario["category_id"],
"severity": scenario.get("severity", "3"),
"severity_id": self._resolve_severity(scenario.get("severity", "3")).id,
"start_date": scenario["start_date"],
"description": scenario.get("description", ""),
"status": "active",
Expand Down
34 changes: 34 additions & 0 deletions spp_hazard/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,40 @@ encounter unexpected behavior, please report it as a new issue.
Changelog
=========

19.0.3.0.0
~~~~~~~~~~

- **BREAKING**: the 1-5 ``severity`` Selection on
``spp.hazard.incident`` and ``severity_override`` on
``spp.hazard.incident.area`` are removed and replaced by
``severity_id`` / ``severity_override_id`` (Many2one to
``spp.vocabulary.code`` on the CAP severity namespace). Modules that
extend these models must migrate: views that reference
``<field name="severity">`` / ``severity_override``, code that reads
``record.severity``, records created with ``severity="…"``, and any
``fields_to_log`` entries or domains naming the old fields. Read
``severity_numeric`` (below) where a numeric scale is needed.
- **BREAKING**: ``spp_hazard`` now depends on ``spp_vocabulary``.
- **BREAKING**: ``category_id`` and ``start_date`` are no longer
``required`` at the model level (they remain required in the incident
form view) so alert ingestion can create incidents that lack them.
- feat: severity is now a CAP v1.2 vocabulary code (``severity_id``,
``severity_override_id`` on incident areas) instead of a hardcoded 1-5
Selection; adds CAP urgency/certainty/message-type/event fields, alert
ingestion (``create_incident_from_alert``), and incident ``uuid``
(re-land from #76).
- feat: ``spp.hazard.incident`` exposes a stored ``severity_numeric``
(5=extreme, 4=severe, 3=moderate, 2=minor, 1=unknown, 0=unset) so
downstream ordering and threshold logic can consume a numeric scale
without resolving CAP vocabulary codes.
- feat: migration backfills legacy 1-5 severity values onto the
vocabulary fields when upgrading from 19.0.2.0.x (1→minor, 2→moderate,
3→severe, 4→severe, 5→extreme); existing values are never overwritten
and legacy columns are kept.
- fix: demo incident-area records now set ``severity_override_id``
vocabulary refs (the removed ``severity_override`` field broke demo
installs).

19.0.2.0.2
~~~~~~~~~~

Expand Down
4 changes: 3 additions & 1 deletion spp_hazard/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"for emergency response. Links registrants to disaster events with geographic scope "
"and severity tracking to enable targeted humanitarian assistance.",
"category": "OpenSPP/Targeting",
"version": "19.0.2.0.2",
"version": "19.0.3.0.0",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
Expand All @@ -21,11 +21,13 @@
"spp_registry",
"spp_area",
"spp_gis",
"spp_vocabulary",
],
"data": [
"security/privileges.xml",
"security/groups.xml",
"security/ir.model.access.csv",
"data/vocabulary_cap.xml",
"data/impact_type_data.xml",
"data/user_roles.xml",
"views/hazard_category_views.xml",
Expand Down
Loading
Loading