From e8c48f824e078d643a3385fb910707d5525e927d Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Thu, 4 May 2023 16:45:08 +0200 Subject: [PATCH] [IMP] hr: Remove address_home_id field Improve usability of employee form. It is confusing for end users to create another record to encode the employee address. Move all the private information on the hr.employee record itself. Remove the M2O address_home_id. TaskID: 3101400 --- addons/hr/__manifest__.py | 2 +- addons/hr/data/hr_data.xml | 9 +- addons/hr/data/hr_demo.xml | 931 +++++++++--------- addons/hr/models/__init__.py | 2 +- addons/hr/models/hr_employee.py | 62 +- addons/hr/models/hr_employee_base.py | 22 - addons/hr/models/hr_employee_public.py | 7 - addons/hr/models/res_partner.py | 16 +- addons/hr/models/res_users.py | 28 +- addons/hr/tests/test_self_user_access.py | 3 +- addons/hr/views/hr_employee_views.xml | 44 +- addons/hr/views/res_users.xml | 23 +- addons/hr/wizard/hr_departure_wizard.py | 7 - .../hr/wizard/hr_departure_wizard_views.xml | 4 +- .../hr_contract/views/hr_contract_views.xml | 3 - addons/hr_expense/data/hr_expense_demo.xml | 23 +- addons/hr_expense/models/hr_expense.py | 12 +- addons/hr_expense/tests/common.py | 2 +- addons/hr_expense/tests/test_expenses.py | 2 +- .../tests/test_expenses_access_rights.py | 2 +- addons/hr_fleet/data/hr_fleet_demo.xml | 2 +- addons/hr_fleet/models/employee.py | 14 +- addons/hr_fleet/models/fleet_vehicle.py | 14 +- .../models/fleet_vehicle_assignation_log.py | 4 +- .../models/fleet_vehicle_log_services.py | 2 +- addons/hr_fleet/wizard/hr_departure_wizard.py | 2 +- addons/hr_holidays/models/hr_leave.py | 2 +- addons/hr_recruitment/models/hr_applicant.py | 11 +- 28 files changed, 562 insertions(+), 693 deletions(-) diff --git a/addons/hr/__manifest__.py b/addons/hr/__manifest__.py index cc7a2915d63..9713f4aa208 100644 --- a/addons/hr/__manifest__.py +++ b/addons/hr/__manifest__.py @@ -34,9 +34,9 @@ 'views/hr_work_location_views.xml', 'views/hr_views.xml', 'views/res_config_settings_views.xml', + 'views/res_partner_views.xml', 'views/discuss_channel_views.xml', 'views/res_users.xml', - 'views/res_partner_views.xml', 'views/hr_templates.xml', 'data/hr_data.xml', ], diff --git a/addons/hr/data/hr_data.xml b/addons/hr/data/hr_data.xml index 295e85ee366..fc9d9d5942c 100644 --- a/addons/hr/data/hr_data.xml +++ b/addons/hr/data/hr_data.xml @@ -6,19 +6,12 @@ Administration - - Administrator - - admin@example.com - private - - - + admin@example.com diff --git a/addons/hr/data/hr_demo.xml b/addons/hr/data/hr_demo.xml index 40526622fe3..0ce3e518753 100644 --- a/addons/hr/data/hr_demo.xml +++ b/addons/hr/data/hr_demo.xml @@ -2,46 +2,54 @@ - Sales - - Management - + + + Management + - - Research & Development - + + Research & Development + - - R&D USA - - + + R&D USA + + - - Long Term Projects - - + + Long Term Projects + + - - Professional Services - + + Professional Services + + + + Permanent + 1 + - - - Interim - 3 - + + Temporary + 2 + - + + Interim + 3 + - - Chief Executive Officer - - Demonstration of different Odoo services for each client and convincing the client about functionality of the application. + + + Chief Executive Officer + + Demonstration of different Odoo services for each client and convincing the client about functionality of the application. The candidate should have excellent communication skills. Relationship building and influencing skills Expertise in New Client Acquisition (NCAs) and Relationship Management. @@ -50,7 +58,7 @@ Coordinating with the sales and support team for adopting different strategies Reviewing progress and identifying opportunities and new areas for development. Building strong relationships with clients / customers for business growth profitability. Keep regular interaction with key clients for better extraction and expansion. - MBA in Marketing is must. + MBA in Marketing is must. Good Communication skills. Only Fresher's can apply. Candidate should be ready to work in young and dynamic environment.. @@ -58,16 +66,16 @@ Candidate should be able to work in “start- up” fast paced environment,hands Honest,approachable and fun team player. Result driven. Excellent analytical skills, ability to think logically and "out of the box" - - + + - - Chief Technical Officer - - You will take part in the consulting services we provide to our partners and customers: design, analysis, development, testing, project management, support/coaching. You will work autonomously as well as coordinate and supervise small distributed development teams for some projects. Optionally, you will deliver Odoo training sessions to partners and customers (8-10 people/session). You will report to the Head of Professional Services and work closely with all developers and consultants. + + Chief Technical Officer + + You will take part in the consulting services we provide to our partners and customers: design, analysis, development, testing, project management, support/coaching. You will work autonomously as well as coordinate and supervise small distributed development teams for some projects. Optionally, you will deliver Odoo training sessions to partners and customers (8-10 people/session). You will report to the Head of Professional Services and work closely with all developers and consultants. The job is located in Grand-Rosière (1367), Belgium (between Louvain-La-Neuve and Namur). - Bachelor, master or engineering degree in Computer Science or equivalent by experience + Bachelor, master or engineering degree in Computer Science or equivalent by experience Preferably at least 1 years of experience Interest for enterprise application development Customer-minded @@ -84,39 +92,39 @@ Good knowledge of HTML and Javascript Knowledge of UML-like modeling Good language skills, other than English (Dutch and French preferred, others welcome) - - + + - - Consultant - - 5 - - + + Consultant + + 5 + + - - Experienced Developer - - 5 - - + + Experienced Developer + + 5 + + - - Human Resources Manager - - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. - Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. - - + + Human Resources Manager + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. + + - - Marketing and Community Manager - - + + Marketing and Community Manager + + - - Trainee - You participate to the update of our tutorial tools and pre-sales tools after the launch of a new version of Odoo. Indeed, any new version of the software brings significant improvements in terms of functionalities, ergonomics and configuration. + + Trainee + You participate to the update of our tutorial tools and pre-sales tools after the launch of a new version of Odoo. Indeed, any new version of the software brings significant improvements in terms of functionalities, ergonomics and configuration. You will have to become familiar with the existing tools (books, class supports, Odoo presentation’s slides, commercial tools), to participate to the update of those tools in order to make them appropriate for the new version of the software and, for sure, to suggest improvements in order to cover the new domains of the software. @@ -128,486 +136,439 @@ You help the support manager to set up new support services by being involved in the treatment of new cases, contributing to the set up of a new politic, being involved into satisfaction surveys in order to have a better knowledge of how the support given is seen by the customers. - You speak fluently English and French (one other European language is a +) + You speak fluently English and French (one other European language is a +) At the time of your traineeship at Odoo, you will be in the last year of a Master or Bachelor Degree (ideally in the following sector: Business Management, IT Management, Computer Sciences) You have a software and new technology awareness You are ready to join a young and dynamic company, you are able to work in a “start up” fast paced environment, hands on attitude You are approachable, honest and a fun team player If you have development competencies, we can propose you specific traineeships - + - + + + Building 1, Second Floor + + - - Building 1, Second Floor - - + + + Sales + + - + + Trainer + + - - Sales - - + + Employee + + - - Trainer - - - - - Employee - - - - - Consultant - - - - - - - Mitchell Admin - 215 Vine St - Scranton - 18503 - - - +1 555-555-5555 - admin@yourcompany.example.com - 2010-01-01 00:00:00 - private - - - Mark Demo - 361-7936 Feugiat St. - 58521 - Williston - - +1 555-555-5757 - demo@yourcompany.example.com - private - 2010-01-01 00:00:00 - + + Consultant + + - - - (237)-125-2389 - admin@yourcompany.example.com - - - Chief Executive Officer - - 2010-01-01 00:00:00 - + + 215 Vine St + Scranton + 18503 + + + +1 555-555-5555 + admin@yourcompany.example.com + + (237)-125-2389 + admin@yourcompany.example.com + + + Chief Executive Officer + + 2010-01-01 00:00:00 + - - Ronnie Hart - ronnie.hart87@example.com - - + + Ronnie Hart + ronnie.hart87@example.com + + - - Ronnie Hart - - - Chief Technical Officer - - - (376)-310-7863 - - - 2010-01-01 00:00:00 - + + Ronnie Hart + + + Chief Technical Officer + + + (376)-310-7863 + + + 2010-01-01 00:00:00 + - - Anita Oliver - (538)-672-3185 - anita.oliver32@example.com - - - - - Anital Oliver - + + Anita Oliver (538)-672-3185 - anita.oliver00@example.com - private + anita.oliver32@example.com + - - Anita Oliver - - - - Experienced Developer - - - - (538)-497-4804 - - - 2010-01-01 00:00:00 - + + Anita Oliver + + + + Experienced Developer + + + (538)-672-3185 + anita.oliver00@example.com + + (538)-497-4804 + + + 2010-01-01 00:00:00 + - - Sharlene Rhodes - sharlene.rhodes49@example.com - - + + Sharlene Rhodes + sharlene.rhodes49@example.com + + - - Sharlene Rhodes - - - - Experienced Developer - - - (450)-719-4182 - - - 2010-01-01 00:00:00 - + + Sharlene Rhodes + + + + Experienced Developer + + + (450)-719-4182 + + + 2010-01-01 00:00:00 + - - Randall Lewis - randall.lewis74@example.com - - + + Randall Lewis + randall.lewis74@example.com + + - - Randall Lewis - - - - Experienced Developer - - - (332)-775-6660 - - - 2010-01-01 00:00:00 - + + Randall Lewis + + + + Experienced Developer + + + (332)-775-6660 + + + 2010-01-01 00:00:00 + - - Jennie Fletcher - jennie.fletcher76@example.com - - + + Jennie Fletcher + jennie.fletcher76@example.com + + - - Jennie Fletcher - - - - Experienced Developer - - - (157)-363-8229 - - - 2010-01-01 00:00:00 - + + Jennie Fletcher + + + + Experienced Developer + + + (157)-363-8229 + + + 2010-01-01 00:00:00 + - - Marc Demo - gilles@odoo.com - + + Marc Demo + gilles@odoo.com + - - Marc Demo - - - - - - Experienced Developer - - - +3281813700 - - 2010-01-01 00:00:00 - + + Marc Demo + + + + 361-7936 Feugiat St. + 58521 + Williston + + +1 555-555-5757 + demo@yourcompany.example.com + + Experienced Developer + + + +3281813700 + + 2010-01-01 00:00:00 + - - Keith Byrd - keith.byrd52@example.com - - + + Keith Byrd + keith.byrd52@example.com + + - - Keith Byrd - - - - Experienced Developer - - - (449)-505-5146 - - - 2010-01-01 00:00:00 - + + Keith Byrd + + + + Experienced Developer + + + (449)-505-5146 + + + 2010-01-01 00:00:00 + - + Audrey Peterson - - Audrey.peterson2020@example.com - private + audrey.peterson25@example.com + - - Audrey Peterson - audrey.peterson25@example.com - - + + Audrey Peterson + + + + Consultant + + + Audrey.peterson2020@example.com + + (203)-276-7903 + + + 2010-01-01 00:00:00 + - - Audrey Peterson - - - - Consultant - - - - (203)-276-7903 - - - 2010-01-01 00:00:00 - + + Toni Jimenez + toni.jimenez23@example.com + + - - Toni Jimenez - toni.jimenez23@example.com - - + + Toni Jimenez + + + + Consultant + + + (663)-707-8451 + + + 2010-01-01 00:00:00 + - - Toni Jimenez - - - - Consultant - - - (663)-707-8451 - - - 2010-01-01 00:00:00 - + + Jeffrey Kelly + jeffrey.kelly72@example.com + + - - Jeffrey Kelly - jeffrey.kelly72@example.com - - + + Jeffrey Kelly + + + + Marketing and Community Manager + + + (916)-264-7362 + + + 2010-01-01 00:00:00 + - - Jeffrey Kelly - - - - Marketing and Community Manager - - - (916)-264-7362 - - - 2010-01-01 00:00:00 - + + Tina Williamson + tina.williamson98@example.com + + - - Tina Williamson - tina.williamson98@example.com - - + + Tina Williamson + + + + Human Resources Manager + + + (360)-694-7266 + + + 2010-01-01 00:00:00 + - - Tina Williamson - - - - Human Resources Manager - - - (360)-694-7266 - - - 2010-01-01 00:00:00 - + + Walter Horton + walter.horton80@example.com + + - - Walter Horton - walter.horton80@example.com - - + + Walter Horton + + + Experienced Developer + + (350)-912-1201 + + + 2010-01-01 00:00:00 + - - Walter Horton - - - Experienced Developer - - (350)-912-1201 - - - 2010-01-01 00:00:00 - + + Paul Williams + paul.williams59@example.com + + - - Paul Williams - paul.williams59@example.com - - - - - Paul Williams - - - Experienced Developer - - (114)-262-1607 - - - 2010-01-01 00:00:00 - - - + + Paul Williams + + + Experienced Developer + + (114)-262-1607 + + + 2010-01-01 00:00:00 + + Doris Cole - - Doris.cole.LoveSong@example.com - private + doris.cole31@example.com + - - Doris Cole - doris.cole31@example.com - - + + Doris Cole + + + Consultant + + Doris.cole.LoveSong@example.com + + (883)-331-5378 + + + 2010-01-01 00:00:00 + - - Doris Cole - - - Consultant - - - (883)-331-5378 - - - 2010-01-01 00:00:00 - + + Rachel Perry + jod@odoo.com + + - - Rachel Perry - jod@odoo.com - - + + Rachel Perry + + + Marketing and Community Manager + + (206)-267-3735 + + + 2010-01-01 00:00:00 + - - Rachel Perry - - - Marketing and Community Manager - - (206)-267-3735 - - - 2010-01-01 00:00:00 - - - + Beth Evans - - beth.evans@example.com - private + beth.evans77@example.com + - - Beth Evans - beth.evans77@example.com - - + + Beth Evans + + + Experienced Developer + + beth.evans@example.com + + (754)-532-3841 + + + 2010-01-01 00:00:00 + - - Beth Evans - - - Experienced Developer - - - (754)-532-3841 - - - 2010-01-01 00:00:00 - + + Ernest Reed + ernest.reed47@example.com + + - - Ernest Reed - ernest.reed47@example.com - - + + Ernest Reed + + + Consultant + + (944)-518-8232 + + + 2010-01-01 00:00:00 + - - Ernest Reed - - - Consultant - - (944)-518-8232 - - - 2010-01-01 00:00:00 - + + Eli Lambert + eli.lambert22@example.com + + - - Eli Lambert - eli.lambert22@example.com - - + + Eli Lambert + + + Marketing and Community Manager + + (644)-169-1352 + + + 2010-01-01 00:00:00 + - - Eli Lambert - - - Marketing and Community Manager - - (644)-169-1352 - - - 2010-01-01 00:00:00 - - - + Abigail Peterson - - abigail.peterson33@example.com - private + abigail.peterson39@example.com + - - Abigail Peterson - abigail.peterson39@example.com - - - - - Abigail Peterson - - - Consultant - - - (482)-233-3393 - - - 2010-01-01 00:00:00 - married - + + Abigail Peterson + + + Consultant + + abigail.peterson33@example.com + + (482)-233-3393 + + + 2010-01-01 00:00:00 + married + diff --git a/addons/hr/models/__init__.py b/addons/hr/models/__init__.py index ab10987d906..3fcdcd3af8a 100644 --- a/addons/hr/models/__init__.py +++ b/addons/hr/models/__init__.py @@ -17,8 +17,8 @@ from . import mail_alias from . import discuss_channel from . import models from . import res_config_settings -from . import res_partner from . import res_users from . import res_company +from . import res_partner from . import resource from . import ir_ui_menu diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py index f4955f84e04..b565b7dfa36 100644 --- a/addons/hr/models/hr_employee.py +++ b/addons/hr/models/hr_employee.py @@ -30,6 +30,10 @@ class HrEmployeePrivate(models.Model): _inherit = ['hr.employee.base', 'mail.thread.main.attachment', 'mail.activity.mixin', 'resource.mixin', 'avatar.mixin'] _mail_post_access = 'read' + @api.model + def _lang_get(self): + return self.env['res.lang'].get_installed() + # resource and user # required on the resource, make sure required="True" set in the view name = fields.Char(string="Employee Name", related='resource_id.name', store=True, readonly=False, tracking=True) @@ -41,17 +45,19 @@ class HrEmployeePrivate(models.Model): company_id = fields.Many2one('res.company', required=True) company_country_id = fields.Many2one('res.country', 'Company Country', related='company_id.country_id', readonly=True) company_country_code = fields.Char(related='company_country_id.code', depends=['company_country_id'], readonly=True) - # private partner - address_home_id = fields.Many2one( - 'res.partner', 'Address', help='Enter here the private address of the employee, not the one linked to your company.', - groups="hr.group_hr_user", tracking=True, - domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") - is_address_home_a_company = fields.Boolean( - 'The employee address has a company linked', - compute='_compute_is_address_home_a_company', - ) - private_email = fields.Char(related='address_home_id.email', string="Private Email", groups="hr.group_hr_user") - lang = fields.Selection(related='address_home_id.lang', string="Lang", groups="hr.group_hr_user", readonly=False) + # private info + private_street = fields.Char(string="Private Street", groups="hr.group_hr_user") + private_street2 = fields.Char(string="Private Street2", groups="hr.group_hr_user") + private_city = fields.Char(string="Private City", groups="hr.group_hr_user") + private_state_id = fields.Many2one( + "res.country.state", string="Private State", + domain="[('country_id', '=?', private_country_id)]", + groups="hr.group_hr_user") + private_zip = fields.Char(string="Private Zip", groups="hr.group_hr_user") + private_country_id = fields.Many2one("res.country", string="Private Country", groups="hr.group_hr_user") + private_phone = fields.Char(string="Private Phone", groups="hr.group_hr_user") + private_email = fields.Char(string="Private Email", groups="hr.group_hr_user") + lang = fields.Selection(selection=_lang_get, string="Lang", groups="hr.group_hr_user") country_id = fields.Many2one( 'res.country', 'Nationality (Country)', groups="hr.group_hr_user", tracking=True) gender = fields.Selection([ @@ -78,7 +84,7 @@ class HrEmployeePrivate(models.Model): passport_id = fields.Char('Passport No', groups="hr.group_hr_user", tracking=True) bank_account_id = fields.Many2one( 'res.partner.bank', 'Bank Account Number', - domain="[('partner_id', '=', address_home_id), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", + domain="[('partner_id', '=', work_contact_id), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", groups="hr.group_hr_user", tracking=True, help='Employee bank account to pay salaries') @@ -111,7 +117,6 @@ class HrEmployeePrivate(models.Model): help="The employee type. Although the primary purpose may seem to categorize employees, this field has also an impact in the Contract History. Only Employee type is supposed to be under contract and will have a Contract History.") job_id = fields.Many2one(tracking=True) - phone = fields.Char(related='address_home_id.phone', related_sudo=False, readonly=False, string="Private Phone", groups="hr.group_hr_user") # employee in company child_ids = fields.One2many('hr.employee', 'parent_id', string='Direct subordinates') category_ids = fields.Many2many( @@ -372,7 +377,6 @@ class HrEmployeePrivate(models.Model): onboarding_notes_bodies = {} hr_root_menu = self.env.ref('hr.menu_hr_root') for employee in employees: - employee._message_subscribe(employee.address_home_id.ids) # Launch onboarding plans url = '/web#%s' % url_encode({ 'action': 'hr.plan_wizard_action', @@ -387,16 +391,16 @@ class HrEmployeePrivate(models.Model): return employees def write(self, vals): - if 'address_home_id' in vals: + if 'work_contact_id' in vals: account_id = vals.get('bank_account_id') or self.bank_account_id.id if account_id: bank_account = self.env['res.partner.bank'].browse(account_id) - if vals['address_home_id'] != bank_account.partner_id.id: + if vals['work_contact_id'] != bank_account.partner_id.id: bank_account.sudo().allow_out_payment = False - bank_account.partner_id = vals['address_home_id'] - self.message_unsubscribe(self.address_home_id.ids) - if vals['address_home_id']: - self._message_subscribe([vals['address_home_id']]) + bank_account.partner_id = vals['work_contact_id'] + self.message_unsubscribe(self.work_contact_id.ids) + if vals['work_contact_id']: + self._message_subscribe([vals['work_contact_id']]) if 'user_id' in vals: # Update the profile pictures with user, except if provided vals.update(self._sync_user(self.env['res.users'].browse(vals['user_id']), @@ -431,8 +435,6 @@ class HrEmployeePrivate(models.Model): 'departure_description': False, 'departure_date': False }) - archived_addresses = unarchived_employees.mapped('address_home_id').filtered(lambda addr: not addr.active) - archived_addresses.toggle_active() archived_employees = self.filtered(lambda e: not e.active) if archived_employees: @@ -474,22 +476,6 @@ class HrEmployeePrivate(models.Model): for employee in self: employee.barcode = '041'+"".join(choice(digits) for i in range(9)) - @api.depends('address_home_id', 'user_partner_id') - def _compute_related_contacts(self): - super()._compute_related_contacts() - for employee in self: - employee.related_contact_ids |= employee.address_home_id | employee.user_partner_id - - @api.depends('address_home_id.parent_id') - def _compute_is_address_home_a_company(self): - """Checks that chosen address (res.partner) is not linked to a company. - """ - for employee in self: - try: - employee.is_address_home_a_company = employee.address_home_id.parent_id.id is not False - except AccessError: - employee.is_address_home_a_company = False - def _get_tz(self): # Finds the first valid timezone in his tz, his work hours tz, # the company calendar tz or UTC and returns it as a string diff --git a/addons/hr/models/hr_employee_base.py b/addons/hr/models/hr_employee_base.py index dab447493e4..0de5022953d 100644 --- a/addons/hr/models/hr_employee_base.py +++ b/addons/hr/models/hr_employee_base.py @@ -31,8 +31,6 @@ class HrEmployeeBase(models.AbstractModel): mobile_phone = fields.Char('Work Mobile', compute="_compute_work_contact_details", store=True, inverse='_inverse_work_contact_details') work_email = fields.Char('Work Email', compute="_compute_work_contact_details", store=True, inverse='_inverse_work_contact_details') work_contact_id = fields.Many2one('res.partner', 'Work Contact', copy=False) - related_contact_ids = fields.Many2many('res.partner', 'Related Contacts', compute='_compute_related_contacts') - related_contacts_count = fields.Integer('Number of related contacts', compute='_compute_related_contacts_count') work_location_id = fields.Many2one('hr.work.location', 'Work Location', compute="_compute_work_location_id", store=True, readonly=False, domain="[('address_id', '=', address_id), '|', ('company_id', '=', False), ('company_id', '=', company_id)]") user_id = fields.Many2one('res.users') @@ -174,26 +172,6 @@ class HrEmployeeBase(models.AbstractModel): 'mobile': employee.mobile_phone, }) - @api.depends('work_contact_id') - def _compute_related_contacts(self): - for employee in self: - employee.related_contact_ids = employee.work_contact_id - - @api.depends('related_contact_ids') - def _compute_related_contacts_count(self): - for employee in self: - employee.related_contacts_count = len(employee.related_contact_ids) - - def action_related_contacts(self): - self.ensure_one() - return { - 'name': _("Related Contacts"), - 'type': 'ir.actions.act_window', - 'view_mode': 'kanban,tree,form', - 'res_model': 'res.partner', - 'domain': [('id', 'in', self.related_contact_ids.ids)] - } - @api.depends('company_id') def _compute_address_id(self): for employee in self: diff --git a/addons/hr/models/hr_employee_public.py b/addons/hr/models/hr_employee_public.py index 4f4d66d6718..fc4a3142036 100644 --- a/addons/hr/models/hr_employee_public.py +++ b/addons/hr/models/hr_employee_public.py @@ -25,7 +25,6 @@ class HrEmployeePublic(models.Model): work_phone = fields.Char(readonly=True) work_email = fields.Char(readonly=True) work_contact_id = fields.Many2one(readonly=True) - related_contact_ids = fields.Many2many(readonly=True) work_location_id = fields.Many2one(readonly=True) user_id = fields.Many2one(readonly=True) resource_id = fields.Many2one(readonly=True) @@ -57,12 +56,6 @@ class HrEmployeePublic(models.Model): for employee in self: employee.employee_id = self.env['hr.employee'].browse(employee.id) - @api.depends('user_partner_id') - def _compute_related_contacts(self): - super()._compute_related_contacts() - for employee in self: - employee.related_contact_ids |= employee.user_partner_id - @api.model def _get_fields(self): return ','.join('emp.%s' % name for name, field in self._fields.items() if field.store and field.type not in ['many2many', 'one2many']) diff --git a/addons/hr/models/res_partner.py b/addons/hr/models/res_partner.py index 5c8722744ff..7bba971f882 100644 --- a/addons/hr/models/res_partner.py +++ b/addons/hr/models/res_partner.py @@ -2,30 +2,16 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import fields, models, _ -from odoo.exceptions import AccessError class Partner(models.Model): _inherit = ['res.partner'] employee_ids = fields.One2many( - 'hr.employee', 'address_home_id', string='Employees', groups="hr.group_hr_user", + 'hr.employee', 'work_contact_id', string='Employees', groups="hr.group_hr_user", help="Related employees based on their private address") employees_count = fields.Integer(compute='_compute_employees_count', groups="hr.group_hr_user") - def _compute_display_name(self): - """ Override to allow an employee to see its private address in his profile. - This avoids to relax access rules on `res.parter` and to add an `ir.rule`. - (advantage in both security and performance). - Use a try/except instead of systematically checking to minimize the impact on performance. - """ - try: - super()._compute_display_name() - except AccessError as e: - if len(self) == 1 and self in self.env.user.employee_ids.mapped('address_home_id'): - super(Partner, self.sudo())._compute_display_name() - raise e - def _compute_employees_count(self): for partner in self: partner.employees_count = len(partner.employee_ids) diff --git a/addons/hr/models/res_users.py b/addons/hr/models/res_users.py index fbad6d30d2b..880c8e04384 100644 --- a/addons/hr/models/res_users.py +++ b/addons/hr/models/res_users.py @@ -12,7 +12,6 @@ HR_READABLE_FIELDS = [ 'active', 'child_ids', 'employee_id', - 'address_home_id', 'employee_ids', 'employee_parent_id', 'hr_presence_state', @@ -21,6 +20,7 @@ HR_READABLE_FIELDS = [ 'can_edit', 'is_system', 'employee_resource_calendar_id', + 'work_contact_id', ] HR_WRITABLE_FIELDS = [ @@ -31,6 +31,8 @@ HR_WRITABLE_FIELDS = [ 'private_state_id', 'private_zip', 'private_country_id', + 'private_phone', + 'private_email', 'address_id', 'barcode', 'birthday', @@ -46,9 +48,7 @@ HR_WRITABLE_FIELDS = [ 'employee_country_id', 'gender', 'identification_id', - 'is_address_home_a_company', 'job_title', - 'private_email', 'km_home_work', 'marital', 'mobile_phone', @@ -56,7 +56,6 @@ HR_WRITABLE_FIELDS = [ 'employee_parent_id', 'passport_id', 'permit_no', - 'employee_phone', 'pin', 'place_of_birth', 'spouse_birthdate', @@ -90,26 +89,25 @@ class User(models.Model): job_title = fields.Char(related='employee_id.job_title', readonly=False, related_sudo=False) work_phone = fields.Char(related='employee_id.work_phone', readonly=False, related_sudo=False) mobile_phone = fields.Char(related='employee_id.mobile_phone', readonly=False, related_sudo=False) - employee_phone = fields.Char(related='employee_id.phone', readonly=False, related_sudo=False) work_email = fields.Char(related='employee_id.work_email', readonly=False, related_sudo=False) category_ids = fields.Many2many(related='employee_id.category_ids', string="Employee Tags", readonly=False, related_sudo=False) department_id = fields.Many2one(related='employee_id.department_id', readonly=False, related_sudo=False) address_id = fields.Many2one(related='employee_id.address_id', readonly=False, related_sudo=False) + work_contact_id = fields.Many2one(related='employee_id.work_contact_id', readonly=False, related_sudo=False) work_location_id = fields.Many2one(related='employee_id.work_location_id', readonly=False, related_sudo=False) employee_parent_id = fields.Many2one(related='employee_id.parent_id', readonly=False, related_sudo=False) coach_id = fields.Many2one(related='employee_id.coach_id', readonly=False, related_sudo=False) - address_home_id = fields.Many2one(related='employee_id.address_home_id', readonly=False, related_sudo=False) - private_street = fields.Char(related='address_home_id.street', string="Private Street", readonly=False, related_sudo=False) - private_street2 = fields.Char(related='address_home_id.street2', string="Private Street2", readonly=False, related_sudo=False) - private_city = fields.Char(related='address_home_id.city', string="Private City", readonly=False, related_sudo=False) + private_street = fields.Char(related='employee_id.private_street', string="Private Street", readonly=False, related_sudo=False) + private_street2 = fields.Char(related='employee_id.private_street2', string="Private Street2", readonly=False, related_sudo=False) + private_city = fields.Char(related='employee_id.private_city', string="Private City", readonly=False, related_sudo=False) private_state_id = fields.Many2one( - related='address_home_id.state_id', string="Private State", readonly=False, related_sudo=False, + related='employee_id.private_state_id', string="Private State", readonly=False, related_sudo=False, domain="[('country_id', '=?', private_country_id)]") - private_zip = fields.Char(related='address_home_id.zip', readonly=False, string="Private Zip", related_sudo=False) - private_country_id = fields.Many2one(related='address_home_id.country_id', string="Private Country", readonly=False, related_sudo=False) - is_address_home_a_company = fields.Boolean(related='employee_id.is_address_home_a_company', readonly=False, related_sudo=False) - private_email = fields.Char(related='address_home_id.email', string="Private Email", readonly=False) - private_lang = fields.Selection(related='address_home_id.lang', string="Employee Lang", readonly=False) + private_zip = fields.Char(related='employee_id.private_zip', readonly=False, string="Private Zip", related_sudo=False) + private_country_id = fields.Many2one(related='employee_id.private_country_id', string="Private Country", readonly=False, related_sudo=False) + private_phone = fields.Char(related='employee_id.private_phone', readonly=False, related_sudo=False) + private_email = fields.Char(related='employee_id.private_email', string="Private Email", readonly=False) + private_lang = fields.Selection(related='employee_id.lang', string="Employee Lang", readonly=False) km_home_work = fields.Integer(related='employee_id.km_home_work', readonly=False, related_sudo=False) # res.users already have a field bank_account_id and country_id from the res.partner inheritance: don't redefine them employee_bank_account_id = fields.Many2one(related='employee_id.bank_account_id', string="Employee's Bank Account Number", related_sudo=False, readonly=False) diff --git a/addons/hr/tests/test_self_user_access.py b/addons/hr/tests/test_self_user_access.py index a3cb1c63075..2eb5094f930 100644 --- a/addons/hr/tests/test_self_user_access.py +++ b/addons/hr/tests/test_self_user_access.py @@ -112,13 +112,12 @@ class TestSelfAccessRights(TestHrCommon): cls.richard_emp = cls.env['hr.employee'].create({ 'name': 'Richard', 'user_id': cls.richard.id, - 'address_home_id': cls.env['res.partner'].create({'name': 'Richard', 'phone': '21454', 'type': 'private'}).id, + 'private_phone': '21454', }) cls.hubert = new_test_user(cls.env, login='hub', groups='base.group_user', name='Simple employee', email='hub@example.com') cls.hubert_emp = cls.env['hr.employee'].create({ 'name': 'Hubert', 'user_id': cls.hubert.id, - 'address_home_id': cls.env['res.partner'].create({'name': 'Hubert', 'type': 'private'}).id, }) cls.protected_fields_emp = OrderedDict([(k, v) for k, v in cls.env['hr.employee']._fields.items() if v.groups == 'hr.group_hr_user']) diff --git a/addons/hr/views/hr_employee_views.xml b/addons/hr/views/hr_employee_views.xml index fb4de5c6623..5137cb7c87d 100644 --- a/addons/hr/views/hr_employee_views.xml +++ b/addons/hr/views/hr_employee_views.xml @@ -54,6 +54,7 @@ +
@@ -135,15 +136,18 @@ - +