From d5e79cdc10f8a9af71e896c756b19851ae6e430e Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Thu, 21 May 2026 03:47:24 -0400 Subject: [PATCH] feat(fusion_claims): add dashboard banner fields Co-Authored-By: Claude Opus 4.7 (1M context) --- fusion_claims/models/dashboard.py | 47 +++++++++++++++++++++++++++ fusion_claims/tests/test_dashboard.py | 34 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/fusion_claims/models/dashboard.py b/fusion_claims/models/dashboard.py index ee9e4361..03ab31e3 100644 --- a/fusion_claims/models/dashboard.py +++ b/fusion_claims/models/dashboard.py @@ -41,3 +41,50 @@ class FusionClaimsDashboard(models.TransientModel): if self.is_manager: return [] return [('user_id', '=', self.env.user.id)] + + # ========================================================================= + # Header banner + # ========================================================================= + posting_period_label = fields.Char(compute='_compute_banner') + posting_period_start = fields.Date(compute='_compute_banner') + posting_period_end = fields.Date(compute='_compute_banner') + submission_deadline_dt = fields.Datetime(compute='_compute_banner') + is_pre_first_posting = fields.Boolean(compute='_compute_banner') + + def _compute_banner(self): + from datetime import date, datetime, time, timedelta + import pytz + + today = date.today() + for rec in self: + base_date = rec._get_adp_posting_base_date() + rec.is_pre_first_posting = today < base_date + + current = rec._get_current_posting_date(today) + nxt = rec._get_next_posting_date(today) + # If we're sitting on a posting date, current == next; treat + # the period as the one starting today. + if current == nxt: + period_start = current + period_end = current + timedelta(days=rec._get_adp_posting_frequency()) + else: + period_start = current + period_end = nxt + + rec.posting_period_start = period_start + rec.posting_period_end = period_end + + if rec.is_pre_first_posting: + rec.posting_period_label = f"Posting starts {base_date.strftime('%b %d')}" + else: + rec.posting_period_label = ( + f"{period_start.strftime('%b %d')} – " + f"{period_end.strftime('%b %d')}" + ) + + wednesday = rec._get_posting_week_wednesday(nxt) + naive_deadline = datetime.combine(wednesday, time(18, 0, 0)) + # Store as UTC; users see it in their TZ; OWL widget computes in local TZ. + tz = pytz.timezone(rec.env.user.tz or 'America/Toronto') + local_deadline = tz.localize(naive_deadline) + rec.submission_deadline_dt = local_deadline.astimezone(pytz.UTC).replace(tzinfo=None) diff --git a/fusion_claims/tests/test_dashboard.py b/fusion_claims/tests/test_dashboard.py index 9fb6e99c..0f88d8c1 100644 --- a/fusion_claims/tests/test_dashboard.py +++ b/fusion_claims/tests/test_dashboard.py @@ -57,3 +57,37 @@ class TestFusionClaimsDashboard(TransactionCase): def test_is_manager_false_for_salesrep(self): dashboard = self.Dashboard.with_user(self.salesrep).create({}) self.assertFalse(dashboard.is_manager) + + # ------------------------------------------------------------------------- + # Task 2 — Banner + # ------------------------------------------------------------------------- + def test_banner_posting_period_label_format(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + label = dashboard.posting_period_label + self.assertTrue(any(month in label + for month in ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']), + "Label should contain a month abbreviation") + + def test_banner_posting_period_start_and_end_are_dates(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + self.assertTrue(dashboard.posting_period_start) + self.assertTrue(dashboard.posting_period_end) + delta = (dashboard.posting_period_end - dashboard.posting_period_start).days + self.assertEqual(delta, 14) + + def test_banner_submission_deadline_is_wednesday_6pm(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + deadline = dashboard.submission_deadline_dt + self.assertTrue(deadline, "Deadline should be set") + # Stored in UTC; convert to user's TZ to assert the wall-clock weekday/hour + import pytz + tz = pytz.timezone(self.manager.tz or 'America/Toronto') + local = pytz.UTC.localize(deadline).astimezone(tz) + self.assertEqual(local.weekday(), 2, "Deadline should be Wednesday") + self.assertEqual(local.hour, 18, "Deadline should be 18:00 (6 PM)") + + def test_is_pre_first_posting_false_when_today_is_past_base_date(self): + # Test runs after 2026-01-23 by default. + dashboard = self.Dashboard.with_user(self.manager).create({}) + self.assertFalse(dashboard.is_pre_first_posting)