Skip to content
Open
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",
}


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
16 changes: 16 additions & 0 deletions spp_hazard/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,22 @@ encounter unexpected behavior, please report it as a new issue.
Changelog
=========

19.0.2.1.0
~~~~~~~~~~

- 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: 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.2.1.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