fix(bridge_mrp): revert malformed hr_employee.py from conflict-marker commit
a2efc9fcommitted a hr_employee.py with unresolved <<<<<<< HEAD / >>>>>>> Stashed changes markers — Python wouldn't have imported the file. Restoring to f340c87's version. The intended fix (Odoo 19 'in' operator handling) lives on main as0f41eb1.
This commit is contained in:
@@ -22,136 +22,3 @@ class HrEmployee(models.Model):
|
|||||||
help='Which shop roles this employee performs. Used by the '
|
help='Which shop roles this employee performs. Used by the '
|
||||||
'Manager Desk and auto-assignment on WO generation.',
|
'Manager Desk and auto-assignment on WO generation.',
|
||||||
)
|
)
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
# Per-role lead-hand list. Sarah might be a lead hand for masking +
|
|
||||||
# racking but not for plating; Mike might cover everything during
|
|
||||||
# a graveyard shift. Stored on a separate relation table so the
|
|
||||||
# primary "Shop Roles" list stays distinct from the cover-anything
|
|
||||||
# authority.
|
|
||||||
x_fc_lead_hand_role_ids = fields.Many2many(
|
|
||||||
'fp.work.role', 'fp_employee_lead_hand_role_rel',
|
|
||||||
'employee_id', 'role_id', string='Lead Hand For',
|
|
||||||
help='Roles where this employee is authorised to lead or cover '
|
|
||||||
'for an absent operator. Lead hands are surfaced first in '
|
|
||||||
'the Manager Desk worker picker for these roles.',
|
|
||||||
)
|
|
||||||
|
|
||||||
x_fc_proficiency_ids = fields.One2many(
|
|
||||||
'fp.operator.proficiency', 'employee_id',
|
|
||||||
string='Task Proficiency',
|
|
||||||
help='Per-role completion tally. Workers earn one count per WO '
|
|
||||||
'they finish on a given role. Once the count crosses the '
|
|
||||||
"role's mastery threshold the role is added to their "
|
|
||||||
'Shop Roles list automatically.',
|
|
||||||
)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
# Attendance helpers — used by the Manager Desk to show who is
|
|
||||||
# currently clocked in. Works with vanilla hr_attendance or the
|
|
||||||
# full fusion_clock module — both store an open record (no
|
|
||||||
# check_out) for as long as the employee is on shift.
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
x_fc_is_clocked_in = fields.Boolean(
|
|
||||||
string='Clocked In',
|
|
||||||
compute='_compute_x_fc_is_clocked_in',
|
|
||||||
search='_search_x_fc_is_clocked_in',
|
|
||||||
help='True if this employee currently has an open hr.attendance '
|
|
||||||
'record (clocked in but not clocked out).',
|
|
||||||
)
|
|
||||||
|
|
||||||
def _compute_x_fc_is_clocked_in(self):
|
|
||||||
"""Compute attendance status from hr.attendance.
|
|
||||||
|
|
||||||
Batched so the manager dashboard doesn't issue one query per
|
|
||||||
employee — important when the shop has dozens of operators.
|
|
||||||
"""
|
|
||||||
if not self:
|
|
||||||
return
|
|
||||||
Att = self.env.get('hr.attendance')
|
|
||||||
if Att is None:
|
|
||||||
for emp in self:
|
|
||||||
emp.x_fc_is_clocked_in = False
|
|
||||||
return
|
|
||||||
# One read for the whole recordset.
|
|
||||||
open_emp_ids = set(Att.sudo().search([
|
|
||||||
('employee_id', 'in', self.ids),
|
|
||||||
('check_out', '=', False),
|
|
||||||
]).mapped('employee_id').ids)
|
|
||||||
for emp in self:
|
|
||||||
emp.x_fc_is_clocked_in = emp.id in open_emp_ids
|
|
||||||
|
|
||||||
def _search_x_fc_is_clocked_in(self, *args):
|
|
||||||
"""Lets `[('x_fc_is_clocked_in', '=', True)]` work as a domain.
|
|
||||||
|
|
||||||
Odoo 19 normalises the equality term ``('=', True)`` into
|
|
||||||
``('in', OrderedSet([True]))`` before calling this method, so
|
|
||||||
we have to handle ``in`` / ``not in`` as well as the bare
|
|
||||||
``=`` / ``!=``. The signature is also variadic so a future
|
|
||||||
Odoo refactor that prepends a ``records`` argument doesn't
|
|
||||||
break us.
|
|
||||||
|
|
||||||
Strategy:
|
|
||||||
1. Reduce the caller's intent to a *match_set* of booleans
|
|
||||||
— which values of ``x_fc_is_clocked_in`` should match.
|
|
||||||
2. Negative operators flip that set.
|
|
||||||
3. Translate the set into an ``id IN`` (or ``NOT IN``) term
|
|
||||||
on the cached open-attendance employee ids.
|
|
||||||
"""
|
|
||||||
# Variable signature — Odoo 19 may pass (records, op, val).
|
|
||||||
if len(args) == 3:
|
|
||||||
_records, operator, value = args
|
|
||||||
elif len(args) == 2:
|
|
||||||
operator, value = args
|
|
||||||
else:
|
|
||||||
return [('id', '=', False)]
|
|
||||||
|
|
||||||
Att = self.env.get('hr.attendance')
|
|
||||||
if Att is None:
|
|
||||||
return [('id', '=', False)]
|
|
||||||
|
|
||||||
# Build the set of bool values the caller wants.
|
|
||||||
if operator in ('=', '!='):
|
|
||||||
match_set = {bool(value)}
|
|
||||||
elif operator in ('in', 'not in'):
|
|
||||||
# value is a (possibly OrderedSet) iterable of bools.
|
|
||||||
match_set = set(map(bool, value))
|
|
||||||
else:
|
|
||||||
return [('id', '=', False)]
|
|
||||||
|
|
||||||
# Negated operators flip the match set so we can reason in
|
|
||||||
# purely positive terms below.
|
|
||||||
if operator in ('!=', 'not in'):
|
|
||||||
match_set = {True, False} - match_set
|
|
||||||
|
|
||||||
if not match_set:
|
|
||||||
return [('id', '=', False)]
|
|
||||||
if match_set == {True, False}:
|
|
||||||
# No filter at all — every employee matches.
|
|
||||||
return []
|
|
||||||
|
|
||||||
open_emp_ids = Att.sudo().search(
|
|
||||||
[('check_out', '=', False)]
|
|
||||||
).employee_id.ids
|
|
||||||
# Sentinel guards against an empty list — Odoo treats
|
|
||||||
# `('id', 'in', [])` as no constraint in some versions and
|
|
||||||
# ends up matching every row.
|
|
||||||
ids_term = open_emp_ids or [0]
|
|
||||||
return [('id', 'in' if True in match_set else 'not in', ids_term)]
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _fp_clocked_in_user_ids(self):
|
|
||||||
"""Return the set of res.users.ids whose linked employee is on shift.
|
|
||||||
|
|
||||||
Used by the Manager Desk controller to short-circuit the worker
|
|
||||||
dropdown to "present today" without an N+1 attendance query
|
|
||||||
per worker.
|
|
||||||
"""
|
|
||||||
Att = self.env.get('hr.attendance')
|
|
||||||
if Att is None:
|
|
||||||
return set()
|
|
||||||
emps = Att.sudo().search([
|
|
||||||
('check_out', '=', False),
|
|
||||||
]).mapped('employee_id')
|
|
||||||
return set(emps.user_id.ids)
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
|
|||||||
Reference in New Issue
Block a user