Skip to content

Commit 2525e5b

Browse files
Merge pull request #12 from OpenSPP/feat/spp-alerts-rule-evaluation-beta
feat(spp_alerts): add rule evaluation engine and promote to Beta
2 parents 5a2ee2f + 2dfd4f1 commit 2525e5b

File tree

11 files changed

+1116
-129
lines changed

11 files changed

+1116
-129
lines changed

spp_alerts/README.rst

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ OpenSPP Alerts
1414
!! source digest: sha256:7186687b7752640f90d9d124b0fc91967afaef27e84c13f22cbed7954ae9b438
1515
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1616
17-
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
17+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
1818
:target: https://odoo-community.org/page/development-status
19-
:alt: Alpha
19+
:alt: Beta
2020
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
2121
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
2222
:alt: License: LGPL-3
@@ -103,11 +103,6 @@ Dependencies
103103

104104
``base``, ``mail``, ``spp_security``, ``spp_vocabulary``
105105

106-
.. IMPORTANT::
107-
This is an alpha version, the data model and design can change at any time without warning.
108-
Only for development or testing purpose, do not use in production.
109-
`More details on development status <https://odoo-community.org/page/development-status>`_
110-
111106
**Table of contents**
112107

113108
.. contents::

spp_alerts/__manifest__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"author": "OpenSPP.org",
1010
"website": "https://github.com/OpenSPP/OpenSPP2",
1111
"license": "LGPL-3",
12-
"development_status": "Alpha",
12+
"development_status": "Beta",
1313
"maintainers": ["jeremi", "gonzalesedwin1123", "emjay0921"],
1414
"depends": [
1515
"base",
@@ -26,6 +26,7 @@
2626
"data/ir_sequence.xml",
2727
"data/vocabulary_namespaces.xml",
2828
"data/vocabulary_codes.xml",
29+
"data/ir_cron.xml",
2930
# Views
3031
"views/alert_views.xml",
3132
"views/alert_rule_views.xml",

spp_alerts/data/ir_cron.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<odoo noupdate="1">
3+
<!-- Generic Alert Rule Evaluation Cron -->
4+
<record id="cron_evaluate_alert_rules" model="ir.cron">
5+
<field name="name">Alerts: Evaluate Alert Rules</field>
6+
<field name="model_id" ref="model_spp_alert_rule" />
7+
<field name="state">code</field>
8+
<field name="code">model._cron_evaluate_rules()</field>
9+
<field name="interval_number">1</field>
10+
<field name="interval_type">days</field>
11+
<field name="active" eval="True" />
12+
</record>
13+
</odoo>

spp_alerts/models/alert.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33

44
from odoo import _, api, fields, models
5+
from odoo.exceptions import UserError
56

67
_logger = logging.getLogger(__name__)
78

@@ -94,6 +95,31 @@ class Alert(models.Model):
9495
help="Detailed description of the alert condition",
9596
)
9697

98+
# Source tracking (populated by rule engine, empty for manual alerts)
99+
rule_id = fields.Many2one(
100+
"spp.alert.rule",
101+
string="Source Rule",
102+
index=True,
103+
readonly=True,
104+
ondelete="set null",
105+
help="Alert rule that generated this alert (empty for manually created alerts)",
106+
)
107+
108+
res_model = fields.Char(
109+
string="Source Model",
110+
index=True,
111+
readonly=True,
112+
help="Technical model name of the record that triggered this alert",
113+
)
114+
115+
res_id = fields.Many2oneReference(
116+
string="Source Record",
117+
model_field="res_model",
118+
index=True,
119+
readonly=True,
120+
help="Record that triggered this alert",
121+
)
122+
97123
# Metrics for threshold and deadline tracking
98124
current_value = fields.Float(
99125
string="Current Value",
@@ -144,7 +170,9 @@ def create(self, vals_list):
144170
for vals in vals_list:
145171
if vals.get("reference", _("New")) == _("New"):
146172
# Use sudo to access sequence (users may not have ir.sequence access)
147-
vals["reference"] = self.env["ir.sequence"].sudo().next_by_code("spp.alert") or _("New")
173+
# nosemgrep: odoo-sudo-without-context - Standard sequence access
174+
Sequence = self.env["ir.sequence"].sudo()
175+
vals["reference"] = Sequence.next_by_code("spp.alert") or _("New")
148176
return super().create(vals_list)
149177

150178
def action_acknowledge(self):
@@ -164,7 +192,15 @@ def action_resolve(self, notes=None):
164192
165193
Returns:
166194
bool: True on success
195+
196+
Raises:
197+
UserError: If resolution notes are not provided.
167198
"""
199+
for record in self:
200+
resolution = notes or record.resolution_notes
201+
if not resolution:
202+
raise UserError(_("Please provide resolution notes before resolving the alert."))
203+
168204
vals = {
169205
"state": "resolved",
170206
"resolved_by_id": self.env.user.id,

0 commit comments

Comments
 (0)