Skip to content

[19.0][IMP] base_tier_validation: late / pending / future systray buckets#41

Open
bosd wants to merge 2 commits into
OCA:19.0from
bosd:19.0-imp-base_tier_validation-systray-buckets
Open

[19.0][IMP] base_tier_validation: late / pending / future systray buckets#41
bosd wants to merge 2 commits into
OCA:19.0from
bosd:19.0-imp-base_tier_validation-systray-buckets

Conversation

@bosd
Copy link
Copy Markdown
Contributor

@bosd bosd commented May 14, 2026

Summary

Mirror Odoo's activity systray layout in the tier-review dropdown so reviewers see three buckets per model instead of just one "Pending" column.

Bucket Meaning Visibility
Late pending reviews older than base_tier_validation.late_after_days (default 7) always rendered; muted when 0
Pending pending reviews within the threshold always rendered
Future waiting reviews queued behind sequenced tiers, current user is the reviewer rendered only when count > 0

The headline systray badge now reflects late + pending (work the reviewer must act on now). Future is a heads-up only and is intentionally excluded from the badge so it doesn't inflate urgency.

How it ties to the activity systray pattern

Reference (Odoo's standard activity menu):

Journal Entry / 0 Late / 1 Today / 3 Future

Screenshot From 2026-05-14 17-00-43

Before this pr:
Screenshot From 2026-05-14 17-02-13

This PR produces:

Journal Entry / 0 Late / 1 Pending / 3 Future

image

Tier reviews don't have an explicit due date, so "Today" becomes "Pending (within threshold)" — every other column maps cleanly.

Click-through

Each bucket's record IDs are computed server-side in review_user_count and shipped to the OWL component. Clicking opens an act_window with domain = [("id", "in", <bucket_ids>)] — labels the breadcrumb with the bucket name so the user knows which slice they're looking at.

Configuration

System parameter base_tier_validation.late_after_days controls the late threshold globally. Default 7. Set per-installation via Settings → Technical → Parameters → System Parameters.

Chose a system parameter over per-definition (tier.definition.notify_reminder_delay) because:

  • one knob, no opt-in per definition required for out-of-box value
  • reviewer reminder cadence is an org-wide concern, not a workflow-specific one
  • easy to switch to a per-definition override later without breaking the contract

Test plan

New test test_systray_counter_late_pending_future_buckets:

  • Creates two sequenced tier definitions (tier 1 and tier 2 both pointing at user 1) → user 1 ends up with one pending + one waiting (future) review on the same record.
  • Verifies late_count=0, pending_count=1, future_count=1 at "now".
  • freeze_time-s forward past the 7-day threshold → verifies the count shifts to late_count=1, pending_count=0, future_count=1.
  • Asserts the per-bucket record id lists also reflect the right state.

Existing test_10_systray_counter keeps passing — the pending_count key is preserved with the same semantics for fresh reviews.

Files touched

  • models/res_users.pyreview_user_count extended; new constant DEFAULT_LATE_AFTER_DAYS.
  • static/src/components/tier_review_menu/tier_review_menu.xml — three-column layout.
  • static/src/components/tier_review_menu/tier_review_menu.esm.jsopenReviewGroup(group, bucket).
  • tests/test_tier_validation.py — new test + import of fields and freeze_time.

Screenshots

Will attach runboat screenshots once CI publishes the preview.

Companion PRs

This builds on #23 (icon refresh including the systray glyph) and #30 (AccessError guard in review_user_count). Either order is fine — no merge conflicts expected.

Mirror Odoo's activity systray layout in the tier-review dropdown so
reviewers can see -- and click into -- three buckets per model
instead of just one "Pending" column.

- ``Late`` (red, hidden when 0 only via greyed style): pending reviews
  older than ``base_tier_validation.late_after_days`` system parameter
  (default 7). The reviewer should prioritise these to avoid blocking
  downstream work.
- ``Pending``: pending reviews within the threshold. Standard "act
  today" work; what the systray showed before.
- ``Future`` (only rendered when count > 0): waiting reviews where the
  current user is assigned as reviewer but the sequence has not yet
  promoted the review to pending. "What is incoming for me".

The headline systray badge now reflects late + pending (the work the
reviewer must act on now); future is a heads-up and is intentionally
excluded so it doesn't inflate the urgency badge.

Backend: ``res.users.review_user_count`` returns per-model dicts with
``late_count`` / ``pending_count`` / ``future_count`` plus the
matching record id lists, so clicking a bucket in the systray opens
exactly those records via a server-supplied ``[("id", "in", ids)]``
domain rather than re-running the lookup client-side.

Frontend: the OWL ``tier_review_menu`` template renders the three
columns in the order Late | Pending | Future. Clicking each calls
``openReviewGroup(group, bucket)`` which composes the action's
domain off the bucket-specific id list and labels the breadcrumb
accordingly.

Test exercises both the "fresh" and "older than threshold" cases by
``freeze_time``-ing forward past the late cutoff and asserting the
counts shift from ``pending_count`` into ``late_count`` while the
sequenced waiting review stays in ``future_count``.
@OCA-git-bot
Copy link
Copy Markdown
Contributor

Hi @LoisRForgeFlow,
some modules you are maintaining are being modified, check this out!

@OCA-git-bot OCA-git-bot added mod:base_tier_validation Module base_tier_validation series:19.0 labels May 14, 2026
@bosd bosd force-pushed the 19.0-imp-base_tier_validation-systray-buckets branch from 3f3968b to 4e002c7 Compare May 14, 2026 15:26
…n the systray

Mirror Odoo's activity systray pattern where the dropdown ends with a
"View all activities" link to the global activity dashboard. The
tier-review dropdown gets the same footer when a downstream module
exposes a global review dashboard.

The hook is a new ``tier_review_dashboard_action`` method on
``res.users`` that returns ``False`` by default and can be overridden
by a module shipping a dashboard (e.g. ``base_tier_validation_board``)
to return a serialised ``ir.actions.act_window`` dict. The systray
fetches the action alongside the bucket counts in parallel and
renders the link conditionally on the response. No additional RPC
round-trip cost beyond the single ``Promise.all``.

When no dashboard is exposed (default install, no board module), the
link is simply not rendered -- the dropdown behaves exactly as before.
@bosd bosd force-pushed the 19.0-imp-base_tier_validation-systray-buckets branch from 4e002c7 to 18a1899 Compare May 14, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:base_tier_validation Module base_tier_validation series:19.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants