[IMP] hr: Review the UX for 'My Profile' view

1/ web: adapt formatDate to handle NaN values
DashboardRenderer might return NaN for `Date` or `DateTime` fields if
their original value is null or incorrect.

2/ hr: add job_title in demo data

3/ hr_recruitment: link employee in the chatter for new recruits

4/ hr: remove employee documents in the model

5/ hr_attendance: improve resiliency of relative_time

6/ hr: display manager on res_users

7/ hr: change Address Book to Employee Directory

TaskID: 2009111

closes odoo/odoo#34180

Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
Kevin Baptiste
2019-07-18 10:27:50 +00:00
committed by Yannick Tivisse
parent 9f5f2fc502
commit e9d9898276
34 changed files with 258 additions and 101 deletions
+20
View File
@@ -141,6 +141,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="work_email">aiden.hughes71@example.com</field> <field name="work_email">aiden.hughes71@example.com</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_3')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_3')])]"/>
<field name="job_id" ref="hr.job_ceo"/> <field name="job_id" ref="hr.job_ceo"/>
<field name="job_title">Chief Executive Officer</field>
<field name="department_id" ref="dep_management"/> <field name="department_id" ref="dep_management"/>
</record> </record>
@@ -148,6 +149,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Ronnie Hart</field> <field name="name">Ronnie Hart</field>
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="job_id" ref="hr.job_cto"/> <field name="job_id" ref="hr.job_cto"/>
<field name="job_title">Chief Technical Officer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_3')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_3')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(376)-310-7863</field> <field name="work_phone">(376)-310-7863</field>
@@ -160,6 +162,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_al"/> <field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(538)-497-4804</field> <field name="work_phone">(538)-497-4804</field>
@@ -173,6 +176,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_management"/> <field name="department_id" ref="dep_management"/>
<field name="parent_id" ref="employee_al"/> <field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(450)-719-4182</field> <field name="work_phone">(450)-719-4182</field>
@@ -185,6 +189,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_al"/> <field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(332)-775-6660</field> <field name="work_phone">(332)-775-6660</field>
@@ -197,6 +202,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_al"/> <field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(157)-363-8229</field> <field name="work_phone">(157)-363-8229</field>
@@ -210,6 +216,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_admin"/> <field name="parent_id" ref="employee_admin"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">+3281813700</field> <field name="work_phone">+3281813700</field>
@@ -222,6 +229,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="parent_id" ref="employee_al"/> <field name="parent_id" ref="employee_al"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(449)-505-5146</field> <field name="work_phone">(449)-505-5146</field>
@@ -234,6 +242,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_ps"/> <field name="department_id" ref="dep_ps"/>
<field name="parent_id" ref="employee_admin"/> <field name="parent_id" ref="employee_admin"/>
<field name="job_id" ref="hr.job_consultant"/> <field name="job_id" ref="hr.job_consultant"/>
<field name="job_title">Consultant</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_5')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_5')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(203)-276-7903</field> <field name="work_phone">(203)-276-7903</field>
@@ -246,6 +255,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_ps"/> <field name="department_id" ref="dep_ps"/>
<field name="parent_id" ref="employee_admin"/> <field name="parent_id" ref="employee_admin"/>
<field name="job_id" ref="hr.job_consultant"/> <field name="job_id" ref="hr.job_consultant"/>
<field name="job_title">Consultant</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_5')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_5')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(663)-707-8451</field> <field name="work_phone">(663)-707-8451</field>
@@ -258,6 +268,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_sales"/> <field name="department_id" ref="dep_sales"/>
<field name="parent_id" ref="employee_admin"/> <field name="parent_id" ref="employee_admin"/>
<field name="job_id" ref="hr.job_marketing"/> <field name="job_id" ref="hr.job_marketing"/>
<field name="job_title">Marketing and Community Manager</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_2')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4'), ref('employee_category_2')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(916)-264-7362</field> <field name="work_phone">(916)-264-7362</field>
@@ -270,6 +281,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="department_id" ref="dep_administration"/> <field name="department_id" ref="dep_administration"/>
<field name="parent_id" ref="employee_admin"/> <field name="parent_id" ref="employee_admin"/>
<field name="job_id" ref="hr.job_hrm"/> <field name="job_id" ref="hr.job_hrm"/>
<field name="job_title">Human Resources Manager</field>
<field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/> <field name="category_ids" eval="[(6, 0, [ref('employee_category_4')])]"/>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(360)-694-7266</field> <field name="work_phone">(360)-694-7266</field>
@@ -281,6 +293,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Walter Horton</field> <field name="name">Walter Horton</field>
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(350)-912-1201</field> <field name="work_phone">(350)-912-1201</field>
<field name="work_email">walter.horton80@example.com</field> <field name="work_email">walter.horton80@example.com</field>
@@ -291,6 +304,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Paul Williams</field> <field name="name">Paul Williams</field>
<field name="department_id" ref="dep_management"/> <field name="department_id" ref="dep_management"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(114)-262-1607</field> <field name="work_phone">(114)-262-1607</field>
<field name="work_email">paul.williams59@example.com</field> <field name="work_email">paul.williams59@example.com</field>
@@ -301,6 +315,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Doris Cole</field> <field name="name">Doris Cole</field>
<field name="department_id" ref="dep_ps"/> <field name="department_id" ref="dep_ps"/>
<field name="job_id" ref="hr.job_consultant"/> <field name="job_id" ref="hr.job_consultant"/>
<field name="job_title">Consultant</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(883)-331-5378</field> <field name="work_phone">(883)-331-5378</field>
<field name="work_email">doris.cole31@example.com</field> <field name="work_email">doris.cole31@example.com</field>
@@ -311,6 +326,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Rachel Perry</field> <field name="name">Rachel Perry</field>
<field name="department_id" ref="dep_sales"/> <field name="department_id" ref="dep_sales"/>
<field name="job_id" ref="hr.job_marketing"/> <field name="job_id" ref="hr.job_marketing"/>
<field name="job_title">Marketing and Community Manager</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(206)-267-3735</field> <field name="work_phone">(206)-267-3735</field>
<field name="work_email">jod@odoo.com</field> <field name="work_email">jod@odoo.com</field>
@@ -321,6 +337,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Beth Evans</field> <field name="name">Beth Evans</field>
<field name="department_id" ref="dep_rd"/> <field name="department_id" ref="dep_rd"/>
<field name="job_id" ref="hr.job_developer"/> <field name="job_id" ref="hr.job_developer"/>
<field name="job_title">Experienced Developer</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(754)-532-3841</field> <field name="work_phone">(754)-532-3841</field>
<field name="work_email">beth.evans77@example.com</field> <field name="work_email">beth.evans77@example.com</field>
@@ -331,6 +348,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Ernest Reed</field> <field name="name">Ernest Reed</field>
<field name="department_id" ref="dep_ps"/> <field name="department_id" ref="dep_ps"/>
<field name="job_id" ref="hr.job_consultant"/> <field name="job_id" ref="hr.job_consultant"/>
<field name="job_title">Consultant</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(944)-518-8232</field> <field name="work_phone">(944)-518-8232</field>
<field name="work_email">ernest.reed47@example.com</field> <field name="work_email">ernest.reed47@example.com</field>
@@ -341,6 +359,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Eli Lambert</field> <field name="name">Eli Lambert</field>
<field name="department_id" ref="dep_sales"/> <field name="department_id" ref="dep_sales"/>
<field name="job_id" ref="hr.job_marketing"/> <field name="job_id" ref="hr.job_marketing"/>
<field name="job_title">Marketing and Community Manager</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_phone">(644)-169-1352</field> <field name="work_phone">(644)-169-1352</field>
<field name="work_email">eli.lambert22@example.com</field> <field name="work_email">eli.lambert22@example.com</field>
@@ -351,6 +370,7 @@ If you have development competencies, we can propose you specific traineeships</
<field name="name">Abigail Peterson</field> <field name="name">Abigail Peterson</field>
<field name="department_id" ref="dep_ps"/> <field name="department_id" ref="dep_ps"/>
<field name="job_id" ref="hr.job_consultant"/> <field name="job_id" ref="hr.job_consultant"/>
<field name="job_title">Consultant</field>
<field name="work_location">Building 1, Second Floor</field> <field name="work_location">Building 1, Second Floor</field>
<field name="work_email">abigail.peterson39@example.com</field> <field name="work_email">abigail.peterson39@example.com</field>
<field name="work_phone">(482)-233-3393</field> <field name="work_phone">(482)-233-3393</field>
+3 -3
View File
@@ -41,12 +41,13 @@ class HrEmployeePrivate(models.Model):
active = fields.Boolean('Active', related='resource_id.active', default=True, store=True, readonly=False) active = fields.Boolean('Active', related='resource_id.active', default=True, store=True, readonly=False)
# private partner # private partner
address_home_id = fields.Many2one( address_home_id = fields.Many2one(
'res.partner', 'Private Address', help='Enter here the private address of the employee, not the one linked to your company.', '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) groups="hr.group_hr_user", tracking=True)
is_address_home_a_company = fields.Boolean( is_address_home_a_company = fields.Boolean(
'The employee adress has a company linked', 'The employee adress has a company linked',
compute='_compute_is_address_home_a_company', compute='_compute_is_address_home_a_company',
) )
private_email = fields.Char(related='address_home_id.email', string="Private Email", readonly=False, groups="hr.group_hr_user")
country_id = fields.Many2one( country_id = fields.Many2one(
'res.country', 'Nationality (Country)', groups="hr.group_hr_user", tracking=True) 'res.country', 'Nationality (Country)', groups="hr.group_hr_user", tracking=True)
gender = fields.Selection([ gender = fields.Selection([
@@ -90,8 +91,7 @@ class HrEmployeePrivate(models.Model):
study_school = fields.Char("School", groups="hr.group_hr_user", tracking=True) study_school = fields.Char("School", groups="hr.group_hr_user", tracking=True)
emergency_contact = fields.Char("Emergency Contact", groups="hr.group_hr_user", tracking=True) emergency_contact = fields.Char("Emergency Contact", groups="hr.group_hr_user", tracking=True)
emergency_phone = fields.Char("Emergency Phone", groups="hr.group_hr_user", tracking=True) emergency_phone = fields.Char("Emergency Phone", groups="hr.group_hr_user", tracking=True)
km_home_work = fields.Integer(string="Km home-work", groups="hr.group_hr_user", tracking=True) km_home_work = fields.Integer(string="Km Home-Work", groups="hr.group_hr_user", tracking=True)
google_drive_link = fields.Char(string="Employee Documents", groups="hr.group_hr_user", tracking=True)
# image: all image fields are base64 encoded and PIL-supported # image: all image fields are base64 encoded and PIL-supported
image = fields.Binary( image = fields.Binary(
+1
View File
@@ -28,6 +28,7 @@ class HrEmployeePublic(models.Model):
user_id = fields.Many2one(readonly=True) user_id = fields.Many2one(readonly=True)
resource_id = fields.Many2one(readonly=True) resource_id = fields.Many2one(readonly=True)
resource_calendar_id = fields.Many2one(readonly=True) resource_calendar_id = fields.Many2one(readonly=True)
color = fields.Integer(readonly=True)
# hr.employee.public specific fields # hr.employee.public specific fields
child_ids = fields.One2many('hr.employee.public', 'parent_id', string='Direct subordinates', readonly=True) child_ids = fields.One2many('hr.employee.public', 'parent_id', string='Direct subordinates', readonly=True)
+6 -6
View File
@@ -9,13 +9,13 @@ class ResConfigSettings(models.TransientModel):
resource_calendar_id = fields.Many2one( resource_calendar_id = fields.Many2one(
'resource.calendar', 'Company Working Hours', 'resource.calendar', 'Company Working Hours',
related='company_id.resource_calendar_id', readonly=False) related='company_id.resource_calendar_id', readonly=False)
module_hr_org_chart = fields.Boolean(string="Show Organizational Chart") module_hr_org_chart = fields.Boolean(string="Organizational Chart")
module_hr_presence = fields.Boolean(string="Advanced control presence of employees") module_hr_presence = fields.Boolean(string="Advanced Employees Presence Check Based on")
module_hr_skills = fields.Boolean(string="Employee Skills and Resumé") module_hr_skills = fields.Boolean(string="Employee Skills and Resumé")
hr_presence_control_login = fields.Boolean(string="According to the system login (User status on chat)", config_parameter='hr.hr_presence_control_login') hr_presence_control_login = fields.Boolean(string="The system login (User status on chat)", config_parameter='hr.hr_presence_control_login')
hr_presence_control_email = fields.Boolean(string="According to the amount of sent emails", config_parameter='hr_presence.hr_presence_control_email') hr_presence_control_email = fields.Boolean(string="The amount of sent emails", config_parameter='hr_presence.hr_presence_control_email')
hr_presence_control_ip = fields.Boolean(string="According to the IP address", config_parameter='hr_presence.hr_presence_control_ip') hr_presence_control_ip = fields.Boolean(string="The IP address", config_parameter='hr_presence.hr_presence_control_ip')
module_hr_attendance = fields.Boolean(string="According to the Attendance module.") module_hr_attendance = fields.Boolean(string="The Attendance module.")
hr_presence_control_email_amount = fields.Integer(related="company_id.hr_presence_control_email_amount", readonly=False) hr_presence_control_email_amount = fields.Integer(related="company_id.hr_presence_control_email_amount", readonly=False)
hr_presence_control_ip_list = fields.Char(related="company_id.hr_presence_control_ip_list", readonly=False) hr_presence_control_ip_list = fields.Char(related="company_id.hr_presence_control_ip_list", readonly=False)
hr_employee_self_edit = fields.Boolean(string="Employee Edition", config_parameter='hr.hr_employee_self_edit') hr_employee_self_edit = fields.Boolean(string="Employee Edition", config_parameter='hr.hr_employee_self_edit')
+1 -2
View File
@@ -25,6 +25,7 @@ class User(models.Model):
coach_id = fields.Many2one(related='employee_id.coach_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) address_home_id = fields.Many2one(related='employee_id.address_home_id', 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) 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)
km_home_work = fields.Integer(related='employee_id.km_home_work', readonly=False, related_sudo=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 # 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) employee_bank_account_id = fields.Many2one(related='employee_id.bank_account_id', string="Employee's Bank Account Number", related_sudo=False, readonly=False)
@@ -44,7 +45,6 @@ class User(models.Model):
visa_no = fields.Char(related='employee_id.visa_no', readonly=False, related_sudo=False) visa_no = fields.Char(related='employee_id.visa_no', readonly=False, related_sudo=False)
permit_no = fields.Char(related='employee_id.permit_no', readonly=False, related_sudo=False) permit_no = fields.Char(related='employee_id.permit_no', readonly=False, related_sudo=False)
visa_expire = fields.Date(related='employee_id.visa_expire', readonly=False, related_sudo=False) visa_expire = fields.Date(related='employee_id.visa_expire', readonly=False, related_sudo=False)
google_drive_link = fields.Char(related='employee_id.google_drive_link', readonly=False, related_sudo=False)
additional_note = fields.Text(related='employee_id.additional_note', readonly=False, related_sudo=False) additional_note = fields.Text(related='employee_id.additional_note', readonly=False, related_sudo=False)
barcode = fields.Char(related='employee_id.barcode', readonly=False, related_sudo=False) barcode = fields.Char(related='employee_id.barcode', readonly=False, related_sudo=False)
pin = fields.Char(related='employee_id.pin', readonly=False, related_sudo=False) pin = fields.Char(related='employee_id.pin', readonly=False, related_sudo=False)
@@ -92,7 +92,6 @@ class User(models.Model):
'employee_bank_account_id', 'employee_bank_account_id',
'employee_country_id', 'employee_country_id',
'gender', 'gender',
'google_drive_link',
'identification_id', 'identification_id',
'is_address_home_a_company', 'is_address_home_a_company',
'job_title', 'job_title',
+14 -5
View File
@@ -8,6 +8,14 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Employees"> <search string="Employees">
<field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/> <field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/>
<field name="job_title" string="Job Title"/>
<field name="department_id" string="Department"/>
<field name="company_id" string="Company"/>
<group expand="0" string="Group By">
<filter name="group_manager" string="Manager" domain="[]" context="{'group_by':'parent_id'}"/>
<filter name="group_department" string="Department" domain="[]" context="{'group_by':'department_id'}"/>
<filter name="group_company" string="Company" domain="[]" context="{'group_by':'company_id'}"/>
</group>
</search> </search>
</field> </field>
</record> </record>
@@ -43,6 +51,7 @@
<group> <group>
<field name="department_id"/> <field name="department_id"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
<field name="parent_id"/>
</group> </group>
</group> </group>
<notebook> <notebook>
@@ -55,8 +64,7 @@
options='{"always_reload": True, "highlight_first_line": True}'/> options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="work_location"/> <field name="work_location"/>
</group> </group>
<group name="managers" string="Managers"> <group name="managers" string="Responsibles">
<field name="parent_id"/>
<field name="coach_id"/> <field name="coach_id"/>
</group> </group>
<group string="Schedule" groups="base.group_no_one"> <group string="Schedule" groups="base.group_no_one">
@@ -81,7 +89,7 @@
<field name="work_email"/> <field name="work_email"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
<field name="department_id"/> <field name="department_id"/>
<field name="job_id"/> <field name="job_title"/>
<field name="parent_id"/> <field name="parent_id"/>
<field name="coach_id" invisible="1"/> <field name="coach_id" invisible="1"/>
</tree> </tree>
@@ -119,12 +127,13 @@
</div> </div>
<field name="name"/> <field name="name"/>
</strong> </strong>
<span t-if="record.job_id.raw_value" class="o_kanban_record_subtitle"><field name="job_id"/></span> <span t-if="record.job_title.raw_value" class="o_kanban_record_subtitle"><field name="job_title"/></span>
</div> </div>
</div> </div>
<ul> <ul>
<li id="last_login"/> <li id="last_login"/>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li> <li t-if="record.work_email.raw_value"><field name="work_email" /></li>
<li t-if="record.work_phone.raw_value"><field name="work_phone" /></li>
</ul> </ul>
</div> </div>
</div> </div>
+13 -21
View File
@@ -10,7 +10,7 @@
<field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/> <field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/>
<field name="department_id" operator="child_of"/> <field name="department_id" operator="child_of"/>
<field name="category_ids" groups="hr.group_hr_user"/> <field name="category_ids" groups="hr.group_hr_user"/>
<field name="job_id" /> <field name="job_title" />
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/> <filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<separator/> <separator/>
@@ -77,7 +77,7 @@
<field name="name" placeholder="Employee's Name" required="True"/> <field name="name" placeholder="Employee's Name" required="True"/>
</h1> </h1>
<h2> <h2>
<field name="job_title" placeholder="Job Title" /> <field name="job_title" placeholder="Job Position" />
</h2> </h2>
<field name="category_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}" placeholder="Tags" groups="hr.group_hr_manager"/> <field name="category_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}" placeholder="Tags" groups="hr.group_hr_manager"/>
</div> </div>
@@ -90,7 +90,8 @@
<group> <group>
<field name="department_id"/> <field name="department_id"/>
<field name="job_id"/> <field name="job_id"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="parent_id"/>
<field name="company_id" invisible="1"/>
</group> </group>
</group> </group>
<notebook> <notebook>
@@ -103,8 +104,7 @@
options='{"always_reload": True, "highlight_first_line": True}'/> options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="work_location"/> <field name="work_location"/>
</group> </group>
<group name="managers" string="Managers"> <group name="managers" string="Responsibles">
<field name="parent_id"/>
<field name="coach_id"/> <field name="coach_id"/>
</group> </group>
<group name="departure" string="Departure" attrs="{'invisible': [('active', '=', True)]}"> <group name="departure" string="Departure" attrs="{'invisible': [('active', '=', True)]}">
@@ -120,23 +120,17 @@
</page> </page>
<page name="personal_information" string="Private Information" groups="hr.group_hr_user"> <page name="personal_information" string="Private Information" groups="hr.group_hr_user">
<group> <group>
<group string="Contact Information"> <group string="Private Contact">
<field name="address_home_id" <field name="address_home_id"
context="{ context="{
'show_address': 1, 'show_address': 1,
'default_type': 'private', 'default_type': 'private',
'form_view_ref': 'base.res_partner_view_form_private'}" 'form_view_ref': 'base.res_partner_view_form_private'}"
options='{"always_reload": True, "highlight_first_line": True}'/> options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="is_address_home_a_company" invisible="1"/> <field name="private_email" string="Email"/>
<div class="text-warning" groups="hr.group_hr_user" <field name="phone" groups="hr.group_hr_user" string="Phone"/>
attrs="{'invisible': [('is_address_home_a_company','=', False)]}">
Use here the home address of the employee.
This private address is used in the expense report reimbursement document.
It should be different from the work address.
</div>
<field name="km_home_work" groups="hr.group_hr_user"/>
<field name="phone" groups="hr.group_hr_user"/>
<field name="bank_account_id" context="{'default_partner_id': address_home_id}"/> <field name="bank_account_id" context="{'default_partner_id': address_home_id}"/>
<field name="km_home_work" groups="hr.group_hr_user"/>
</group> </group>
<group string="Citizenship"> <group string="Citizenship">
<field name="country_id" options='{"no_open": True, "no_create": True}'/> <field name="country_id" options='{"no_open": True, "no_create": True}'/>
@@ -175,16 +169,13 @@
<field name="study_school"/> <field name="study_school"/>
</group> </group>
</group> </group>
<group>
<field name="google_drive_link" widget="url"/>
</group>
</page> </page>
<page name="hr_settings" string="HR Settings" groups="hr.group_hr_user"> <page name="hr_settings" string="HR Settings" groups="hr.group_hr_user">
<group> <group>
<group string='Status' name="active_group"> <group string='Status' name="active_group">
<field name="user_id" string="Related User"/> <field name="user_id" string="Related User"/>
</group> </group>
<group string="Login Information" name="identification_group"> <group string="Attendance" name="identification_group">
<field name="pin"/> <field name="pin"/>
<field name="barcode"/> <field name="barcode"/>
<button string="Generate Badge ID" class="btn btn-primary" type="object" name="generate_random_barcode" attrs="{'invisible': [('barcode', '!=', False)]}"/> <button string="Generate Badge ID" class="btn btn-primary" type="object" name="generate_random_barcode" attrs="{'invisible': [('barcode', '!=', False)]}"/>
@@ -251,13 +242,14 @@
</div> </div>
<field name="name" placeholder="Employee's Name"/> <field name="name" placeholder="Employee's Name"/>
</strong> </strong>
<span t-if="record.job_id.raw_value" class="o_kanban_record_subtitle"><field name="job_id"/></span> <span t-if="record.job_title.raw_value" class="o_kanban_record_subtitle"><field name="job_title"/></span>
</div> </div>
</div> </div>
<field name="category_ids" widget="many2many_tags" options="{'color_field': 'color'}"/> <field name="category_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
<ul> <ul>
<li id="last_login"/> <li id="last_login"/>
<li t-if="record.work_location.raw_value"><field name="work_location"/></li> <li t-if="record.work_email.raw_value"><field name="work_email" /></li>
<li t-if="record.work_phone.raw_value"><field name="work_phone" /></li>
</ul> </ul>
</div> </div>
</div> </div>
+1 -1
View File
@@ -31,7 +31,7 @@
<menuitem <menuitem
id="menu_hr_employee" id="menu_hr_employee"
name="Company Address" name="Employee Directory"
action="hr_employee_public_action" action="hr_employee_public_action"
parent="menu_hr_root" parent="menu_hr_root"
sequence="4"/> sequence="4"/>
@@ -16,7 +16,7 @@
<div class="o_setting_right_pane"> <div class="o_setting_right_pane">
<label for="module_hr_skills"/> <label for="module_hr_skills"/>
<div class="text-muted"> <div class="text-muted">
Manage skills, knowledge and resumé of your employees Enrich Employees Profiles with Resume, Skills and knowledge
</div> </div>
</div> </div>
</div> </div>
@@ -73,7 +73,7 @@
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/> <span class="fa fa-lg fa-building-o" title="Values set here are company-specific." role="img" aria-label="Values set here are company-specific." groups="base.group_multi_company"/>
<div class="row"> <div class="row">
<div class="text-muted col-lg-8"> <div class="text-muted col-lg-8">
Set default calendar used to compute time allocation for leaves, timesheets, ... Set default company schedule to manage your employees working time
</div> </div>
</div> </div>
<div class="content-group"> <div class="content-group">
+25 -22
View File
@@ -15,6 +15,19 @@
<footer position="replace"/> <footer position="replace"/>
<h1 position="replace"/> <h1 position="replace"/>
<xpath expr="//field[@name='image']" position="replace"/> <xpath expr="//field[@name='image']" position="replace"/>
<xpath expr="//field[@name='email']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//group[@name='preferences']" position="before">
<separator string="Email &amp; Notifications" />
</xpath>
<field name="signature" position="replace" />
<xpath expr="//field[@name='company_id']" position="after">
<field name="signature" />
</xpath>
<xpath expr="//field[@name='company_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
</field> </field>
</record> </record>
@@ -71,7 +84,7 @@
<field name="category_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}" placeholder="Tags" groups="hr.group_hr_user"/> <field name="category_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}" placeholder="Tags" groups="hr.group_hr_user"/>
</div> </div>
<h2> <h2>
<field name="job_title"/> <field name="job_title" placeholder="Job Position"/>
</h2> </h2>
<group> <group>
<group> <group>
@@ -81,10 +94,14 @@
</group> </group>
<group> <group>
<field name="department_id"/> <field name="department_id"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" invisible="1"/>
<field name="employee_parent_id"/>
</group> </group>
</group> </group>
<notebook> <notebook>
<page name="preferences" string="Preferences">
<div>$0</div>
</page>
<page name="public" string="Work Information"> <page name="public" string="Work Information">
<div id="o_work_employee_container"> <!-- These two div are used to position org_chart --> <div id="o_work_employee_container"> <!-- These two div are used to position org_chart -->
<div id="o_work_employee_main"> <div id="o_work_employee_main">
@@ -94,8 +111,7 @@
options='{"always_reload": True, "highlight_first_line": True}'/> options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="work_location"/> <field name="work_location"/>
</group> </group>
<group name="managers" string="Managers"> <group name="managers" string="Responsibles">
<field name="employee_parent_id"/>
<field name="coach_id"/> <field name="coach_id"/>
</group> </group>
</div> </div>
@@ -112,16 +128,10 @@
'default_type': 'private', 'default_type': 'private',
'form_view_ref': 'base.res_partner_view_form_private'}" 'form_view_ref': 'base.res_partner_view_form_private'}"
options='{"always_reload": True, "highlight_first_line": True}'/> options='{"always_reload": True, "highlight_first_line": True}'/>
<field name="is_address_home_a_company" invisible="1"/> <field name="private_email" string="Email"/>
<div class="text-warning" <field name="employee_phone" string="Phone"/>
attrs="{'invisible': [('is_address_home_a_company','=', False)]}">
Use here the home address of the employee.
This private address is used in the expense report reimbursement document.
It should be different from the work address.
</div>
<field name="km_home_work"/>
<field name="employee_phone"/>
<field name="employee_bank_account_id"/> <field name="employee_bank_account_id"/>
<field name="km_home_work"/>
</group> </group>
<group string="Citizenship"> <group string="Citizenship">
<field name="employee_country_id" options='{"no_open": True, "no_create": True}'/> <field name="employee_country_id" options='{"no_open": True, "no_create": True}'/>
@@ -155,18 +165,11 @@
<field name="visa_expire"/> <field name="visa_expire"/>
</group> </group>
</group> </group>
<group>
<field name="google_drive_link" widget="url"/>
</group>
</page>
<page name="preferences" string="Preferences">
<div>$0</div>
</page> </page>
<page name="hr_settings" string="HR Settings"> <page name="hr_settings" string="HR Settings">
<group> <group>
<group string='Status' name="active_group"> <group string='Status' name="active_group" invisible="1"></group>
</group> <group string="Attendance" name="identification_group">
<group string="Login Information" name="identification_group">
<field name="pin"/> <field name="pin"/>
<field name="barcode"/> <field name="barcode"/>
</group> </group>
@@ -13,9 +13,12 @@ class HrEmployeeBase(models.AbstractModel):
attendance_ids = fields.One2many('hr.attendance', 'employee_id', help='list of attendances for the employee') attendance_ids = fields.One2many('hr.attendance', 'employee_id', help='list of attendances for the employee')
last_attendance_id = fields.Many2one('hr.attendance', compute='_compute_last_attendance_id', store=True) last_attendance_id = fields.Many2one('hr.attendance', compute='_compute_last_attendance_id', store=True)
last_check_in = fields.Datetime(related='last_attendance_id.check_in', store=True)
last_check_out = fields.Datetime(related='last_attendance_id.check_out', store=True)
attendance_state = fields.Selection(string="Attendance Status", compute='_compute_attendance_state', selection=[('checked_out', "Checked out"), ('checked_in', "Checked in")]) attendance_state = fields.Selection(string="Attendance Status", compute='_compute_attendance_state', selection=[('checked_out', "Checked out"), ('checked_in', "Checked in")])
hours_last_month = fields.Float(compute='_compute_hours_last_month') hours_last_month = fields.Float(compute='_compute_hours_last_month')
hours_today = fields.Float(compute='_compute_hours_today') hours_today = fields.Float(compute='_compute_hours_today')
hours_last_month_display = fields.Char(compute='_compute_hours_last_month')
def _compute_presence_state(self): def _compute_presence_state(self):
""" """
@@ -42,6 +45,7 @@ class HrEmployeeBase(models.AbstractModel):
('check_out', '<=', end), ('check_out', '<=', end),
]) ])
employee.hours_last_month = sum(attendances.mapped('worked_hours')) employee.hours_last_month = sum(attendances.mapped('worked_hours'))
employee.hours_last_month_display = "%g" % employee.hours_last_month
def _compute_hours_today(self): def _compute_hours_today(self):
now = fields.Datetime.now() now = fields.Datetime.now()
+4
View File
@@ -8,7 +8,10 @@ class User(models.Model):
_inherit = ['res.users'] _inherit = ['res.users']
hours_last_month = fields.Float(related='employee_id.hours_last_month') hours_last_month = fields.Float(related='employee_id.hours_last_month')
hours_last_month_display = fields.Char(related='employee_id.hours_last_month_display')
attendance_state = fields.Selection(related='employee_id.attendance_state') attendance_state = fields.Selection(related='employee_id.attendance_state')
last_check_in = fields.Datetime(related='employee_id.last_attendance_id.check_in')
last_check_out = fields.Datetime(related='employee_id.last_attendance_id.check_out')
def __init__(self, pool, cr): def __init__(self, pool, cr):
""" Override of __init__ to add access rights. """ Override of __init__ to add access rights.
@@ -17,6 +20,7 @@ class User(models.Model):
""" """
attendance_readable_fields = [ attendance_readable_fields = [
'hours_last_month', 'hours_last_month',
'hours_last_month_display',
'attendance_state', 'attendance_state',
] ]
super(User, self).__init__(pool, cr) super(User, self).__init__(pool, cr)
@@ -0,0 +1,19 @@
odoo.define('hr_attendance.widget', function (require) {
"use strict";
var basic_fields = require('web.basic_fields');
var field_registry = require('web.field_registry');
var RelativeTime = basic_fields.FieldDateTime.extend({
_formatValue: function (val) {
if (!(val && val._isAMomentObject)) {
return;
}
return val.fromNow(true);
},
});
field_registry.add('relative_time', RelativeTime);
return RelativeTime;
});
@@ -24,7 +24,15 @@
('attendance_state', '=', 'checked_out')]}"> ('attendance_state', '=', 'checked_out')]}">
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/> <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/> <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
<div class="o_stat_info"> <div class="o_stat_info" attrs="{'invisible': ['|', ('last_check_in', '=', False), ('last_check_out', '!=', False)]}">
<span class="o_stat_text">Present Since</span>
<span class="o_stat_value"><field name="last_check_in" widget="relative_time"/></span>
</div>
<div class="o_stat_info" attrs="{'invisible': [('last_check_out', '=', False)]}">
<span class="o_stat_text">Absent Since</span>
<span class="o_stat_value"><field name="last_check_out" widget="relative_time"/></span>
</div>
<div class="o_stat_info" attrs="{'invisible': [('last_check_in', '!=', False)]}">
<span class="o_stat_text">Attendance</span> <span class="o_stat_text">Attendance</span>
</div> </div>
</button> </button>
@@ -37,7 +45,7 @@
help="Worked hours last month"> help="Worked hours last month">
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="hours_last_month"/> Hours <field name="hours_last_month_display"/> Hours
</span> </span>
<span class="o_stat_text"> <span class="o_stat_text">
Last Month Last Month
@@ -66,7 +74,15 @@
type="action" attrs="{'invisible': ['|', ('attendance_state', '=', False), '&amp;', ('hr_presence_state', '=', 'present'), ('attendance_state', '=', 'checked_out')]}"> type="action" attrs="{'invisible': ['|', ('attendance_state', '=', False), '&amp;', ('hr_presence_state', '=', 'present'), ('attendance_state', '=', 'checked_out')]}">
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/> <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_green" attrs="{'invisible': [('attendance_state', '=', 'checked_out')]}" aria-label="Available" title="Available"/>
<div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/> <div role="img" id="oe_hr_attendance_status" class="fa fa-fw fa-circle o_button_icon oe_hr_attendance_status_red" attrs="{'invisible': [('attendance_state', '=', 'checked_in')]}" aria-label="Not available" title="Not available"/>
<div class="o_stat_info"> <div class="o_stat_info" attrs="{'invisible': ['|', ('last_check_in', '=', False), ('last_check_out', '!=', False)]}">
<span class="o_stat_text">Present Since</span>
<span class="o_stat_value"><field name="last_check_in" widget="relative_time"/></span>
</div>
<div class="o_stat_info" attrs="{'invisible': [('last_check_out', '=', False)]}">
<span class="o_stat_text">Absent Since</span>
<span class="o_stat_value"><field name="last_check_out" widget="relative_time"/></span>
</div>
<div class="o_stat_info" attrs="{'invisible': [('last_check_in', '!=', False)]}">
<span class="o_stat_text">Attendance</span> <span class="o_stat_text">Attendance</span>
</div> </div>
</button> </button>
@@ -82,7 +98,7 @@
help="Worked hours last month"> help="Worked hours last month">
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="hours_last_month"/> Hours <field name="hours_last_month_display"/> Hours
</span> </span>
<span class="o_stat_text"> <span class="o_stat_text">
Last Month Last Month
@@ -7,6 +7,7 @@
<script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_mode.js"></script> <script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_mode.js"></script>
<script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_confirm.js"></script> <script type="text/javascript" src="/hr_attendance/static/src/js/kiosk_confirm.js"></script>
<script type="text/javascript" src="/hr_attendance/static/src/js/my_attendances.js"></script> <script type="text/javascript" src="/hr_attendance/static/src/js/my_attendances.js"></script>
<script type="text/javascript" src="/hr_attendance/static/src/js/time_widget.js"></script>
<link rel="stylesheet" type="text/scss" href="/hr_attendance/static/src/scss/hr_attendance.scss"/> <link rel="stylesheet" type="text/scss" href="/hr_attendance/static/src/scss/hr_attendance.scss"/>
</xpath> </xpath>
</template> </template>
@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
hr_presence_control_attendance = fields.Boolean(string="the Attendance module", config_parameter='hr_presence.hr_presence_control_attendance')
@@ -27,12 +27,6 @@
<field name="contracts_count" widget="statinfo" string="Contracts"/> <field name="contracts_count" widget="statinfo" string="Contracts"/>
</button> </button>
</div> </div>
<xpath expr="//group[@name='active_group']" position="after">
<group string="Current Contract">
<field name="medic_exam" string="Medical Exam"/>
<field name="vehicle"/>
</group>
</xpath>
<xpath expr="//field[@name='bank_account_id']" position="replace"> <xpath expr="//field[@name='bank_account_id']" position="replace">
<field name="bank_account_id" context="{'display_partner':True}" attrs="{'invisible' : [('address_home_id', '=', False)]}"/> <field name="bank_account_id" context="{'display_partner':True}" attrs="{'invisible' : [('address_home_id', '=', False)]}"/>
</xpath> </xpath>
@@ -89,12 +83,6 @@
<field name="model">res.users</field> <field name="model">res.users</field>
<field name="inherit_id" ref="hr.res_users_view_form_profile"/> <field name="inherit_id" ref="hr.res_users_view_form_profile"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='active_group']" position="after">
<group string="Current Contract">
<field name="medic_exam" string="Medical Exam"/>
<field name="vehicle"/>
</group>
</xpath>
<xpath expr="//field[@name='employee_bank_account_id']" position="replace"> <xpath expr="//field[@name='employee_bank_account_id']" position="replace">
<field name="employee_bank_account_id" context="{'display_partner':True}"/> <field name="employee_bank_account_id" context="{'display_partner':True}"/>
</xpath> </xpath>
+1 -1
View File
@@ -18,7 +18,7 @@ class Employee(models.Model):
return [('groups_id', 'in', group.ids)] if group else [] return [('groups_id', 'in', group.ids)] if group else []
expense_manager_id = fields.Many2one( expense_manager_id = fields.Many2one(
'res.users', string='Expense Responsible', 'res.users', string='Expense',
domain=_group_hr_expense_user_domain, domain=_group_hr_expense_user_domain,
help="User responsible of expense approval. Should be Expense approver.") help="User responsible of expense approval. Should be Expense approver.")
+5 -1
View File
@@ -15,7 +15,7 @@ class HrEmployeeBase(models.AbstractModel):
return [('groups_id', 'in', group.ids)] if group else [] return [('groups_id', 'in', group.ids)] if group else []
leave_manager_id = fields.Many2one( leave_manager_id = fields.Many2one(
'res.users', string='Time Off Responsible', 'res.users', string='Time Off',
domain=_group_hr_user_domain, domain=_group_hr_user_domain,
help="User responsible of leaves approval. Should be Team Leader or Department Manager.") help="User responsible of leaves approval. Should be Team Leader or Department Manager.")
remaining_leaves = fields.Float( remaining_leaves = fields.Float(
@@ -39,6 +39,8 @@ class HrEmployeeBase(models.AbstractModel):
allocation_used_count = fields.Float('Total number of days off used', compute='_compute_total_allocation_used') allocation_used_count = fields.Float('Total number of days off used', compute='_compute_total_allocation_used')
show_leaves = fields.Boolean('Able to see Remaining Time Off', compute='_compute_show_leaves') show_leaves = fields.Boolean('Able to see Remaining Time Off', compute='_compute_show_leaves')
is_absent = fields.Boolean('Absent Today', compute='_compute_leave_status', search='_search_absent_employee') is_absent = fields.Boolean('Absent Today', compute='_compute_leave_status', search='_search_absent_employee')
allocation_display = fields.Char(compute='_compute_allocation_count')
allocation_used_display = fields.Char(compute='_compute_total_allocation_used')
def _get_date_start_work(self): def _get_date_start_work(self):
return self.create_date return self.create_date
@@ -86,10 +88,12 @@ class HrEmployeeBase(models.AbstractModel):
('date_to', '>=', datetime.date.today()), ('date_to', '>=', datetime.date.today()),
]) ])
employee.allocation_count = sum(allocations.mapped('number_of_days')) employee.allocation_count = sum(allocations.mapped('number_of_days'))
employee.allocation_display = "%g" % employee.allocation_count
def _compute_total_allocation_used(self): def _compute_total_allocation_used(self):
for employee in self: for employee in self:
employee.allocation_used_count = employee.allocation_count - employee.remaining_leaves employee.allocation_used_count = employee.allocation_count - employee.remaining_leaves
employee.allocation_used_display = "%g" % employee.allocation_used_count
def _compute_presence_state(self): def _compute_presence_state(self):
super()._compute_presence_state() super()._compute_presence_state()
+4
View File
@@ -13,6 +13,8 @@ class User(models.Model):
allocation_count = fields.Float(related='employee_id.allocation_count') allocation_count = fields.Float(related='employee_id.allocation_count')
leave_date_to = fields.Date(related='employee_id.leave_date_to') leave_date_to = fields.Date(related='employee_id.leave_date_to')
is_absent = fields.Boolean(related='employee_id.is_absent') is_absent = fields.Boolean(related='employee_id.is_absent')
allocation_used_display = fields.Char(related='employee_id.allocation_used_display')
allocation_display = fields.Char(related='employee_id.allocation_display')
def __init__(self, pool, cr): def __init__(self, pool, cr):
""" Override of __init__ to add access rights. """ Override of __init__ to add access rights.
@@ -27,6 +29,8 @@ class User(models.Model):
'allocation_count', 'allocation_count',
'leave_date_to', 'leave_date_to',
'is_absent', 'is_absent',
'allocation_used_display',
'allocation_display',
] ]
init_res = super(User, self).__init__(pool, cr) init_res = super(User, self).__init__(pool, cr)
# duplicate list to avoid modifying the original reference # duplicate list to avoid modifying the original reference
+5 -5
View File
@@ -171,8 +171,8 @@
help="Remaining leaves"> help="Remaining leaves">
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="allocation_used_count" digits="[42,1]"/>/ <field name="allocation_used_display"/>/
<field name="allocation_count" digits="[42,1]"/> <field name="allocation_display"/>
</span> </span>
<span class="o_stat_text"> <span class="o_stat_text">
Time Off Time Off
@@ -198,7 +198,7 @@
<button disabled="1" <button disabled="1"
class="oe_stat_button" class="oe_stat_button"
attrs="{'invisible': [('is_absent', '=', False)]}"> attrs="{'invisible': [('is_absent', '=', False)]}">
<div role="img" class="fa fa-fw fa-plane o_button_icon text-danger" aria-label="Absent Until" title="Absent Until"/> <div role="img" class="fa fa-fw fa-plane o_button_icon text-warning" aria-label="Absent Until" title="Absent Until"/>
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="leave_date_to"/> <field name="leave_date_to"/>
@@ -258,8 +258,8 @@
help="Remaining leaves"> help="Remaining leaves">
<div class="o_field_widget o_stat_info"> <div class="o_field_widget o_stat_info">
<span class="o_stat_value"> <span class="o_stat_value">
<field name="allocation_used_count" digits="[42,1]"/>/ <field name="allocation_used_display"/>/
<field name="allocation_count" digits="[42,1]"/> <field name="allocation_display"/>
</span> </span>
<span class="o_stat_text"> <span class="o_stat_text">
Time Off Time Off
@@ -38,6 +38,7 @@ class HrOrgChartController(http.Controller):
link='/mail/view?model=%s&res_id=%s' % ('hr.employee.public', employee.id,), link='/mail/view?model=%s&res_id=%s' % ('hr.employee.public', employee.id,),
job_id=job.id, job_id=job.id,
job_name=job.name or '', job_name=job.name or '',
job_title=employee.job_title or '',
direct_sub_count=len(employee.child_ids), direct_sub_count=len(employee.child_ids),
indirect_sub_count=employee.child_all_count, indirect_sub_count=employee.child_all_count,
) )
@@ -36,12 +36,12 @@
<t t-if="!is_self"> <t t-if="!is_self">
<a t-att-href="employee.link" class="o_employee_redirect" t-att-data-employee-id="employee.id"> <a t-att-href="employee.link" class="o_employee_redirect" t-att-data-employee-id="employee.id">
<h5 class="o_media_heading"><b><t t-esc="employee.name"/></b></h5> <h5 class="o_media_heading"><b><t t-esc="employee.name"/></b></h5>
<strong><t t-esc="employee.job_name"/></strong> <strong><t t-esc="employee.job_title"/></strong>
</a> </a>
</t> </t>
<t t-if="is_self"> <t t-if="is_self">
<h5 class="o_media_heading"><b><t t-esc="employee.name"/></b></h5> <h5 class="o_media_heading"><b><t t-esc="employee.name"/></b></h5>
<strong><t t-esc="employee.job_name"/></strong> <strong><t t-esc="employee.job_title"/></strong>
</t> </t>
</div> </div>
</div> </div>
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
hr_presence_control_login = fields.Boolean(string="the system login (User status on chat)", config_parameter='hr_presence.hr_presence_control_login')
hr_presence_control_email = fields.Boolean(string="the amount of sent emails", config_parameter='hr_presence.hr_presence_control_email')
hr_presence_control_ip = fields.Boolean(string="the IP address", config_parameter='hr_presence.hr_presence_control_ip')
hr_presence_control_email_amount = fields.Integer(related="company_id.hr_presence_control_email_amount", readonly=False)
hr_presence_control_ip_list = fields.Char(related="company_id.hr_presence_control_ip_list", readonly=False)
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.hr</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="70"/>
<field name="inherit_id" ref="hr.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@data-key='hr']//div[hasclass('o_settings_container')]" position="inside">
<div class="col-12 col-lg-6 o_setting_box" title="Employees Presence Check Based on">
<div class="o_setting_left_pane">
<field name="module_hr_presence"/>
</div>
<div class="o_setting_right_pane">
<label for="module_hr_presence"/>
<div class="content-group" name="hr_presence_options">
<div class="row">
<field name="hr_presence_control_login" class="col-lg-1 ml16"/>
<label for="hr_presence_control_login" class="col-lg-10 o_light_label"/>
</div>
<div class="row">
<field name="hr_presence_control_email" class="col-lg-1 ml16"/>
<label for="hr_presence_control_email" class="col-lg-10 o_light_label"/>
</div>
<div attrs="{'invisible': [('hr_presence_control_email', '=', False)]}">
<span>At least </span>
<field name="hr_presence_control_email_amount"/>
<span> sent emails</span>
</div>
<div class="row">
<field name="hr_presence_control_ip" class="col-lg-1 ml16"/>
<label for="hr_presence_control_ip" class="col-lg-10 o_light_label"/>
</div>
<div attrs="{'invisible': [('hr_presence_control_ip', '=', False)]}">
<span>IP List (comma separated):</span>
<field name="hr_presence_control_ip_list"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
+1
View File
@@ -23,6 +23,7 @@
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'data/hr_recruitment_data.xml', 'data/hr_recruitment_data.xml',
'data/digest_data.xml', 'data/digest_data.xml',
'data/hr_recruitment_templates.xml',
'views/hr_recruitment_views.xml', 'views/hr_recruitment_views.xml',
'views/res_config_settings_views.xml', 'views/res_config_settings_views.xml',
'views/hr_recruitment_templates.xml', 'views/hr_recruitment_templates.xml',
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="applicant_hired_template">
Applicant hired<br/>
<ul>
<li>Employee: <a href="#" t-att-data-oe-id="applicant.emp_id.id" data-oe-model="hr.employee"><t t-esc="applicant.emp_id.name"/></a></li>
</ul>
</template>
</data>
</odoo>
@@ -156,10 +156,10 @@ class Applicant(models.Model):
day_close = fields.Float(compute='_compute_day', string="Days to Close") day_close = fields.Float(compute='_compute_day', string="Days to Close")
delay_close = fields.Float(compute="_compute_day", string='Delay to Close', readonly=True, group_operator="avg", help="Number of days to close", store=True) delay_close = fields.Float(compute="_compute_day", string='Delay to Close', readonly=True, group_operator="avg", help="Number of days to close", store=True)
color = fields.Integer("Color Index", default=0) color = fields.Integer("Color Index", default=0)
emp_id = fields.Many2one('hr.employee', string="Employee", tracking=True, help="Employee linked to the applicant.") emp_id = fields.Many2one('hr.employee', string="Employee", help="Employee linked to the applicant.")
user_email = fields.Char(related='user_id.email', type="char", string="User Email", readonly=True) user_email = fields.Char(related='user_id.email', type="char", string="User Email", readonly=True)
attachment_number = fields.Integer(compute='_get_attachment_number', string="Number of Attachments") attachment_number = fields.Integer(compute='_get_attachment_number', string="Number of Attachments")
employee_name = fields.Char(related='emp_id.name', string="Employee Name", readonly=False) employee_name = fields.Char(related='emp_id.name', string="Employee Name", readonly=False, tracking=False)
attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'hr.applicant')], string='Attachments') attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'hr.applicant')], string='Attachments')
kanban_state = fields.Selection([ kanban_state = fields.Selection([
('normal', 'Grey'), ('normal', 'Grey'),
@@ -461,6 +461,7 @@ class Applicant(models.Model):
employee = self.env['hr.employee'].create({ employee = self.env['hr.employee'].create({
'name': applicant.partner_name or contact_name, 'name': applicant.partner_name or contact_name,
'job_id': applicant.job_id.id or False, 'job_id': applicant.job_id.id or False,
'job_title': applicant.job_id.name,
'address_home_id': address_id, 'address_home_id': address_id,
'department_id': applicant.department_id.id or False, 'department_id': applicant.department_id.id or False,
'address_id': applicant.company_id and applicant.company_id.partner_id 'address_id': applicant.company_id and applicant.company_id.partner_id
@@ -475,6 +476,10 @@ class Applicant(models.Model):
applicant.job_id.message_post( applicant.job_id.message_post(
body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name, body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name,
subtype="hr_recruitment.mt_job_applicant_hired") subtype="hr_recruitment.mt_job_applicant_hired")
applicant.message_post_with_view(
'hr_recruitment.applicant_hired_template',
values={'applicant': applicant},
subtype_id=self.env.ref("hr_recruitment.mt_applicant_hired").id)
employee_action = self.env.ref('hr.open_view_employee_list') employee_action = self.env.ref('hr.open_view_employee_list')
dict_act_window = employee_action.read([])[0] dict_act_window = employee_action.read([])[0]
+13 -1
View File
@@ -16,7 +16,19 @@
<field name="model">hr.employee</field> <field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_filter"/> <field name="inherit_id" ref="hr.view_employee_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='job_id']" position="after"> <xpath expr="//field[@name='job_title']" position="after">
<field name="employee_skill_ids"/>
<field name="resume_line_ids" string="Resumé" filter_domain="['|', ('resume_line_ids.name', 'ilike', self), ('resume_line_ids.description', 'ilike', self)]"/>
</xpath>
</field>
</record>
<record id="hr_employee_public_view_search" model="ir.ui.view">
<field name="name">hr.employee.public.skill.search</field>
<field name="model">hr.employee.public</field>
<field name="inherit_id" ref="hr.hr_employee_public_view_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='company_id']" position="after">
<field name="employee_skill_ids"/> <field name="employee_skill_ids"/>
<field name="resume_line_ids" string="Resumé" filter_domain="['|', ('resume_line_ids.name', 'ilike', self), ('resume_line_ids.description', 'ilike', self)]"/> <field name="resume_line_ids" string="Resumé" filter_domain="['|', ('resume_line_ids.name', 'ilike', self), ('resume_line_ids.description', 'ilike', self)]"/>
</xpath> </xpath>
+3 -7
View File
@@ -8,12 +8,8 @@
<field name="model">res.users</field> <field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form_simple_modif"/> <field name="inherit_id" ref="base.view_users_form_simple_modif"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//footer" position="before"> <xpath expr="//group[@name='out of office']" position="inside">
<group name="livechat" string="Livechat Preferences"> <field name="livechat_username" string="Online Chat Username" readonly="0"/>
<group>
<field name="livechat_username" readonly="0"/>
</group>
</group>
</xpath> </xpath>
</field> </field>
</record> </record>
@@ -24,7 +20,7 @@
<field name="model">res.users</field> <field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/> <field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='messaging']" position="after"> <xpath expr="//group[@name='messaging']" position="inside">
<group name="livechat" string="Livechat"> <group name="livechat" string="Livechat">
<field name="livechat_username"/> <field name="livechat_username"/>
</group> </group>
+1 -1
View File
@@ -28,7 +28,7 @@ class Users(models.Model):
notification_type = fields.Selection([ notification_type = fields.Selection([
('email', 'Handle by Emails'), ('email', 'Handle by Emails'),
('inbox', 'Handle in Odoo')], ('inbox', 'Handle in Odoo')],
'Notification Management', required=True, default='email', 'Notification', required=True, default='email',
help="Policy on how to handle Chatter notifications:\n" help="Policy on how to handle Chatter notifications:\n"
"- Handle by Emails: notifications are sent to your email address\n" "- Handle by Emails: notifications are sent to your email address\n"
"- Handle in Odoo: notifications appear in your Odoo Inbox") "- Handle in Odoo: notifications appear in your Odoo Inbox")
+1 -1
View File
@@ -13,7 +13,7 @@
<field name="notification_type" widget="radio" readonly="0"/> <field name="notification_type" widget="radio" readonly="0"/>
</field> </field>
<xpath expr="//group[@name='signature']" position="after"> <xpath expr="//group[@name='signature']" position="after">
<group string="Chat Status" name="out of office"> <group string="Chat" name="out of office">
<field name="out_of_office_message" readonly="0"/> <field name="out_of_office_message" readonly="0"/>
</group> </group>
</xpath> </xpath>
@@ -106,7 +106,7 @@ function formatChar(value, field, options) {
* @returns {string} * @returns {string}
*/ */
function formatDate(value, field, options) { function formatDate(value, field, options) {
if (value === false) { if (value === false || isNaN(value)) {
return ""; return "";
} }
if (field && field.type === 'datetime') { if (field && field.type === 'datetime') {
+1 -1
View File
@@ -240,7 +240,7 @@ class Users(models.Model):
# Special behavior for this field: res.company.search() will only return the companies # Special behavior for this field: res.company.search() will only return the companies
# available to the current user (should be the user's companies?), when the user_preference # available to the current user (should be the user's companies?), when the user_preference
# context is set. # context is set.
company_id = fields.Many2one('res.company', string='Default Company', required=True, default=lambda self: self.env.company.id, company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company.id,
help='The default company for this user.', context={'user_preference': True}) help='The default company for this user.', context={'user_preference': True})
company_ids = fields.Many2many('res.company', 'res_company_users_rel', 'user_id', 'cid', company_ids = fields.Many2many('res.company', 'res_company_users_rel', 'user_id', 'cid',
string='Companies', default=lambda self: self.env.company.ids) string='Companies', default=lambda self: self.env.company.ids)