Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions addons/hr/models/hr_employee.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,9 @@ def _lang_get(self):
}
"""

permit_no = fields.Char('Work Permit No', groups="hr.group_hr_user", tracking=True)
visa_no = fields.Char('Visa No', groups="hr.group_hr_user", tracking=True)
visa_expire = fields.Date('Visa Expiration Date', groups="hr.group_hr_user", tracking=True)
work_permit_expiration_date = fields.Date('Work Permit Expiration Date', groups="hr.group_hr_user", tracking=True)
has_work_permit = fields.Binary(string="Work Permit", groups="hr.group_hr_user")
work_permit_scheduled_activity = fields.Boolean(default=False, groups="hr.group_hr_user")
work_permit_name = fields.Char('work_permit_name', compute='_compute_work_permit_name', groups="hr.group_hr_user")
certificate = fields.Selection(selection='_get_certificate_selection', string='Certificate Level', groups="hr.group_hr_user", tracking=True)
study_field = fields.Char("Field of Study", groups="hr.group_hr_user", tracking=True)
emergency_contact = fields.Char(groups="hr.group_hr_user", tracking=True)
Expand Down Expand Up @@ -649,8 +645,7 @@ def _compute_split_legal_name(self):
@api.depends('current_version_id')
@api.depends_context('version_id')
def _compute_version_id(self):
context_version_id = self.env.context.get('version_id', False)
context_version = self.env['hr.version'].browse(context_version_id).exists() if context_version_id else self.env['hr.version']
context_version = self.env['hr.version'].browse(self.env.context.get('version_id', False))

for employee in self:
if context_version.employee_id == self:
Expand Down Expand Up @@ -1197,13 +1192,6 @@ def _compute_birthday_public_display_string(self):
else:
employee.birthday_public_display_string = "hidden"

@api.depends('name', 'permit_no')
def _compute_work_permit_name(self):
for employee in self:
name = employee.name.replace(' ', '_') + '_' if employee.name else ''
permit_no = '_' + employee.permit_no if employee.permit_no else ''
employee.work_permit_name = "%swork_permit%s" % (name, permit_no)

def _get_partner_count_depends(self):
return ['user_id']

Expand Down
12 changes: 12 additions & 0 deletions addons/hr/models/hr_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ def _get_hr_responsible_domain(self):
('other', 'Other'),
], groups="hr.group_hr_user", tracking=1, help="This is the legal sex as recognized by the state, used for official and statutory purposes.")

permit_no = fields.Char('Work Permit No', groups="hr.group_hr_user")
work_permit_expiration_date = fields.Date('Work Permit Expiration Date', groups="hr.group_hr_user")
work_permit_scheduled_activity = fields.Boolean(default=False, groups="hr.group_hr_user")
work_permit_name = fields.Char('work_permit_name', compute='_compute_work_permit_name', groups="hr.group_hr_user")

private_street = fields.Char(string="Private Street", groups="hr.group_hr_user", tracking=1)
private_street2 = fields.Char(string="Private Street2", groups="hr.group_hr_user", tracking=1)
private_city = fields.Char(string="Private City", groups="hr.group_hr_user", tracking=1)
Expand Down Expand Up @@ -243,6 +248,13 @@ def _compute_allowed_country_state_ids(self):
for version in versions_without_countries:
version.allowed_country_state_ids = states

@api.depends('employee_id.name', 'permit_no')
def _compute_work_permit_name(self):
for version in self:
emp_name = version.employee_id.name.replace(' ', '_') + '_' if version.employee_id and version.employee_id.name else ''
permit_no = '_' + version.permit_no if version.permit_no else ''
version.work_permit_name = f"{emp_name}work_permit{permit_no}"

@api.constrains('employee_id', 'contract_date_start', 'contract_date_end')
def _check_dates(self):
version_read_group = self.env['hr.version'].sudo()._read_group(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<t t-name="hr.ButtonNewContract">
<span class="w-100 d-flex justify-content-end">
<button class="btn btn-link p-0 o_field_widget text-end w-auto text-nowrap" t-on-click="this.onClickNewContractBtn"
t-ref="this.datetimePickerTargetRef" t-if="this.props.record.resId and this.props.record.data.contract_date_start">New Contract</button>
t-ref="this.datetimePickerTargetRef" t-if="this.props.record.resId">New Contract</button>
</span>
</t>
</template>
21 changes: 0 additions & 21 deletions addons/hr/tests/test_hr_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,27 +523,6 @@ def test_multi_edit_other_and_contract_date_sync(self):
self.assertEqual(version.job_id.id, jobB.id)
self.assertEqual(version.contract_date_end, date(2020, 9, 30))

def test_delete_version(self):
employee = self.env['hr.employee'].create({
'name': 'John Doe',
'date_version': '2020-01-01',
})
v1 = employee.version_id
v2 = employee.create_version({
'date_version': '2021-01-01',
})
v3 = employee.create_version({
'date_version': '2022-01-01',
})
self.assertEqual(employee.current_version_id, v3)

v3.unlink()
self.assertEqual(employee.current_version_id, v2)
v1.unlink()
self.assertEqual(employee.current_version_id, v2)
with self.assertRaises(ValidationError):
v2.unlink()

def test_multi_edit_multi_employees_no_contract(self):
"""
Test the multi-edit when there is one version per employee, without contract
Expand Down
2 changes: 1 addition & 1 deletion addons/hr/views/hr_employee_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@
<span invisible="not contract_date_start">to</span>
<field name="contract_date_end" string="End Date" placeholder="Indefinite" widget="date_dynamic_min" options="{'min_date_field': 'contract_date_start'}"
class="o_hr_narrow_field ms-3" invisible="not contract_date_start"/>
<widget name="button_new_contract"/>
<widget name="button_new_contract" invisible="not contract_date_start"/>
</div>
<field name="fixed_term" string="Fixed Term" invisible="1"/>
<label for="wage"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
}

