diff --git a/hr_payroll_timesheet/__init__.py b/hr_payroll_timesheet/__init__.py deleted file mode 100644 index dc1ae41b..00000000 --- a/hr_payroll_timesheet/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from . import models - - -def ts_payroll_pre_init_hook(cr): - """ - This module installs a Work Entry Type with code "TS_OT" - If you have undergone a migration (either for this module - or even your own Payslip Work Entry lines with code "TS_OT") - then the uniqueness constraint will prevent this module - from installing. - """ - cr.execute("UPDATE hr_work_entry_type " - "SET code = 'TS_OT-PRE-INSTALL-15' " - "WHERE code = 'TS_OT';" - ) diff --git a/hr_payroll_timesheet/__manifest__.py b/hr_payroll_timesheet/__manifest__.py deleted file mode 100755 index 95c40294..00000000 --- a/hr_payroll_timesheet/__manifest__.py +++ /dev/null @@ -1,27 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -{ - 'name': 'Timesheets on Payslips', - 'description': 'Get Timesheet hours onto Employee Payslips.', - 'version': '15.0.1.0.0', - 'website': 'https://hibou.io/', - 'author': 'Hibou Corp. ', - 'license': 'OPL-1', - 'category': 'Human Resources', - 'data': [ - 'data/hr_payroll_timesheet_data.xml', - 'views/hr_contract_view.xml', - 'views/hr_payslip_views.xml', - 'views/timesheet_views.xml', - ], - 'demo': [ - 'data/hr_payroll_timesheet_demo.xml', - ], - 'depends': [ - 'hr_payroll_hibou', - 'hr_timesheet_work_entry', - 'hr_payroll_overtime', - 'hibou_professional', - ], - 'pre_init_hook': 'ts_payroll_pre_init_hook', -} diff --git a/hr_payroll_timesheet/data/hr_payroll_timesheet_data.xml b/hr_payroll_timesheet/data/hr_payroll_timesheet_data.xml deleted file mode 100644 index 69ae14c0..00000000 --- a/hr_payroll_timesheet/data/hr_payroll_timesheet_data.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Timesheet Overtime - TS_OT - - - - - - - - diff --git a/hr_payroll_timesheet/data/hr_payroll_timesheet_demo.xml b/hr_payroll_timesheet/data/hr_payroll_timesheet_demo.xml deleted file mode 100644 index af096c6b..00000000 --- a/hr_payroll_timesheet/data/hr_payroll_timesheet_demo.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/hr_payroll_timesheet/i18n/es.po b/hr_payroll_timesheet/i18n/es.po deleted file mode 100644 index f4c192f6..00000000 --- a/hr_payroll_timesheet/i18n/es.po +++ /dev/null @@ -1,80 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * hr_payroll_timesheet -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 15.0+e\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-11-01 22:03+0000\n" -"PO-Revision-Date: 2021-11-01 22:03+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: hr_payroll_timesheet -#: model:ir.model,name:hr_payroll_timesheet.model_account_analytic_line -msgid "Analytic Line" -msgstr "Línea Analítica" - -#. module: hr_payroll_timesheet -#: code:addons/hr_payroll_timesheet/models/account.py:0 -#, python-format -msgid "Cannot create attendance linked to payslip that is not draft." -msgstr "No se puede crear una asistencia vinculada a una nómina que no es un borrador" - -#. module: hr_payroll_timesheet -#: code:addons/hr_payroll_timesheet/models/account.py:0 -#, python-format -msgid "Cannot modify attendance linked to payslip that is not draft." -msgstr "No se puede modificar una asistencia vinculada a una nómina que no es un borrador" - -#. module: hr_payroll_timesheet -#: model:ir.model,name:hr_payroll_timesheet.model_hr_contract -msgid "Employee Contract" -msgstr "Contrato del empleado" - -#. module: hr_payroll_timesheet -#: model:ir.model.fields,field_description:hr_payroll_timesheet.field_hr_contract__paid_hourly_timesheet -msgid "Paid Hourly Timesheet" -msgstr "Fichas de Horario Pagada por Hora" - -#. module: hr_payroll_timesheet -#: code:addons/hr_payroll_timesheet/models/hr_payslip.py:0 -#, python-format -msgid "Paid Timesheets" -msgstr "Fichas de Horario Pagadas" - -#. module: hr_payroll_timesheet -#: model:ir.model,name:hr_payroll_timesheet.model_hr_payslip -msgid "Pay Slip" -msgstr "Recibo de nómina" - -#. module: hr_payroll_timesheet -#: model:ir.model.fields,field_description:hr_payroll_timesheet.field_account_analytic_line__payslip_id -msgid "Payslip" -msgstr "Recibo de nómina" - -#. module: hr_payroll_timesheet -#: model:ir.model.fields,field_description:hr_payroll_timesheet.field_hr_payslip__timesheet_count -msgid "Timesheet Count" -msgstr "Recuento de Fichas de Horario" - -#. module: hr_payroll_timesheet -#: model:hr.work.entry.type,name:hr_payroll_timesheet.work_input_timesheet_overtime -msgid "Timesheet Overtime" -msgstr "Ficha de Horario de Horas Extra" - -#. module: hr_payroll_timesheet -#: model:ir.model.fields,field_description:hr_payroll_timesheet.field_hr_payslip__timesheet_ids -#: model_terms:ir.ui.view,arch_db:hr_payroll_timesheet.hr_payslip_view_form_inherit -msgid "Timesheets" -msgstr "Ficha de Horario" - -#. module: hr_payroll_timesheet -#: model:ir.model.fields,help:hr_payroll_timesheet.field_hr_payslip__timesheet_ids -msgid "Timesheets represented by payslip." -msgstr "Fichas de Horario representados por un recibo de nomina" diff --git a/hr_payroll_timesheet/models/__init__.py b/hr_payroll_timesheet/models/__init__.py deleted file mode 100644 index 6683136f..00000000 --- a/hr_payroll_timesheet/models/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import account -from . import hr_contract -from . import hr_payslip diff --git a/hr_payroll_timesheet/models/account.py b/hr_payroll_timesheet/models/account.py deleted file mode 100644 index 32c90bbf..00000000 --- a/hr_payroll_timesheet/models/account.py +++ /dev/null @@ -1,35 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from odoo import api, fields, models, _ -from odoo.exceptions import ValidationError - - -class AnalyticLine(models.Model): - _inherit = 'account.analytic.line' - - payslip_id = fields.Many2one('hr.payslip', string="Payslip", ondelete='set null') - - @api.model_create_multi - def create(self, vals_list): - if isinstance(vals_list, dict): - vals_list = [vals_list] - - payslip_ids = [i for i in set([d.get('payslip_id') or 0 for d in vals_list]) if i != 0] - if payslip_ids: - payslips = self.env['hr.payslip'].sudo().browse(payslip_ids) - if any(p.state not in ('draft', 'verify') for p in payslips): - raise ValidationError(_('Cannot create timesheet linked to payslip that is not draft.')) - return super().create(vals_list) - - def write(self, values): - payslip_id = values.get('payslip_id') - if payslip_id: - payslip = self.env['hr.payslip'].sudo().browse(payslip_id) - if payslip.exists().state not in ('draft', 'verify'): - raise ValidationError(_('Cannot modify timesheet linked to payslip that is not draft.')) - return super().write(values) - - def unlink(self): - ts_with_payslip = self.filtered(lambda ts: ts.payslip_id) - ts_with_payslip.write({'payslip_id': False}) - return super(AnalyticLine, self - ts_with_payslip).unlink() diff --git a/hr_payroll_timesheet/models/hr_contract.py b/hr_payroll_timesheet/models/hr_contract.py deleted file mode 100644 index f9d7501d..00000000 --- a/hr_payroll_timesheet/models/hr_contract.py +++ /dev/null @@ -1,16 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from odoo import api, fields, models - - -class HrContract(models.Model): - _inherit = 'hr.contract' - - paid_hourly_timesheet = fields.Boolean(string="Paid Hourly Timesheet", default=False) - - @api.onchange('paid_hourly_timesheet') - def _onchange_paid_hourly_timesheet(self): - for contract in self: - if contract.paid_hourly_timesheet: - # only allow switch, not automatic switch 'back' - contract.wage_type = 'hourly' diff --git a/hr_payroll_timesheet/models/hr_payslip.py b/hr_payroll_timesheet/models/hr_payslip.py deleted file mode 100644 index 278a20db..00000000 --- a/hr_payroll_timesheet/models/hr_payslip.py +++ /dev/null @@ -1,73 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from odoo import api, fields, models, _ - - -class HrPayslip(models.Model): - _inherit = 'hr.payslip' - - timesheet_ids = fields.One2many('account.analytic.line', 'payslip_id', string='Timesheets', - help='Timesheets represented by payslip.', readonly=True, - states={'draft': [('readonly', False)], 'verify': [('readonly', False)]}) - timesheet_count = fields.Integer(compute='_compute_timesheet_count') - - @api.depends('timesheet_ids', 'timesheet_ids.payslip_id') - def _compute_timesheet_count(self): - for payslip in self: - payslip.timesheet_count = len(payslip.timesheet_ids) - - def _filter_worked_day_lines_values(self, worked_day_lines_values): - worked_day_lines_values = super()._filter_worked_day_lines_values(worked_day_lines_values) - if self.contract_id.paid_hourly_timesheet: - original_work_type = self.env.ref('hr_work_entry.work_entry_type_attendance', raise_if_not_found=False) - if original_work_type: - # filter out "work calendar lines" - return [w for w in worked_day_lines_values if w['work_entry_type_id'] != original_work_type.id] - return worked_day_lines_values - - def _pre_aggregate_work_data(self): - work_data = super()._pre_aggregate_work_data() - if self.contract_id.paid_hourly_timesheet: - timesheet_to_keep = self.timesheet_ids.filtered(lambda ts: ts.employee_id == self.employee_id - and ts.date <= self.date_to) - timesheet_to_keep |= self.env['account.analytic.line'].search([ - ('employee_id', '=', self.employee_id.id), - ('date', '<=', self.date_to), - ('payslip_id', '=', False), - ]) - self.update({'timesheet_ids': [(6, 0, timesheet_to_keep.ids)]}) - - timesheet_type = self.env.ref('hr_timesheet_work_entry.work_input_timesheet', raise_if_not_found=False) - if not timesheet_type: - # different default type - timesheet_type = self.struct_id.type_id.default_work_entry_type_id - if not timesheet_type: - # return early, include the "work calendar lines" - return work_data - work_data = self._pre_aggregate_timesheet_data(work_data, timesheet_type) - return work_data - - def _pre_aggregate_timesheet_data(self, work_data, default_workentrytype): - for ts in self.timesheet_ids.sorted('create_date'): - if ts.unit_amount: - ts_iso = ts.date.isocalendar() - timesheet_type = ts.work_type_id or default_workentrytype - if timesheet_type in self.struct_id.unpaid_work_entry_type_ids: - # this is unpaid, so we have to skip it from aggregation - continue - work_data[ts_iso].append((timesheet_type, ts.unit_amount, ts)) - return work_data - - def action_open_timesheets(self): - self.ensure_one() - return { - 'type': 'ir.actions.act_window', - 'name': _('Paid Timesheets'), - 'res_model': 'account.analytic.line', - 'view_mode': 'tree,form', - 'context': { - 'default_employee_id': self.employee_id.id, - 'default_payslip_id': self.id, - }, - 'domain': [('id', 'in', self.timesheet_ids.ids)], - } diff --git a/hr_payroll_timesheet/tests/__init__.py b/hr_payroll_timesheet/tests/__init__.py deleted file mode 100755 index 1345fb8f..00000000 --- a/hr_payroll_timesheet/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import test_payslip_timesheet diff --git a/hr_payroll_timesheet/tests/test_payslip_timesheet.py b/hr_payroll_timesheet/tests/test_payslip_timesheet.py deleted file mode 100644 index c1c348b5..00000000 --- a/hr_payroll_timesheet/tests/test_payslip_timesheet.py +++ /dev/null @@ -1,246 +0,0 @@ -# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. - -from odoo.addons.hr_payroll_hibou.tests import common -from odoo.exceptions import ValidationError - - -class TestPayslipTimesheet(common.TestPayslip): - - def setUp(self): - super(TestPayslipTimesheet, self).setUp() - - self.work_type = self.env.ref('hr_timesheet_work_entry.work_input_timesheet') - self.overtime_rules = self.work_type.overtime_type_id - self.overtime_rules.hours_per_day = 0.0 - self.overtime_rules.multiplier = 1.5 - - self.test_hourly_wage = 21.5 - self.employee = self._createEmployee() - self.contract = self._createContract(self.employee, - wage=self.test_hourly_wage, - hourly_wage=self.test_hourly_wage, - wage_type='hourly', - paid_hourly_timesheet=True) - - self.work_entry_type_leave = self.env['hr.work.entry.type'].create({ - 'name': 'Test PTO', - 'code': 'TESTPTO', - 'is_leave': True, - }) - self.project = self.env['project.project'].create({ - 'name': 'Timesheets', - }) - - # self.test_hourly_wage = 21.5 - # self.employee = self.env.ref('hr.employee_hne') - # self.contract = self.env['hr.contract'].create({ - # 'name': 'Test', - # 'employee_id': self.employee.id, - # 'structure_type_id': self.env.ref('hr_payroll.structure_type_employee').id, - # 'date_start': '2018-01-01', - # 'resource_calendar_id': self.employee.resource_calendar_id.id, - # 'wage': self.test_hourly_wage, - # 'paid_hourly_timesheet': True, - # 'state': 'open', - # }) - # self.payslip_dummy = self.env['hr.payslip'].create({ - # 'name': 'test slip dummy', - # 'employee_id': self.employee.id, - # 'date_from': '2017-01-01', - # 'date_to': '2017-01-31', - # }) - # self.payslip = self.env['hr.payslip'].create({ - # 'name': 'test slip', - # 'employee_id': self.employee.id, - # 'date_from': '2018-01-01', - # 'date_to': '2018-01-31', - # }) - # self.project = self.env['project.project'].create({ - # 'name': 'Timesheets', - # }) - # self.work_entry_type_leave = self.env['hr.work.entry.type'].create({ - # 'name': 'Test PTO', - # 'code': 'TESTPTO', - # 'is_leave': True, - # }) - # self.leave_type = self.env['hr.leave.type'].create({ - # 'name': 'Test Paid Time Off', - # 'time_type': 'leave', - # 'allocation_type': 'no', - # 'validity_start': False, - # 'work_entry_type_id': self.work_entry_type_leave.id, - # }) - - - def test_payslip_timesheet(self): - self.assertTrue(self.contract.paid_hourly_timesheet) - - # Day 1 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-01', - 'unit_amount': 5.0, - 'name': 'test', - }) - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-01', - 'unit_amount': 3.0, - 'name': 'test', - }) - - # Day 2 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-02', - 'unit_amount': 10.0, - 'name': 'test', - }) - - self.payslip_dummy = self._createPayslip(self.employee, '2017-01-01', '2017-01-31') - # Make one that should be excluded. - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2017-01-01', - 'unit_amount': 5.0, - 'name': 'test', - 'payslip_id': self.payslip_dummy.id, - }) - - self.payslip = self._createPayslip(self.employee, '2018-01-01', '2018-01-31') - self.assertTrue(self.payslip.contract_id, 'No auto-discovered contract!') - wage = self.test_hourly_wage - self.assertTrue(self.payslip.worked_days_line_ids) - - timesheet_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == 'TS') - self.assertTrue(timesheet_line) - self.assertEqual(timesheet_line.number_of_days, 2.0) - self.assertEqual(timesheet_line.number_of_hours, 18.0) - self.assertEqual(timesheet_line.amount, 18.0 * wage) - - # Day 3 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-03', - 'unit_amount': 10.0, - 'name': 'test', - }) - # Day 4 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-04', - 'unit_amount': 10.0, - 'name': 'test', - }) - # Day 5 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-05', - 'unit_amount': 10.0, - 'name': 'test', - }) - # Day 6 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-06', - 'unit_amount': 4.0, - 'name': 'test', - }) - - self.payslip.state = 'draft' - self.payslip.action_refresh_from_work_entries() - timesheet_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == 'TS') - timesheet_overtime_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == 'TS_OT') - self.assertTrue(timesheet_line) - self.assertEqual(timesheet_line.number_of_days, 5.0) - self.assertEqual(timesheet_line.number_of_hours, 40.0) - self.assertTrue(timesheet_overtime_line) - self.assertEqual(timesheet_overtime_line.number_of_days, 1.0) - self.assertEqual(timesheet_overtime_line.number_of_hours, 12.0) - - def test_payslip_timesheet_specific_work_entry_type(self): - self.assertTrue(self.contract.paid_hourly_timesheet) - worktype = self.env.ref('hr_timesheet_work_entry.work_input_timesheet_internal') - - # Day 1 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-01', - 'unit_amount': 5.0, - 'name': 'test', - }) - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-01', - 'unit_amount': 3.0, - 'name': 'test', - }) - - # Day 2 - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2018-01-02', - 'unit_amount': 10.0, - 'name': 'test', - 'work_type_id': worktype.id, - }) - - self.payslip_dummy = self._createPayslip(self.employee, '2017-01-01', '2017-01-31') - # Make one that should be excluded. - self.env['account.analytic.line'].create({ - 'employee_id': self.employee.id, - 'project_id': self.project.id, - 'date': '2017-01-01', - 'unit_amount': 5.0, - 'name': 'test', - 'payslip_id': self.payslip_dummy.id, - }) - - self.payslip = self._createPayslip(self.employee, '2018-01-01', '2018-01-31') - self.assertTrue(self.payslip.contract_id, 'No auto-discovered contract!') - wage = self.test_hourly_wage - self.assertTrue(self.payslip.worked_days_line_ids) - - timesheet_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == 'TS') - self.assertTrue(timesheet_line) - self.assertEqual(timesheet_line.number_of_days, 1.0) - self.assertEqual(timesheet_line.number_of_hours, 8.0) - - worktype_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == worktype.code) - self.assertTrue(worktype_line) - self.assertEqual(worktype_line.number_of_days, 1.0) - self.assertEqual(worktype_line.number_of_hours, 10.0) - - - def test_with_leave(self): - date_from = '2020-01-10' - date_to = '2020-01-11' - self.env['resource.calendar.leaves'].create({ - 'name': 'Doctor Appointment', - 'date_from': date_from, - 'date_to': date_to, - 'resource_id': self.employee.resource_id.id, - 'calendar_id': self.employee.resource_calendar_id.id, - 'work_entry_type_id': self.work_entry_type_leave.id, - 'time_type': 'leave', - }) - - self.payslip = self._createPayslip(self.employee, '2020-01-06', '2020-01-19') - self.assertTrue(self.payslip.worked_days_line_ids) - - leave_line = self.payslip.worked_days_line_ids.filtered(lambda l: l.code == 'TESTPTO') - self.assertTrue(leave_line) - self.assertEqual(leave_line.number_of_days, 1.0) - self.assertEqual(leave_line.number_of_hours, 8.0) - self.assertEqual(leave_line.amount, 8.0 * self.test_hourly_wage) diff --git a/hr_payroll_timesheet/views/hr_contract_view.xml b/hr_payroll_timesheet/views/hr_contract_view.xml deleted file mode 100755 index 48c41e75..00000000 --- a/hr_payroll_timesheet/views/hr_contract_view.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - hr.contract.form.inherit - hr.contract - - - - - - - - diff --git a/hr_payroll_timesheet/views/hr_payslip_views.xml b/hr_payroll_timesheet/views/hr_payslip_views.xml deleted file mode 100644 index 8b193a26..00000000 --- a/hr_payroll_timesheet/views/hr_payslip_views.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - hr.payslip.view.form.inherit - hr.payslip - - - - - - - - - - - - diff --git a/hr_payroll_timesheet/views/timesheet_views.xml b/hr_payroll_timesheet/views/timesheet_views.xml deleted file mode 100644 index c7eeb3f4..00000000 --- a/hr_payroll_timesheet/views/timesheet_views.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - account.analytic.line.tree.hr_timesheet.inherit - account.analytic.line - - - - - - - - - - - account.analytic.line.form.inherit - account.analytic.line - - - - - - - - - -