167 lines
7.2 KiB
Python
167 lines
7.2 KiB
Python
import hashlib
|
|
from odoo import models, fields, api, _
|
|
|
|
class HrEmployee(models.Model):
|
|
_inherit = 'hr.employee'
|
|
|
|
company_ids = fields.Many2many(
|
|
'res.company',
|
|
string='Branches',
|
|
domain="[('parent_id', '!=', False)]",
|
|
help="Branch companies this employee is associated with."
|
|
)
|
|
|
|
# Overriding company_id to be computed from company_ids
|
|
# This maintains compatibility with standard Odoo logic that expects a single company_id
|
|
company_id = fields.Many2one(
|
|
'res.company',
|
|
string='Company',
|
|
compute='_compute_company_id',
|
|
store=True,
|
|
readonly=False,
|
|
required=True,
|
|
help="The primary company of the employee. Automatically set to the first branch in Branches."
|
|
)
|
|
|
|
attendance_manager_id = fields.Many2one(
|
|
'res.users',
|
|
domain="[('share', '=', False), ('company_ids', 'in', company_ids)]"
|
|
)
|
|
|
|
@api.model
|
|
def _register_hook(self):
|
|
super()._register_hook()
|
|
rules_to_update = {
|
|
'stock.stock_picking_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_picking_type_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_putaway_rule_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_production_lot_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_warehouse_comp_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_location_comp_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_move_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_move_line_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_quant_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_warehouse_orderpoint_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.product_pulled_flow_comp_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_location_route_comp_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_package_comp_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
'stock.stock_scrap_company_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.report_stock_quantity_flow_comp_rule': "[('company_id', 'in', user.company_ids.ids)]",
|
|
'stock.stock_storage_category_rule': "[('company_id', 'in', user.company_ids.ids + [False])]",
|
|
}
|
|
for xml_id, domain in rules_to_update.items():
|
|
rule = self.env.ref(xml_id, raise_if_not_found=False)
|
|
if rule and rule.domain_force != domain:
|
|
rule.sudo().write({'domain_force': domain})
|
|
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
employees = super().create(vals_list)
|
|
employees.sudo()._sync_user_company_ids()
|
|
return employees
|
|
|
|
def write(self, vals):
|
|
res = super().write(vals)
|
|
if any(f in vals for f in ['company_ids', 'company_id', 'user_id']):
|
|
self.sudo()._sync_user_company_ids()
|
|
return res
|
|
|
|
def _sync_user_company_ids(self):
|
|
for employee in self:
|
|
if employee.user_id:
|
|
user = employee.user_id
|
|
employee_companies = employee.company_ids | employee.company_id
|
|
companies_to_add = employee_companies - user.company_ids
|
|
if companies_to_add:
|
|
user.write({
|
|
'company_ids': [(4, cid.id) for cid in companies_to_add]
|
|
})
|
|
|
|
@api.depends('company_ids')
|
|
def _compute_company_id(self):
|
|
for employee in self:
|
|
if employee.company_ids:
|
|
employee.company_id = employee.company_ids[0]
|
|
elif employee.company_id:
|
|
# Sync company_ids from company_id for existing records
|
|
employee.company_ids = [(6, 0, [employee.company_id.id])]
|
|
else:
|
|
employee.company_id = self.env.company
|
|
employee.company_ids = [(6, 0, [self.env.company.id])]
|
|
|
|
@api.model
|
|
def _search(self, domain, offset=0, limit=None, order=None, **kwargs):
|
|
""" Override search to include company_ids and fallback to company_id if empty """
|
|
def replace_company_leaf(dom):
|
|
if not dom:
|
|
return dom
|
|
new_dom = []
|
|
for leaf in dom:
|
|
if isinstance(leaf, (list, tuple)):
|
|
if leaf[0] == 'company_id':
|
|
# Match if Branch is in search OR (Branch is empty AND Company is in search)
|
|
new_dom.append('|')
|
|
new_dom.append(('company_ids', leaf[1], leaf[2]))
|
|
new_dom.append('&')
|
|
new_dom.append(('company_ids', '=', False))
|
|
new_dom.append(('company_id', leaf[1], leaf[2]))
|
|
else:
|
|
new_dom.append(leaf)
|
|
elif isinstance(leaf, list):
|
|
new_dom.append(replace_company_leaf(leaf))
|
|
else:
|
|
new_dom.append(leaf)
|
|
return new_dom
|
|
|
|
if domain:
|
|
domain = replace_company_leaf(domain)
|
|
return super()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
|
|
|
|
|
|
@api.model
|
|
def _load_pos_data_read(self, records, config):
|
|
"""Override to read employee data (including work_contact_id / res.partner)
|
|
with sudo() so cashier users whose user.company_ids doesn't include the
|
|
employee partner's company_id don't get a read access error on session open.
|
|
The employee records are already filtered by _load_pos_data_domain before
|
|
arriving here, so sudo() is safe — we're only relaxing the partner rule.
|
|
"""
|
|
fields = self._load_pos_data_fields(config)
|
|
# Read with sudo to bypass res.partner multi-company rule for work_contact_id
|
|
read_records = records.sudo().read(fields, load=False)
|
|
manager_ids = records.filtered(
|
|
lambda emp: config.group_pos_manager_id.id in emp.user_id.all_group_ids.ids
|
|
).ids
|
|
|
|
employees_barcode_pin = records.get_barcodes_and_pin_hashed()
|
|
bp_per_employee_id = {bp_e['id']: bp_e for bp_e in employees_barcode_pin}
|
|
|
|
for employee in read_records:
|
|
if employee['id'] in manager_ids:
|
|
role = 'manager'
|
|
employee['_user_role'] = 'admin'
|
|
elif employee['id'] in config.advanced_employee_ids.ids:
|
|
role = 'manager'
|
|
elif employee['id'] in config.minimal_employee_ids.ids:
|
|
role = 'minimal'
|
|
else:
|
|
role = 'cashier'
|
|
|
|
employee['_role'] = role
|
|
employee['_barcode'] = bp_per_employee_id[employee['id']]['barcode']
|
|
employee['_pin'] = bp_per_employee_id[employee['id']]['pin']
|
|
|
|
return read_records
|
|
|
|
|
|
class HrEmployeePublic(models.Model):
|
|
_inherit = 'hr.employee.public'
|
|
|
|
company_ids = fields.Many2many(
|
|
'res.company',
|
|
related='employee_id.company_ids',
|
|
readonly=True,
|
|
string='Branches'
|
|
)
|