.o_accrual {
.o_field_accrual, .o_field_selection, .o_field_day_selection, .o_field_filterable_selection {
.o_field_accrual, .o_field_selection, .o_field_filterable_selection {
width: fit-content !important;

&:not(.o_readonly_modifier) > *:first-child {
Expand All @@ -20,7 +20,7 @@
field-sizing: content;
}

&:not(.o_field_selection, .o_field_day_selection, .o_field_filterable_selection) > *:first-child {
&:not(.o_field_selection, .o_field_filterable_selection) > *:first-child {
max-width: 8ch;
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { t, useProps } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { SelectionField, selectionField, selectionFieldProps } from "@web/views/fields/selection/selection_field";

export class DynamicDaySelectionField extends SelectionField {
props = useProps({
...selectionFieldProps,
monthFieldName: t.string().optional(),
});

get options() {
const allOptions = super.options;
const monthFieldName = this.props.monthFieldName;
const monthValue = this.props.record.data[monthFieldName];

if (!monthValue) {
return allOptions;
}

// Leap year so that February always gets 29 days.
const maxDays = new Date(2004, monthValue, 0).getDate();

const filteredOptions = allOptions.filter(option => {
if (!option[0]) {
return true;
}
return parseInt(option[0]) <= maxDays;
});

return filteredOptions;
}
}

export const dynamicDaySelection = {
...selectionField,
component: DynamicDaySelectionField,

extractProps({ attrs }) {
return {
...selectionField.extractProps(...arguments),
monthFieldName: attrs.month_field,
};
},

fieldDependencies: ({ attrs }) => {
return [
{
name: attrs.month_field,
type: "selection",
},
];
},
};

registry.category("fields").add("dynamic_day_selection", dynamicDaySelection);
22 changes: 22 additions & 0 deletions addons/hr_holidays/tests/test_hr_work_entry_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,25 @@ def test_change_count_days_as(self):

with self.assertRaises(ValidationError):
work_entry_type.count_days_as = 'working'

def test_time_off_type_dropdown_search(self):
""" Test that loading the time off types (hr.work.entry.type) dropdown list
does not raise any traceback during search or selection.
"""
self.env['hr.work.entry.type'].create({
'name': 'Test Paid Time Off',
'code': 'TPTO',
'requires_allocation': True,
'request_unit': 'day',
'unit_of_measure': 'day',
})

domain = [('virtual_remaining_leaves', '>', 0)]

res = self.env['hr.work.entry.type'].with_user(self.user_employee_id).name_search(
name='',
domain=domain,
operator='ilike',
limit=8,
)
self.assertIsNotNone(res)
10 changes: 5 additions & 5 deletions addons/hr_holidays/views/hr_leave_accrual_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@
</span>
<span name="biyearly" invisible="frequency != 'biyearly'">
on the
<field nolabel="1" name="first_month_day" class="o_hr_narrow_field-3" widget="day_selection" month_field="first_month" placeholder="select a day" required="frequency == 'biyearly'"/>
<field nolabel="1" name="first_month_day" class="o_hr_narrow_field-3" placeholder="select a day" required="frequency == 'biyearly'" widget="dynamic_day_selection" month_field="first_month"/>
of
<field name="first_month" class="o_hr_narrow_field-5" placeholder="select a month" required="frequency == 'biyearly'"/>
and the
<field nolabel="1" name="second_month_day" class="o_hr_narrow_field-3" widget="day_selection" month_field="second_month" placeholder="select a day" required="frequency == 'biyearly'"/>
<field nolabel="1" name="second_month_day" class="o_hr_narrow_field-3" placeholder="select a day" required="frequency == 'biyearly'" widget="dynamic_day_selection" month_field="second_month"/>
of
<field nolabel="1" name="second_month" class="o_hr_narrow_field-5" placeholder="select a month" required="frequency == 'biyearly'"/>
</span>
<span name="yearly" invisible="frequency != 'yearly'">
on the
<field nolabel="1" name="yearly_day" class="o_hr_narrow_field-3" widget="day_selection" month_field="yearly_month" required="frequency == 'yearly'" placeholder="select a day"/>
<field nolabel="1" name="yearly_day" class="o_hr_narrow_field-3" required="frequency == 'yearly'" placeholder="select a day" widget="dynamic_day_selection" month_field="yearly_month"/>
of
<field nolabel="1" name="yearly_month" class="o_hr_narrow_field-5" required="frequency == 'yearly'" placeholder="select a month"/>
</span>
Expand Down Expand Up @@ -204,8 +204,8 @@
options="{'links': {'other': 'carryover_custom_date'}, 'observe': 'carryover'}"/>
<span id="carryover_custom_date">
: the
<field name="carryover_day" widget="day_selection" month_field="carryover_month" placeholder="select a day"
required="carryover_date == 'other'"/>
<field name="carryover_day" placeholder="select a day" class="o_hr_narrow_field-3"
required="carryover_date == 'other'" widget="dynamic_day_selection" month_field="carryover_month"/>
of
<field name="carryover_month" placeholder="select a month"
required="carryover_date == 'other'"/>
Expand Down
1 change: 1 addition & 0 deletions addons/hr_skills/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'data/ir_actions_server_data.xml',
'data/ir_cron_data.xml',
'data/report_paperformat.xml',
'report/hr_employee_certification_report_views.xml',
'report/hr_employee_skill_history_report_views.xml',
'report/hr_employee_skill_report_views.xml',
'report/hr_employee_cv_report.xml',
Expand Down
1 change: 1 addition & 0 deletions addons/hr_skills/report/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from . import hr_employee_certification_report
from . import hr_employee_cv_report
from . import hr_employee_skill_history_report
from . import hr_employee_skill_report
47 changes: 47 additions & 0 deletions addons/hr_skills/report/hr_employee_certification_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import fields, models, tools


class HrEmployeeCertificationReport(models.BaseModel):
_name = 'hr.employee.certification.report'
_auto = False
_inherit = ["hr.manager.department.report"]
_description = 'Employee Certification Report'
_order = 'employee_id, level_progress desc'

company_id = fields.Many2one('res.company', readonly=True)
department_id = fields.Many2one('hr.department', readonly=True)

skill_id = fields.Many2one('hr.skill', readonly=True)
skill_type_id = fields.Many2one('hr.skill.type', readonly=True)
skill_level = fields.Char(readonly=True)
level_progress = fields.Float(readonly=True, aggregator='avg')
active = fields.Boolean(readonly=False)

def init(self):
tools.drop_view_if_exists(self.env.cr, self._table)

self.env.cr.execute("""
CREATE OR REPLACE VIEW %(table)s AS (
SELECT
row_number() OVER () AS id,
e.id AS employee_id,
e.company_id AS company_id,
v.department_id AS department_id,
s.skill_id AS skill_id,
s.skill_type_id AS skill_type_id,
sl.level_progress / 100.0 AS level_progress,
sl.name AS skill_level,
(s.valid_to IS NULL OR s.valid_to >= '%(date)s') AND s.valid_from <= '%(date)s' AS active
FROM hr_employee e
LEFT JOIN hr_version v ON e.current_version_id = v.id
LEFT OUTER JOIN hr_employee_skill s ON e.id = s.employee_id
LEFT OUTER JOIN hr_skill_level sl ON sl.id = s.skill_level_id
LEFT OUTER JOIN hr_skill_type st ON st.id = sl.skill_type_id
WHERE e.active AND st.active IS True AND st.is_certification IS TRUE
)
""" % {
'table': self._table,
'date': fields.Date.context_today(self)
})
Loading