Skip to main content
iVentureTeam

hr_presence_status_private

An employee presence indicator that Odoo 19 registers for form views only. Odoo 20 both lifts that restriction and quietly changes how it looks.

September 18, 2026Updated September 18, 20264 min read
Technical namehr_presence_status_private
Field typesselection
Viewsform
Form variantform.hr_presence_status_private is the only registration in Odoo 19
Modulehr, installed with the Employees app
Used in core0 uses in Odoo 19 Community or Enterprise, and 0 in Odoo 20.
VersionsOdoo 19.0, Odoo 20.0
No-code setupNo. There is no Studio entry for this widget.
Alternativesbadge, selection_badge, state_selection

What the hr_presence_status_private widget does

In Odoo 19 this is an empty subclass. The whole file is a class that adds nothing, a descriptor that swaps in that class, and one registration:

export class HrPresenceStatusPrivatePill extends HrPresenceStatusPill {}

export const hrPresenceStatusPrivatePill = {
    ...hrPresenceStatusPill,
    component: HrPresenceStatusPrivatePill,
};

registry.category("fields").add("form.hr_presence_status_private", hrPresenceStatusPrivatePill);

All the visible behavior comes from the pill it extends, which renders the status as a rounded outline button and picks the color from the value: success for present, warning for absent, muted secondary for out of working hours or archived.

The separate class exists so that other modules can patch the private variant without affecting the public one.

What this means for your team

Presence status is one of the more sensitive things an HR screen displays, which is why Odoo keeps a separate private variant at all. The variant is the hook a module uses to show more to an HR officer than to a colleague.

What matters for a rollout is that this widget is not used anywhere in standard Odoo. If you see presence indicators on your employee screens, they are coming from a different widget in the same family. This one exists as an extension point.

Working examples

In Odoo 19, on an employee form. The prefix is chosen by the view, so you write the bare name:

<field name="hr_presence_state" widget="hr_presence_status_private"/>

In Odoo 19 that same line in a list view resolves to nothing, because no unprefixed registration exists. In Odoo 20 it works in both.

What Odoo 20 changes, and why it is easy to miss

Two changes land together, and only one of them is obvious.

The obvious one is scope. Odoo 19 registers form.hr_presence_status_private and nothing else. When Odoo resolves a widget it tries the view-prefixed key first and then the bare one, so in a list or kanban view there is no match at all and the field falls back to its default rendering. Odoo 20 registers the bare hr_presence_status_private, so it resolves everywhere.

The quiet one is appearance. In Odoo 19 the class extends the pill:

export class HrPresenceStatusPrivatePill extends HrPresenceStatusPill {}

In Odoo 20 it extends the base status component instead:

export class HrPresenceStatusPrivate extends HrPresenceStatus { }

HrPresenceStatusPill is what supplies the rounded outline button and the btn-outline-success and btn-outline-warning color classes. Extending the base instead means that styling is gone in Odoo 20.

So a field that showed a colored pill in Odoo 19 shows the plain status rendering after an upgrade. Nothing errors, no option changed, and a diff of the registration alone would report only the prefix change. The visual difference only shows up if you read which class is being extended.

If your database patches this widget, check the patch too: it was written against a subclass of the pill and now sits on a subclass of the base.

Version compatibility

VersionStatusNotes
Odoo 19.0VerifiedRegistered for form views only, rendered as a colored pill.
Odoo 20.0Partial / changedPrefix dropped so it works in any view, but the pill styling is gone.

Both the registration and the base class change in Odoo 20.

What is changing in Odoo 20

The form. prefixed registration is removed and replaced by a bare hr_presence_status_private, so the widget becomes usable in every view rather than forms only. The file also moves, from components/hr_presence_status_private_pill/ to components/hr_presence_status_private/.

Alongside that, the component's base class changes from HrPresenceStatusPill to HrPresenceStatus, which removes the rounded pill styling and its outline colors. Expect the indicator to look different after an upgrade even though no option changed.

The sibling hr_presence_status keeps its own form. variant, so the two are no longer registered the same way.

Common problems and fixes

SymptomCause and fix
The widget has no effect in a list or kanban view on Odoo 19Only form.hr_presence_status_private is registered, so there is no match outside a form. Use it on a form, or upgrade to Odoo 20 where the bare registration exists.
The pill styling disappeared after upgrading to Odoo 20The component's base class changed from HrPresenceStatusPill to HrPresenceStatus, which drops the rounded button and outline colors. Style it yourself, or extend the pill component in a custom widget.
A patch on this widget stopped applying after upgradeThe file moved and the class it extends changed. Repoint the patch at the new path and check it against the base component rather than the pill.

Hr_presence_status_private widget vs the alternatives

WidgetBest forKey difference
hr_presence_status_privateThe private employee presence indicator as an extension pointForm-only in Odoo 19, and its styling changes in Odoo 20
badgeAny status shown as a colored badgeGeneric, with real options and no HR dependency
selection_badgeA selection rendered as clickable badgesEditable, and shows every value
state_selectionA status with a colored dotDifferent visual language and widely used in core

For a general status field, badge or selection_badge give you colored rendering with real options and no dependency on the HR module. Use this widget only where you specifically want the private presence variant as an extension point.

Frequently asked questions

Why does hr_presence_status_private not work in a list view in Odoo 19?+
Because Odoo 19 registers it only as form.hr_presence_status_private. Odoo resolves the view-prefixed key first and then the bare one, and there is no bare registration, so outside a form nothing matches. Odoo 20 adds the bare registration.
Why does the presence pill look different after upgrading to Odoo 20?+
The component's base class changed from HrPresenceStatusPill to HrPresenceStatus. The pill supplied the rounded outline button and its color classes, so extending the base instead removes that styling. No option changed.
Does hr_presence_status_private have options?+
None of its own. It spreads the presence status descriptor and adds only a component, which in Odoo 19 is an empty subclass of the pill.

Employee data visible to the wrong people?

Presence, contracts and payroll all sit on the same employee record, and Odoo's defaults are not a policy. We set up HR access so managers, officers and colleagues each see exactly what they should.

Request an access rights audit

How this page was produced

Verified by reading addons/hr/static/src/components/hr_presence_status_private_pill/hr_presence_status_private_pill.js and its parent hr_presence_status_pill.js on the 19.0 branch of a local clone of the official Odoo repository, then reading the replacement at addons/hr/static/src/components/hr_presence_status_private/hr_presence_status_private.js on the 20.0 branch. Both class declarations are quoted verbatim. The color classes come from the pill's color getter. Corrections welcome via our contact page.