feat(quality_dashboard): banner with overdue + critical (Task 4)

_fetch_banner_candidates collects (overdue) OR (critical-customer +
open) records per type. _critical_customer_ids reuses partner.x_fc_rush
and partner.x_fc_vip flags when defined (gracefully no-ops when
absent). _critical_badge returns RUSH/VIP/AEROSPACE/AS9100 label
when the banner reason is critical-customer (no badge when overdue).
_build_banner ranks: overdue first by oldest, then critical-customer
by oldest, takes top 6, reports total_matching.

build() now collects banner candidates from every section in one
pass + invokes _build_banner once.

Tests cover overdue hold pickup, 6-cap with overflow count, and
all_clear when DB is empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-25 12:22:01 -04:00
parent e271908109
commit 40d563801a
2 changed files with 200 additions and 3 deletions

View File

@@ -109,3 +109,64 @@ class TestDashboardSnapshotItems(TransactionCase):
self.assertEqual(item['open_action']['res_model'],
'fusion.plating.quality.hold')
self.assertEqual(item['open_action']['res_id'], hold.id)
class TestDashboardSnapshotBanner(TransactionCase):
"""Banner population + ranking."""
def _build(self):
from odoo.addons.fusion_plating_quality.controllers.fp_quality_dashboard \
import FpQualityDashboardSnapshot
return FpQualityDashboardSnapshot(self.env).build()
def test_banner_picks_up_overdue_hold(self):
from datetime import datetime, timedelta
if 'fusion.plating.quality.hold' not in self.env:
self.skipTest('fusion.plating.quality.hold not installed')
partner = self.env['res.partner'].create({'name': 'Cust'})
hold = self.env['fusion.plating.quality.hold'].create({
'partner_id': partner.id, 'state': 'on_hold', 'reason': 'old',
})
# Backdate create_date past the 3-day overdue threshold
old = datetime.now() - timedelta(days=5)
self.env.cr.execute(
"UPDATE fusion_plating_quality_hold SET create_date = %s WHERE id = %s",
(old, hold.id),
)
hold.invalidate_recordset(['create_date'])
snap = self._build()
self.assertFalse(snap['banner']['all_clear'])
self.assertEqual(snap['banner']['total_matching'], 1)
self.assertEqual(len(snap['banner']['items']), 1)
item = snap['banner']['items'][0]
self.assertEqual(item['type'], 'hold')
self.assertEqual(item['urgency'], 'overdue')
def test_banner_caps_at_6_with_overflow_count(self):
from datetime import datetime, timedelta
if 'fusion.plating.quality.hold' not in self.env:
self.skipTest('fusion.plating.quality.hold not installed')
partner = self.env['res.partner'].create({'name': 'Cust'})
Hold = self.env['fusion.plating.quality.hold']
# 8 overdue holds
old = datetime.now() - timedelta(days=5)
for i in range(8):
h = Hold.create({
'partner_id': partner.id, 'state': 'on_hold',
'reason': f'overdue {i}',
})
self.env.cr.execute(
"UPDATE fusion_plating_quality_hold SET create_date = %s WHERE id = %s",
(old, h.id),
)
snap = self._build()
self.assertEqual(len(snap['banner']['items']), 6)
self.assertEqual(snap['banner']['total_matching'], 8)
self.assertFalse(snap['banner']['all_clear'])
def test_banner_all_clear_when_zero(self):
snap = self._build()
# Empty DB — no overdue, no critical
self.assertTrue(snap['banner']['all_clear'])
self.assertEqual(snap['banner']['items'], [])