Files
Odoo-Modules/fusion_accounting_assets/tests/test_asset_anomaly_detection.py
2026-04-19 16:49:02 -04:00

72 lines
2.8 KiB
Python

from odoo.tests.common import TransactionCase
from odoo.tests import tagged
from odoo.addons.fusion_accounting_assets.services.anomaly_detection import (
detect_schedule_variance, detect_low_utilization, AssetAnomaly,
)
@tagged('post_install', '-at_install')
class TestAssetAnomalyDetection(TransactionCase):
def test_schedule_variance_within_threshold_returns_none(self):
# 5% variance < 10% threshold
result = detect_schedule_variance(
asset_id=1, asset_name='Truck', expected_accumulated=10000,
actual_accumulated=10500,
)
self.assertIsNone(result)
def test_schedule_variance_behind_schedule_low_severity(self):
# 15% behind: low severity, behind_schedule
result = detect_schedule_variance(
asset_id=1, asset_name='Truck', expected_accumulated=10000,
actual_accumulated=8500,
)
self.assertIsNotNone(result)
self.assertEqual(result.anomaly_type, 'behind_schedule')
self.assertEqual(result.severity, 'low')
def test_schedule_variance_ahead_high_severity(self):
# 60% ahead: high severity
result = detect_schedule_variance(
asset_id=2, asset_name='Server', expected_accumulated=10000,
actual_accumulated=16000,
)
self.assertIsNotNone(result)
self.assertEqual(result.anomaly_type, 'ahead_of_schedule')
self.assertEqual(result.severity, 'high')
def test_schedule_variance_zero_expected_returns_none(self):
result = detect_schedule_variance(
asset_id=1, asset_name='Truck', expected_accumulated=0,
actual_accumulated=500,
)
self.assertIsNone(result)
def test_low_utilization_flags_when_underused(self):
# 60% deficit -> high severity
result = detect_low_utilization(
asset_id=3, asset_name='Mill', expected_units=1000, actual_units=400,
)
self.assertIsNotNone(result)
self.assertEqual(result.anomaly_type, 'low_utilization')
self.assertEqual(result.severity, 'high')
def test_low_utilization_within_tolerance_returns_none(self):
# 95% used: within 10% tolerance
result = detect_low_utilization(
asset_id=3, asset_name='Mill', expected_units=1000, actual_units=950,
)
self.assertIsNone(result)
def test_anomaly_to_dict_round_trip(self):
anomaly = AssetAnomaly(
asset_id=1, asset_name='X', anomaly_type='behind_schedule',
severity='medium', expected=100.0, actual=70.0, variance_pct=30.0,
detail='example',
)
d = anomaly.to_dict()
self.assertEqual(d['asset_id'], 1)
self.assertEqual(d['anomaly_type'], 'behind_schedule')
self.assertEqual(d['severity'], 'medium')