Skip to content

[18.0][ADD] project_multi_department#1674

Draft
cvinh wants to merge 1 commit intoOCA:18.0from
invitu:18.0-project_multi_department
Draft

[18.0][ADD] project_multi_department#1674
cvinh wants to merge 1 commit intoOCA:18.0from
invitu:18.0-project_multi_department

Conversation

@cvinh
Copy link

@cvinh cvinh commented Feb 21, 2026

This module allows link between project and hr_department. It's many2many field (not many2one like project_department module)

@cvinh
Copy link
Author

cvinh commented Feb 21, 2026

tests fail because of sale_project_task_selection

@cvinh cvinh force-pushed the 18.0-project_multi_department branch from 76d2a21 to e815441 Compare February 22, 2026 05:00
Copy link

@luisDIXMIT luisDIXMIT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on runboat, LGTM!

Copy link
Contributor

@alexey-pelykh alexey-pelykh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting concept — multi-department assignment on projects with record rules is useful. A few things:

  • Tests are failing on OCB and Odoo CI, so something needs attention there
  • I don't see any test files in the PR — given the security rules, tests covering department-based access would be important
  • The child_of operator in the record rule domain means child departments also get access, which is nice but should be tested

Happy to re-review once CI is green and tests are added.

Copy link
Contributor

@alexey-pelykh alexey-pelykh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this contribution -- multi-department assignment on projects is a useful addition to the OCA ecosystem, especially alongside the existing single-department project_department module.

After reviewing the code, manifest, views, and security rules, I have several findings that should be addressed before this can be merged.


Critical: No Tests

This module introduces ir.rule security restrictions that filter projects and tasks by department membership. Without automated tests, there is no verification that:

  • A user in Department A can access projects assigned to Department A
  • A user in Department A cannot access projects assigned only to Department B
  • The child_of operator correctly grants access to child departments
  • Projects/tasks with no department assigned are visible to all users
  • The related department_ids on project.task works correctly for tasks with and without a project

Please add a tests/ directory with at least one test case covering the record rule behavior.

Critical: Security Rules May Lock Out Users Without Employees

The record rules reference user.employee_id.department_id.id. If a user has no linked employee (e.g., admin users, portal users, newly created internal users), employee_id is a falsy recordset and department_id.id evaluates to False.

The domain ('department_ids', 'child_of', [False]) may produce unexpected results depending on the Odoo version. Consider adding a condition that also grants access when the user has no department:

[
    '|',
    '|',
    ('department_ids', '=', False),
    ('department_ids', 'child_of', [user.employee_id.department_id.id]),
    ('department_ids', 'in', user.employee_ids.department_id.ids),
]

Also, the rules have no groups attribute, so they apply to all users globally (including portal and public). Consider restricting them to the base.group_user group at minimum.

Important: Missing ir.model.access.csv

The Many2many field between project.project and hr.department creates a relation table. While OCA CI may not always enforce it, best practice is to include a security/ir.model.access.csv file -- even if it's empty or only contains access for the implicit relation model.

Important: Missing installable Key in Manifest

OCA convention is to explicitly declare "installable": True in __manifest__.py. While it defaults to True, being explicit improves clarity.

Important: Missing i18n Infrastructure

OCA modules should include an i18n/ directory with at least a .pot file for translations. This can be generated with oca-gen-addon-readme or by exporting translations.

Minor: Related Field on Tasks for Private Tasks

The department_ids field on project.task is defined as:

department_ids = fields.Many2many(related="project_id.department_ids")

Tasks can exist without a project (project_id = False), e.g., private tasks. The related field will be empty in that case, which is functionally fine but worth a note in the documentation or a test to confirm behavior.

Minor: Typo in CONTRIBUTORS.md

The contributor line has a stray > character:

- Cyril VINH-TUNG \<cyril@invitu.com>\>

Should be:

- Cyril VINH-TUNG <cyril@invitu.com>

Overall the approach is sound and the module fills a real gap. The main blockers are the missing tests and the security rule edge cases. Happy to re-review once those are addressed.

Review posted via CorporateHub OCA review campaign

<field name="model_id" ref="model_project_project" />
<field name="domain_force">[
'|',
('department_ids', 'child_of', [user.employee_id.department_id.id] ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The domain uses user.employee_id.department_id.id -- if the user has no linked employee record, this evaluates to False. Combined with child_of, this may produce unexpected behavior (potentially hiding all projects from admin users or users without HR employee records).

Consider:

  1. Adding a third '|' branch for users without a department (e.g., ('department_ids', '!=', False) negated, or checking user.employee_id)
  2. Restricting this rule to base.group_user via a groups attribute so portal/public users are not affected

Example with user-without-department handling:

<field name="domain_force">[
    '|',
    ('department_ids', '=', False),
    '|',
    ('department_ids', 'child_of', user.employee_id.department_id.ids),
    ('department_ids', 'in', user.employee_ids.department_id.ids),
]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]" />

Note: using .ids (plural) instead of [.id] is safer when the recordset may be empty.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with adding the group.
On the other hand, I don't get the problem if the employee has no department or the user has no employee... in both cases, we don't want that user to access projects with department set up...

<field name="model_id" ref="model_project_task" />
<field name="domain_force">[
'|',
('department_ids', 'child_of', [user.employee_id.department_id.id] ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as the project rule above -- user.employee_id.department_id.id is unsafe for users without an employee record, and the rule lacks a groups restriction.

Please apply the same fix as suggested for the project rule.

"project",
"hr",
],
"data": ["security/project_security.xml", "views/project_project_views.xml"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things to add to the manifest:

  1. "installable": True -- OCA convention is to be explicit
  2. Consider adding "security/ir.model.access.csv" to the data list if you add access rights for the implicit Many2many relation table

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Consider adding "security/ir.model.access.csv" to the data list if you add access rights for the implicit Many2many relation table

I never saw access rights on a relation table, can you humanly confirm that please (not with AI) ?

@cvinh cvinh marked this pull request as draft March 3, 2026 08:29
@cvinh cvinh force-pushed the 18.0-project_multi_department branch from e815441 to 4cc7219 Compare March 12, 2026 00:53
@cvinh cvinh force-pushed the 18.0-project_multi_department branch from 4cc7219 to 9fe391a Compare March 12, 2026 17:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants