Skip to main content
iVentureTeam

internal_resume_lines

New in Odoo 19: internal_resume_lines writes the employee's internal career history for you, computed from version records, no manual resume entry required. It is the block titled with your company name above the editable resume.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 26, 2026Updated August 26, 20265 min read
Technical nameinternal_resume_lines
Viewsform (view widget, element)
Modulehr_skills (installed with Skills Management)
Used in core2 occurrences in hr_skills: the employee form and the user profile form, both right above resume_one2many
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. The block appears automatically with hr_skills; Studio cannot add or configure it
Alternativesresume_one2many, skills_one2many, hr_org_chart

What the internal resume widget does

Odoo 19 reworked employee records around versions: every contract change, job change or timeline event is an hr.version row. internal_resume_lines is the widget that turns that raw history into something people actually read, an automatic Experience section on the resume tab, listing the employee's roles at your company with start and end dates, current role marked Current.

It is a view widget with no options and no value of its own. On mount it calls a single server method, get_internal_resume_lines, and renders the returned entries as a timeline styled like a grouped list, headed by Experience and the company name. The editable resume lines, the resume_one2many field widget, sit directly beneath it in both core placements.

What this means for your team

Manual resume upkeep is the first thing HR teams abandon. Titles change, promotions happen, and the resume tab quietly rots. This widget removes the internal half of that chore: as long as versions are maintained, which payroll and contracts force anyway, the employee's in-company career writes itself. Only external history, previous employers and education, still needs manual entry below.

The dual placement matters for self-service. The same block renders on the user's own profile form, so employees see their computed career path without HR access, and the underlying access check through the public employee model keeps it safe to expose.

Working examples

How core places it

<!-- Adding fields in the list arch below makes them accessible to the widget -->
<widget name="internal_resume_lines"/>
<field mode="list" name="resume_line_ids" widget="resume_one2many"/>

From hr_skills/views/hr_views.xml. The widget needs no configuration; the pairing with resume_one2many is convention, not requirement.

The server call it makes

self.env['hr.employee'].get_internal_resume_lines(res_id, res_model)
# res.users ids are mapped to their employee first
# raises AccessError without read access to hr.employee.public

How versions become resume entries

The interesting logic is all server side, in hr_skills/models/hr_employee.py. The method walks the employee's version_ids in order and emits one entry per contiguous stretch of the same job title, computing each stretch's start as the later of the version date and the contract start, and its end from the next version's date or the contract end. Versions without a job title close the running interval, and gaps between contracts split entries, so a rehire shows as two stints. The entries carry the version's id, job title and the date pair, nothing else, which is exactly what the template prints.

Client side, two details are easy to miss. The dates are formatted through Odoo's locale-aware formatDate, so the timeline follows the user's date format. And the empty-state paragraph, there are no resume lines on this employee, is gated by haveResumeLines, which is true if either the computed internal lines or the manual resume_line_ids have content, so the hint disappears as soon as anything at all is on the resume.

Version compatibility

VersionStatusNotes
Odoo 20.0VerifiedNot released. Rewritten onto asyncComputed reactive state; same contract. See below.
Odoo 19.0VerifiedIntroduced in 19.0 alongside the hr.version rework. Verified against the shipped source.
Odoo 18.0Not availableDoes not exist; the resume tab shows only manual resume lines.
Odoo 17.0Not availableDoes not exist.
Odoo 16.0Not availableDoes not exist.

Upgrade note. Coming from 18 or earlier there is nothing to migrate: the widget did not exist and appears automatically with hr_skills on 19. The quality of the timeline is entirely a function of your version data, so a migration that collapses contract history into a single version yields a one-line resume.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We read the widget's file on the public development branch at the time of writing; the branch is unstable and this page will be re-verified after release.

The component is rewritten onto asyncComputed: the resume lines become reactive state with an initial empty array, recomputed automatically when the record changes, replacing 19's onWillStart and onWillUpdateProps pair, and internalResumeLines becomes a callable in the template. Registration, dependencies and the server method contract are unchanged, so only JavaScript patches are affected.

Common problems and fixes

SymptomCause and fix
The Experience block is empty for an employee with years of historyThe timeline is computed from hr.version records; missing or collapsed versions yield no entries. Check the employee's version history; entries need job titles and dates on the versions.
AccessError when opening the resume tabThe server method requires read access to hr.employee.public for the target employee. Grant the user the base employee visibility or restrict the form instead.
The block header shows the wrong companyThe header prints the record's company_id display name, auto-loaded by the widget. Correct the employee's company; multi-company setups show the employee's own company.
One long stint shows where two roles existedConsecutive versions share the same job title, so they merge into one entry by design. Give the versions distinct job titles; the split follows title changes and contract gaps.
Widget shows nothing on a custom model's formThe server method only understands hr.employee and res.users (mapped to its employee). Keep the widget on employee or user forms, or extend get_internal_resume_lines.

Internal resume widget vs the alternatives

WidgetBest forKey difference
internal_resume_linesThe automatic in-company experience timeline on the resume tabRead-only and computed from hr.version history; nothing is typed or stored
resume_one2manyManually maintained resume entries, external experience and educationAn editable one2many grouped by line type; users create and edit rows
skills_one2manyThe skills matrix on the same tabEditable skills grouped by skill type, with levels and progress
hr_org_chartThe reporting hierarchy rather than the career historyFetches the manager chain live from its own controller

This widget owns the computed, read-only half of the resume. Anything a human should type still belongs to the editable resume and skills widgets beneath it.

Frequently asked questions

Where does internal_resume_lines get its data?+
From one ORM call to hr.employee.get_internal_resume_lines, which walks the employee's hr.version records and returns entries built from job title changes and contract date gaps. Nothing is stored on the resume itself.
Why did this widget only appear in Odoo 19?+
It rides on the 19.0 employee versioning rework: hr.version made the underlying career history queryable, and hr_skills added this widget to surface it. Earlier versions have no equivalent data to render.
Can employees see their own computed resume?+
Yes. The second core placement is on the user profile form, and the server maps a res.users id to its employee before checking access against the public employee model.
Can I edit or hide individual computed entries?+
No. The block is read-only and has no options; correcting an entry means correcting the version records it is computed from. Hiding the whole block is a view inheritance removing the widget element.
What does Current mean on an entry?+
The entry has no end date, the role is ongoing. The template prints Current in place of the end date, using your locale's date format for the rest.
Why does the no-resume-lines message not show even though this block is empty?+
The empty-state text renders only when both the computed internal lines and the manual resume_line_ids are empty; content in either suppresses it.

Getting real value out of Odoo 19's employee versioning?

The new version model powers timelines like this widget, but only if your migration carries contract history over cleanly. We plan hr.version data mapping during Odoo migrations so features like the automatic resume work on day one instead of rendering empty.

Plan your HR data migration

How this page was produced

Behavior was read from internal_resume_one2many.js, its QWeb template and hr_employee.get_internal_resume_lines on the Odoo 19.0 branch, compared against the development branch for the Odoo 20 section, and the two placements were verified in hr_skills/views/hr_views.xml. The widget does not exist in 18 or earlier, which we confirmed in those trees. Spotted an error? Tell us and we will correct the page.