From d0500405ebb11a14a77e4b7975b73c88a9ad9291 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 20 Mar 2019 12:26:36 +0100 Subject: [PATCH 1/8] [IMP] Fix amount calculation issues + code simplification --- hr_timesheet_sheet/README.rst | 10 +- hr_timesheet_sheet/__manifest__.py | 4 +- .../models/hr_timesheet_sheet.py | 277 +++++++----------- hr_timesheet_sheet/readme/DESCRIPTION.rst | 2 - hr_timesheet_sheet/readme/ROADMAP.rst | 6 +- .../tests/test_hr_timesheet_sheet.py | 156 +++++++--- .../views/hr_timesheet_sheet_views.xml | 3 +- 7 files changed, 232 insertions(+), 226 deletions(-) diff --git a/hr_timesheet_sheet/README.rst b/hr_timesheet_sheet/README.rst index 5e1766fea..c55648119 100644 --- a/hr_timesheet_sheet/README.rst +++ b/hr_timesheet_sheet/README.rst @@ -23,15 +23,13 @@ HR Timesheet Sheet :target: https://runbot.odoo-community.org/runbot/117/12.0 :alt: Try me on Runbot -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module supplies a new screen enabling you to manage your work encoding (timesheet) by period. Timesheet entries are made by employees each day. At the end of the defined period, employees validate their sheet and the manager must then approve his team's entries. Periods are defined in the company forms and you can set them to run monthly, weekly or daily. -Negative hours are not admitted. - **Table of contents** .. contents:: @@ -57,9 +55,9 @@ If you want other default ranges different from weekly, you need to go: Known issues / Roadmap ====================== -* When you open the `Summary` or `Details` tab, a save should be performed - to ensure the data shown is correct. This perhaps could be achieved by including - a .js file that does that. +* When you change values on the `Summary` tab, a save should be performed + to ensure the data shown on the `Details` tab is correct. This limitation could be + perhaps avoided by including a .js file that aligns the `Details` tab. * The timesheet grid is limited to display a max. of 1M cells, due to a limitation of the tree view limit parameter not being able to dynamically set a limit. Since default value of odoo, 40 records is too small, we decided diff --git a/hr_timesheet_sheet/__manifest__.py b/hr_timesheet_sheet/__manifest__.py index 387ea66a9..5a3589b11 100644 --- a/hr_timesheet_sheet/__manifest__.py +++ b/hr_timesheet_sheet/__manifest__.py @@ -1,16 +1,18 @@ # Copyright 2018 Eficent # Copyright 2018-2019 Brainbean Apps +# Copyright 2018-2019 Onestein () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'HR Timesheet Sheet', - 'version': '12.0.1.0.7', + 'version': '12.0.1.1.0', 'category': 'Human Resources', 'sequence': 80, 'summary': 'Timesheet Sheets, Activities', 'license': 'AGPL-3', 'author': ( 'Eficent, ' + 'Onestein, ' 'Odoo Community Association (OCA)' ), 'website': 'https://github.com/OCA/hr-timesheet', diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index fdd6c5207..15fb0c925 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -1,5 +1,6 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # Copyright 2018-2019 Brainbean Apps +# Copyright 2018-2019 Onestein () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import babel.dates @@ -132,18 +133,12 @@ def _default_employee(self): string='Select Project', help='If selected, the associated project is added ' 'to the timesheet sheet when clicked the button.', - states={ - 'draft': [('readonly', False)], - }, ) add_line_task_id = fields.Many2one( comodel_name='project.task', string='Select Task', help='If selected, the associated task is added ' 'to the timesheet sheet when clicked the button.', - states={ - 'draft': [('readonly', False)], - }, ) total_time = fields.Float( compute='_compute_total_time', @@ -165,7 +160,7 @@ def _check_start_end_dates(self): @api.constrains('date_start', 'date_end', 'employee_id') def _check_sheet_date(self, forced_user_id=False): for sheet in self: - new_user_id = forced_user_id or sheet.user_id and sheet.user_id.id + new_user_id = forced_user_id or sheet.user_id.id if new_user_id: self.env.cr.execute( """ @@ -229,8 +224,7 @@ def _check_company_id(self): if not rec.company_id: continue for field in rec.timesheet_ids: - if rec.company_id and field.company_id and \ - rec.company_id != field.company_id: + if field.company_id and rec.company_id != field.company_id: raise ValidationError(_( 'You cannot change the company, as this %s (%s) ' 'is assigned to %s (%s).' @@ -262,37 +256,51 @@ def _compute_line_ids(self): dates = sheet._get_dates() if not dates: continue - timesheets = sheet._get_timesheet_lines() - lines = self.env['hr_timesheet.sheet.line'] + data_matrix = {} + projects = sheet.timesheet_ids.mapped('project_id') for date in dates: - for project in timesheets.mapped('project_id'): - timesheet = timesheets.filtered( - lambda x: (x.project_id == project)) - lines |= sheet._collect_lines_from_timesheets( - project, - timesheet, - date - ) - sheet.line_ids = lines - - def _get_timesheet_lines(self): + for project in projects: + project_timesheets = sheet.timesheet_ids.filtered( + lambda x: x.project_id == project) + tasks = [project_timesheets.mapped('task_id')] + if not project_timesheets or not all( + [t.task_id for t in project_timesheets]): + tasks += [self.env['project.task']] + for task in tasks: + timesheets = project_timesheets.filtered( + lambda t: date == t.date + and t.task_id == task) + unit_amount = sum(t.unit_amount for t in timesheets) + data_matrix[(date, project, task)] = { + 'unit_amount': unit_amount, + 'timesheets': timesheets + } + sheet.line_ids = sheet._create_data_matrix_lines(data_matrix) + + def _create_data_matrix_lines(self, data_matrix): self.ensure_one() - if self.state == 'draft': - domain = self._get_timesheet_sheet_lines_domain() - timesheets = self.env['account.analytic.line'].search(domain) - else: - timesheets = self.timesheet_ids - return timesheets + lines = self.env['hr_timesheet.sheet.line'] + for item in data_matrix: + lines |= self.env['hr_timesheet.sheet.line'].create( + self._get_default_sheet_line( + date=item[0], + project=item[1], + task=item[2], + unit_amount=data_matrix[item]['unit_amount'] + )) + self.clean_timesheets(data_matrix[item]['timesheets']) + return lines - @api.onchange('date_start', 'date_end', 'timesheet_ids') - def _onchange_dates_or_timesheets(self): - self._compute_line_ids() + @api.onchange('date_start', 'date_end') + def _onchange_dates(self): + domain = self._get_timesheet_sheet_lines_domain() + timesheets = self.env['account.analytic.line'].search(domain) + self.link_timesheets_to_sheet(timesheets) + self.timesheet_ids = timesheets - @api.onchange('line_ids') - def _onchange_line_ids(self): - if self.state == 'draft' and not self.timesheet_ids and self.line_ids: - timesheets = self._get_timesheet_lines() - self.timesheet_ids = timesheets + @api.onchange('timesheet_ids') + def _onchange_timesheets(self): + self._compute_line_ids() @api.onchange('add_line_project_id') def onchange_add_project_id(self): @@ -378,18 +386,15 @@ def action_timesheet_draft(self): _('Only an HR Officer or Manager can refuse sheets ' 'or reset them to draft.')) self.write({'state': 'draft'}) - return True @api.multi def action_timesheet_confirm(self): for sheet in self: - if sheet.employee_id and sheet.employee_id.parent_id \ - and sheet.employee_id.parent_id.user_id: + if sheet.employee_id.parent_id.user_id: self.message_subscribe_users( user_ids=[sheet.employee_id.parent_id.user_id.id]) - sheet.reset_add_line() + self.reset_add_line() self.write({'state': 'confirm'}) - return True @api.multi def action_timesheet_done(self): @@ -410,13 +415,12 @@ def button_add_line(self): if rec.state == 'draft': rec.add_line() rec.reset_add_line() - return True - @api.multi def reset_add_line(self): - for sheet in self: - sheet.add_line_task_id = False - sheet.add_line_project_id = False + self.write({ + 'add_line_project_id': False, + 'add_line_task_id': False, + }) def _get_date_name(self, date): name = babel.dates.format_skeleton( @@ -453,49 +457,20 @@ def _get_new_line_name(self): self.add_line_task_id, ) - def _collect_lines_from_timesheets(self, project, timesheet, date): - tasks = [task for task in timesheet.mapped('task_id')] - if not timesheet or not all( - [t.task_id for t in timesheet]): - tasks += [self.env['project.task']] - - name_x = self._get_date_name(date) - lines = self.env['hr_timesheet.sheet.line'] - for task in tasks: - name_y = self._get_line_name(project, task) - values = { - 'value_x': name_x, - 'value_y': name_y, - 'date': date, - 'project_id': project.id, - 'task_id': task.id, - } - lines |= self.env['hr_timesheet.sheet.line'].create( - self._get_default_sheet_line( - values=values, - timesheets=timesheet.filtered( - lambda t: date == t.date - and t.task_id.id == task.id), - ) - ) - - return lines - - def _get_default_sheet_line(self, values, timesheets=None): - timesheets = self.clean_timesheets(timesheets) - values.update({ - 'count_timesheets': len(timesheets), - 'unit_amount': 0.0, - }) + def _get_default_sheet_line(self, date, project, task, unit_amount): + name_y = self._get_line_name(project, task) + values = { + 'value_x': self._get_date_name(date), + 'value_y': name_y, + 'date': date, + 'project_id': project.id, + 'task_id': task.id, + 'unit_amount': unit_amount, + } if self.id: values.update({ 'sheet_id': self.id, }) - if timesheets: - unit_amount = sum([t.unit_amount for t in timesheets]) - values.update({ - 'unit_amount': unit_amount, - }) return values @api.model @@ -521,10 +496,13 @@ def add_line(self): self.timesheet_ids |= \ self.env['account.analytic.line'].create(values) - def clean_timesheets(self, timesheets): + def link_timesheets_to_sheet(self, timesheets): + self.ensure_one() if self.id and self.state == 'draft': for aal in timesheets.filtered(lambda a: not a.sheet_id): aal.write({'sheet_id': self.id}) + + def clean_timesheets(self, timesheets): repeated = timesheets.filtered(lambda t: t.name == empty_name) if len(repeated) > 1 and self.id: return repeated.merge_timesheets() @@ -534,15 +512,10 @@ def delete_empty_lines(self, delete_empty_rows=False): for name in self.line_ids.mapped('value_y'): row = self.line_ids.filtered(lambda l: l.value_y == name) if row: - ts_row = self.env['account.analytic.line'].search([ - ('project_id', '=', row[0].project_id.id), - ('task_id', '=', row[0].task_id.id), - ('date', '<=', self.date_end), - ('date', '>=', self.date_start), - ('employee_id', '=', self.employee_id.id), - ('sheet_id', '=', self.id), - ('company_id', '=', self.company_id.id), - ]) + ts_row = self.timesheet_ids.filtered( + lambda x: x.project_id.id == row[0].project_id.id + and x.task_id.id == row[0].task_id.id + ) if delete_empty_rows and self.add_line_project_id: check = any([l.unit_amount for l in row]) else: @@ -596,9 +569,6 @@ class SheetLine(models.TransientModel): string="Quantity", default=0.0, ) - count_timesheets = fields.Integer( - default=0, - ) @api.onchange('unit_amount') def onchange_unit_amount(self): @@ -607,97 +577,46 @@ def onchange_unit_amount(self): If yes, it does several comparisons to see if the unit_amount of the timesheets should be updated accordingly.""" self.ensure_one() - if self.unit_amount < 0.0: - self.write({'unit_amount': 0.0}) - if self.unit_amount and not self.count_timesheets: - self._create_timesheet(self.unit_amount) - elif self.count_timesheets: - timesheets = self._find_timesheets() - if len(timesheets) != self.count_timesheets: - _logger.info('Found timesheets %s, expected %s', - len(timesheets), self.count_timesheets) - self.count_timesheets = len(timesheets) - if not self.unit_amount: - new_ts = timesheets.filtered(lambda t: t.name == empty_name) - other_ts = timesheets.filtered(lambda t: t.name != empty_name) - if new_ts: - new_ts.unlink() - for timesheet in other_ts: - timesheet.write({'unit_amount': 0.0}) - self.count_timesheets = len(other_ts) - else: - if self.count_timesheets == 1: - timesheets.write({'unit_amount': self.unit_amount}) - elif self.count_timesheets > 1: - amount = sum([t.unit_amount for t in timesheets]) - new_ts = timesheets.filtered( - lambda t: t.name == empty_name) - other_ts = timesheets.filtered( - lambda t: t.name != empty_name) - diff_amount = self.unit_amount - amount - if new_ts: - if len(new_ts) > 1: - new_ts = new_ts.merge_timesheets() - self.count_timesheets = len( - self.sheet_id.timesheet_ids) - if new_ts.unit_amount + diff_amount >= 0.0: - if diff_amount != 0.0: - new_ts.unit_amount += diff_amount - if not new_ts.unit_amount: - new_ts.unlink() - self.count_timesheets -= 1 - else: - diff_amount += new_ts.unit_amount - new_ts.write({'unit_amount': 0.0}) - new_ts.unlink() - self.count_timesheets -= 1 - self._diff_amount_timesheets(diff_amount, other_ts) - else: - if diff_amount > 0.0: - self._create_timesheet(diff_amount) - else: - self._diff_amount_timesheets(diff_amount, other_ts) - else: - raise ValidationError( - _('Error code: Cannot have 0 timesheets.')) - - def _create_timesheet(self, amount): - values = self._line_to_timesheet(amount) - if self.env['account.analytic.line'].create(values): - self.count_timesheets += 1 - @api.model - def _diff_amount_timesheets(self, diff_amount, timesheets): - for timesheet in timesheets: - if timesheet.unit_amount + diff_amount >= 0.0: - if diff_amount != 0.0: - timesheet.unit_amount += diff_amount - break - else: - diff_amount += timesheet.unit_amount - timesheet.write({'unit_amount': 0.0}) + sheet = self.sheet_id + if not sheet: + model = self.env.context.get('params', {}).get('model', '') + obj_id = self.env.context.get('params', {}).get('id') + if model == 'hr_timesheet.sheet' and isinstance(obj_id, int): + sheet = self.env['hr_timesheet.sheet'].browse(obj_id) + if not sheet: + return {'warning': { + 'title': _("Warning"), + 'message': _("Save the Timesheet Sheet first.") + }} + timesheets = sheet.timesheet_ids.filtered( + lambda t: t.date == self.date + and t.project_id.id == self.project_id.id + and t.task_id.id == self.task_id.id + ) + new_ts = timesheets.filtered(lambda t: t.name == empty_name) + amount = sum(t.unit_amount for t in timesheets) + diff_amount = self.unit_amount - amount + if not diff_amount: + return + if new_ts: + if len(new_ts) > 1: + new_ts = new_ts.merge_timesheets() + unit_amount = new_ts.unit_amount + diff_amount + new_ts.write({'unit_amount': unit_amount}) + else: + new_ts_values = self._line_to_timesheet(diff_amount) + self.env['account.analytic.line'].create(new_ts_values) @api.model def _line_to_timesheet(self, amount): - task = self.task_id.id if self.task_id else False return { 'name': empty_name, 'employee_id': self.sheet_id.employee_id.id, 'date': self.date, 'project_id': self.project_id.id, - 'task_id': task, + 'task_id': self.task_id.id, 'sheet_id': self.sheet_id.id, 'unit_amount': amount, 'company_id': self.sheet_id.company_id.id, } - - @api.model - def _find_timesheets(self): - return self.env['account.analytic.line'].search([ - ('project_id', '=', self.project_id.id), - ('task_id', '=', self.task_id.id), - ('date', '=', self.date), - ('employee_id', '=', self.sheet_id.employee_id.id), - ('sheet_id', '=', self.sheet_id.id), - ('company_id', '=', self.sheet_id.company_id.id), - ]) diff --git a/hr_timesheet_sheet/readme/DESCRIPTION.rst b/hr_timesheet_sheet/readme/DESCRIPTION.rst index dc37e94bc..24e618c36 100644 --- a/hr_timesheet_sheet/readme/DESCRIPTION.rst +++ b/hr_timesheet_sheet/readme/DESCRIPTION.rst @@ -2,5 +2,3 @@ This module supplies a new screen enabling you to manage your work encoding (tim Timesheet entries are made by employees each day. At the end of the defined period, employees validate their sheet and the manager must then approve his team's entries. Periods are defined in the company forms and you can set them to run monthly, weekly or daily. - -Negative hours are not admitted. diff --git a/hr_timesheet_sheet/readme/ROADMAP.rst b/hr_timesheet_sheet/readme/ROADMAP.rst index 6859f85a1..52ccb8dc7 100644 --- a/hr_timesheet_sheet/readme/ROADMAP.rst +++ b/hr_timesheet_sheet/readme/ROADMAP.rst @@ -1,6 +1,6 @@ -* When you open the `Summary` or `Details` tab, a save should be performed - to ensure the data shown is correct. This perhaps could be achieved by including - a .js file that does that. +* When you change values on the `Summary` tab, a save should be performed + to ensure the data shown on the `Details` tab is correct. This limitation could be + perhaps avoided by including a .js file that aligns the `Details` tab. * The timesheet grid is limited to display a max. of 1M cells, due to a limitation of the tree view limit parameter not being able to dynamically set a limit. Since default value of odoo, 40 records is too small, we decided diff --git a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py index 39eeb9596..cf848fb0b 100644 --- a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py @@ -1,5 +1,6 @@ # Copyright 2018 Eficent Business and IT Consulting Services, S.L. # Copyright 2018 Brainbean Apps +# Copyright 2018-2019 Onestein () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from dateutil.relativedelta import relativedelta @@ -104,12 +105,12 @@ def test_1(self): sheet.add_line_project_id = self.project_1 sheet.onchange_add_project_id() sheet.sudo(self.user).button_add_line() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 1) self.assertEqual(len(sheet.line_ids), 7) sheet.date_end = sheet.date_end + relativedelta(days=1) - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 0) self.assertEqual(len(sheet.line_ids), 0) @@ -130,7 +131,7 @@ def test_2(self): sheet.add_line_project_id = self.project_1 sheet.onchange_add_project_id() sheet.sudo(self.user).button_add_line() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() sheet.onchange_add_project_id() self.assertEqual(sheet.add_line_project_id.id, False) self.assertEqual(len(sheet.line_ids), 7) @@ -139,19 +140,17 @@ def test_2(self): line = sheet.line_ids.filtered(lambda l: l.date != timesheet.date)[0] self.assertEqual(line.unit_amount, 0.0) - self.assertEqual(line.count_timesheets, 0) line._cache.update( line._convert_to_cache( {'unit_amount': 1.0}, update=True)) line.onchange_unit_amount() self.assertEqual(line.unit_amount, 1.0) - self.assertEqual(line.count_timesheets, 1) self.assertEqual(len(sheet.timesheet_ids), 2) sheet.add_line_project_id = self.project_2 sheet.onchange_add_project_id() sheet.sudo(self.user).button_add_line() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 2) self.assertNotIn(timesheet.id, sheet.timesheet_ids.ids) self.assertEqual(len(sheet.line_ids), 14) @@ -196,12 +195,12 @@ def test_3(self): 'date_end': self.sheet_model._default_date_end(), 'state': 'draft', }) - sheet._onchange_dates_or_timesheets() + sheet._onchange_dates() self.assertEqual(len(sheet.line_ids), 7) - self.assertEqual(len(sheet.timesheet_ids), 0) + self.assertEqual(len(sheet.timesheet_ids), 1) self.assertTrue(self.aal_model.search([('id', '=', timesheet.id)])) - sheet._onchange_line_ids() + sheet._onchange_timesheets() self.assertEqual(len(sheet.line_ids), 7) self.assertEqual(len(sheet.timesheet_ids), 1) @@ -237,6 +236,8 @@ def test_4(self): 'employee_id': self.employee.id, 'company_id': self.user.company_id.id, }) + sheet._onchange_dates() + sheet._onchange_timesheets() self.assertEqual(len(sheet.line_ids), 7) self.assertEqual(len(sheet.timesheet_ids), 2) @@ -247,11 +248,10 @@ def test_4(self): self.assertEqual(timesheet_3.unit_amount, 0.0) line = sheet.line_ids.filtered(lambda l: l.unit_amount != 0.0) - self.assertEqual(line.count_timesheets, 1) self.assertEqual(line.unit_amount, 1.0) line.unit_amount = 0.0 line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 1) self.assertFalse(self.aal_model.search( [('id', '=', timesheet_1_or_2.id)])) @@ -261,7 +261,7 @@ def test_4(self): sheet.onchange_add_project_id() sheet.add_line_task_id = self.task_2 sheet.sudo(self.user).button_add_line() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 1) self.assertEqual(len(sheet.line_ids), 7) self.assertFalse(self.aal_model.search( @@ -284,10 +284,11 @@ def test_5(self): 'employee_id': self.employee.id, 'company_id': self.user.company_id.id, }) + sheet._onchange_dates() + sheet._onchange_timesheets() self.assertEqual(len(sheet.line_ids), 7) self.assertEqual(len(sheet.timesheet_ids), 2) line = sheet.line_ids.filtered(lambda l: l.unit_amount != 0.0) - self.assertEqual(line.count_timesheets, 2) self.assertEqual(line.unit_amount, 4.0) timesheet_2.name = '/' @@ -295,7 +296,7 @@ def test_5(self): line._convert_to_cache( {'unit_amount': 3.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 1) self.assertEqual(sheet.timesheet_ids[0].unit_amount, 3.0) @@ -308,9 +309,8 @@ def test_5(self): line._convert_to_cache( {'unit_amount': 4.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 1) - self.assertEqual(line.count_timesheets, 1) self.assertEqual(sheet.timesheet_ids[0].unit_amount, 4.0) self.assertEqual(timesheet_1_or_2.unit_amount, 4.0) @@ -318,9 +318,9 @@ def test_5(self): line._convert_to_cache( {'unit_amount': -1.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() - self.assertEqual(len(sheet.line_ids), 0) - self.assertEqual(len(sheet.timesheet_ids), 0) + sheet._onchange_timesheets() + self.assertEqual(len(sheet.line_ids), 7) + self.assertEqual(len(sheet.timesheet_ids), 1) def test_6(self): timesheet_1 = self.aal_model.create({ @@ -357,10 +357,11 @@ def test_6(self): 'employee_id': self.employee.id, 'company_id': self.user.company_id.id, }) + sheet._onchange_dates() + sheet._onchange_timesheets() self.assertEqual(len(sheet.line_ids), 7) self.assertEqual(len(sheet.timesheet_ids), 5) line = sheet.line_ids.filtered(lambda l: l.unit_amount != 0.0) - self.assertEqual(line.count_timesheets, 5) self.assertEqual(line.unit_amount, 10.0) timesheet_2.name = '/' @@ -368,9 +369,8 @@ def test_6(self): line._convert_to_cache( {'unit_amount': 6.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 3) - self.assertEqual(line.count_timesheets, 3) timesheet_1_or_2 = self.aal_model.search( [('id', 'in', [timesheet_1.id, timesheet_2.id])]) @@ -380,9 +380,9 @@ def test_6(self): line._convert_to_cache( {'unit_amount': 3.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() - self.assertEqual(len(sheet.timesheet_ids), 3) - self.assertEqual(line.count_timesheets, 3) + sheet._onchange_timesheets() + self.assertEqual(len(sheet.timesheet_ids), 4) + self.assertEqual(line.unit_amount, 3.0) timesheet_3_4_and_5 = self.aal_model.search( [('id', 'in', [timesheet_3.id, timesheet_4.id, timesheet_5.id])]) @@ -394,20 +394,19 @@ def test_6(self): 'employee_id': self.employee.id, 'unit_amount': 2.0, }) - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.timesheet_ids), 4) line = sheet.line_ids.filtered(lambda l: l.unit_amount != 0.0) - self.assertEqual(line.count_timesheets, 4) + self.assertEqual(len(line), 1) self.assertEqual(line.unit_amount, 5.0) line._cache.update( line._convert_to_cache( {'unit_amount': 1.0}, update=True)) line.onchange_unit_amount() - sheet._onchange_dates_or_timesheets() - self.assertEqual(len(sheet.timesheet_ids), 3) - self.assertEqual(line.count_timesheets, 3) - self.assertFalse(self.aal_model.search([('id', '=', timesheet_6.id)])) + sheet._onchange_timesheets() + self.assertEqual(len(sheet.timesheet_ids), 4) + self.assertTrue(self.aal_model.search([('id', '=', timesheet_6.id)])) def test_7(self): sheet = self.sheet_model.sudo(self.user).new({ @@ -417,7 +416,7 @@ def test_7(self): 'date_end': self.sheet_model._default_date_start(), 'state': 'draft', }) - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() self.assertEqual(len(sheet.line_ids), 0) self.assertEqual(len(sheet.timesheet_ids), 0) with self.assertRaises(ValidationError): @@ -483,7 +482,7 @@ def test_9(self): sheet.add_line_project_id = self.project_1 sheet.onchange_add_project_id() sheet.sudo(self.user).button_add_line() - sheet._onchange_dates_or_timesheets() + sheet._onchange_timesheets() sheet.onchange_add_project_id() self.assertEqual(len(sheet.timesheet_ids), 1) @@ -513,3 +512,94 @@ def test_10_start_day(self): "Sunday") self.assertEqual(weekday_to, 5, "The timesheet should end on Saturday") + + def test_11_onchange_unit_amount(self): + """Test onchange unit_amount for line without sheet_id.""" + self.aal_model.create({ + 'name': 'test1', + 'project_id': self.project_1.id, + 'employee_id': self.employee.id, + 'unit_amount': 2.0, + 'date': self.sheet_model._default_date_start(), + }) + self.aal_model.create({ + 'name': 'test2', + 'project_id': self.project_1.id, + 'employee_id': self.employee.id, + 'unit_amount': 2.0, + 'date': self.sheet_model._default_date_start(), + }) + sheet = self.sheet_model.sudo(self.user).create({ + 'employee_id': self.employee.id, + 'company_id': self.user.company_id.id, + 'department_id': self.department.id, + 'date_start': self.sheet_model._default_date_start(), + 'date_end': self.sheet_model._default_date_end(), + 'state': 'draft', + }) + sheet._onchange_dates() + sheet._onchange_timesheets() + self.assertEqual(len(sheet.timesheet_ids), 2) + self.assertEqual(len(sheet.line_ids), 7) + + for line in sheet.line_ids: + if line.unit_amount: + line.sheet_id = False + unit_amount = line.unit_amount + line.write({'unit_amount': unit_amount + 1.0}) + res_onchange = line.with_context( + params={'model': 'hr_timesheet.sheet', 'id': sheet.id} + ).onchange_unit_amount() + self.assertFalse(res_onchange) + self.assertEqual(line.unit_amount, unit_amount + 1.0) + + sheet._onchange_dates() + self.assertEqual(len(sheet.timesheet_ids), 3) + self.assertEqual(len(sheet.line_ids), 7) + + new_timesheet = sheet.timesheet_ids.filtered(lambda t: t.name == '/') + self.assertEqual(len(new_timesheet), 1) + self.assertEqual(new_timesheet.unit_amount, 1.0) + + for line in sheet.line_ids: + if line.unit_amount: + line.sheet_id = False + unit_amount = line.unit_amount + line.write({'unit_amount': unit_amount + 1.0}) + res_onchange = line.onchange_unit_amount() + warning = res_onchange.get('warning') + self.assertTrue(warning) + message = warning.get('message') + self.assertTrue(message) + + def test_12_creating_sheet(self): + """Test onchange unit_amount for line without sheet_id.""" + self.aal_model.create({ + 'name': 'test1', + 'project_id': self.project_1.id, + 'employee_id': self.employee.id, + 'unit_amount': 2.0, + 'date': self.sheet_model._default_date_start(), + }) + sheet = self.sheet_model.sudo(self.user).create({ + 'employee_id': self.employee.id, + 'company_id': self.user.company_id.id, + 'department_id': self.department.id, + 'date_start': self.sheet_model._default_date_start(), + 'date_end': self.sheet_model._default_date_end(), + }) + sheet._onchange_dates() + sheet._onchange_timesheets() + self.assertEqual(len(sheet.timesheet_ids), 1) + self.assertEqual(len(sheet.line_ids), 7) + + line = sheet.line_ids.filtered(lambda l: l.unit_amount) + self.assertEqual(len(line), 1) + self.assertEqual(line.unit_amount, 2.0) + + unit_amount = line.unit_amount + line.write({'unit_amount': unit_amount}) + line.onchange_unit_amount() + self.assertEqual(line.unit_amount, 2.0) + self.assertEqual(len(sheet.timesheet_ids), 1) + self.assertEqual(len(sheet.line_ids), 7) diff --git a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml index 814ba00c1..8c81beb4b 100644 --- a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml +++ b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml @@ -69,7 +69,6 @@ - @@ -85,7 +84,7 @@ - + From c4466861e8e09475e5863f57d5d1a4388361a020 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 20 Mar 2019 12:31:15 +0100 Subject: [PATCH 2/8] [FIX] Fix employee_id related stuff --- .../models/account_analytic_line.py | 4 +-- hr_timesheet_sheet/models/hr_employee.py | 5 ++-- .../models/hr_timesheet_sheet.py | 26 ++++++++++++------- .../tests/test_hr_timesheet_sheet.py | 2 +- .../views/hr_timesheet_sheet_views.xml | 4 +-- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/hr_timesheet_sheet/models/account_analytic_line.py b/hr_timesheet_sheet/models/account_analytic_line.py index 979546df7..7d52f459f 100644 --- a/hr_timesheet_sheet/models/account_analytic_line.py +++ b/hr_timesheet_sheet/models/account_analytic_line.py @@ -24,7 +24,7 @@ def _compute_sheet(self): ('date_start', '<=', timesheet.date), ('employee_id', '=', timesheet.employee_id.id), ('company_id', 'in', [timesheet.company_id.id, False]), - ('state', '=', 'draft'), + ('state', 'in', ['new', 'draft']), ], limit=1) if timesheet.sheet_id != sheet: timesheet.sheet_id = sheet @@ -81,7 +81,7 @@ def _check_state(self): if self.env.context.get('skip_check_state'): return for line in self: - if line.sheet_id and line.sheet_id.state != 'draft': + if line.sheet_id and line.sheet_id.state not in ['new', 'draft']: raise UserError( _('You cannot modify an entry in a confirmed ' 'timesheet sheet.')) diff --git a/hr_timesheet_sheet/models/hr_employee.py b/hr_timesheet_sheet/models/hr_employee.py index fccc10282..5ba77c32d 100644 --- a/hr_timesheet_sheet/models/hr_employee.py +++ b/hr_timesheet_sheet/models/hr_employee.py @@ -16,9 +16,10 @@ class HrEmployee(models.Model): @api.multi def _compute_timesheet_count(self): + Sheet = self.env['hr_timesheet.sheet'] for employee in self: - employee.timesheet_count = employee.env['hr_timesheet.sheet'].\ - search_count([('employee_id', '=', employee.id)]) + employee.timesheet_count = Sheet.search_count([ + ('employee_id', '=', employee.id)]) @api.constrains('company_id') def _check_company_id(self): diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index 15fb0c925..ef5a6ce56 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -57,9 +57,11 @@ def _default_date_end(self): return today def _default_employee(self): - emp_ids = self.env['hr.employee'].search( - [('user_id', '=', self.env.uid)]) - return emp_ids and emp_ids[0] or False + company = self.env['res.company']._company_default_get() + return self.env['hr.employee'].search([ + ('user_id', '=', self.env.uid), + ('company_id', '=', company.id), + ], limit=1) name = fields.Char( string="Note", @@ -70,6 +72,8 @@ def _default_employee(self): string='Employee', default=lambda self: self._default_employee(), required=True, + readonly=True, + states={'new': [('readonly', False)]}, ) user_id = fields.Many2one( comodel_name='res.users', @@ -84,7 +88,7 @@ def _default_employee(self): required=True, index=True, readonly=True, - states={'draft': [('readonly', False)]}, + states={'new': [('readonly', False)]}, ) date_end = fields.Date( string='Date To', @@ -92,7 +96,7 @@ def _default_employee(self): required=True, index=True, readonly=True, - states={'draft': [('readonly', False)]}, + states={'new': [('readonly', False)]}, ) timesheet_ids = fields.One2many( comodel_name='account.analytic.line', @@ -100,6 +104,7 @@ def _default_employee(self): string='Timesheets', readonly=True, states={ + 'new': [('readonly', False)], 'draft': [('readonly', False)], } ) @@ -109,14 +114,16 @@ def _default_employee(self): string='Timesheet Sheet Lines', readonly=True, states={ + 'new': [('readonly', False)], 'draft': [('readonly', False)], } ) state = fields.Selection([ + ('new', 'New'), ('draft', 'Open'), ('confirm', 'Waiting Approval'), ('done', 'Approved')], - default='draft', track_visibility='onchange', + default='new', track_visibility='onchange', string='Status', required=True, readonly=True, index=True, ) company_id = fields.Many2one( @@ -235,7 +242,6 @@ def _check_company_id(self): def _onchange_employee_id(self): if self.employee_id: self.department_id = self.employee_id.department_id - self.user_id = self.employee_id.user_id def _get_timesheet_sheet_lines_domain(self): self.ensure_one() @@ -291,7 +297,7 @@ def _create_data_matrix_lines(self, data_matrix): self.clean_timesheets(data_matrix[item]['timesheets']) return lines - @api.onchange('date_start', 'date_end') + @api.onchange('date_start', 'date_end', 'employee_id') def _onchange_dates(self): domain = self._get_timesheet_sheet_lines_domain() timesheets = self.env['account.analytic.line'].search(domain) @@ -412,7 +418,7 @@ def action_timesheet_refuse(self): @api.multi def button_add_line(self): for rec in self: - if rec.state == 'draft': + if rec.state in ['new', 'draft']: rec.add_line() rec.reset_add_line() @@ -498,7 +504,7 @@ def add_line(self): def link_timesheets_to_sheet(self, timesheets): self.ensure_one() - if self.id and self.state == 'draft': + if self.id and self.state in ['new', 'draft']: for aal in timesheets.filtered(lambda a: not a.sheet_id): aal.write({'sheet_id': self.id}) diff --git a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py index cf848fb0b..2a5128e77 100644 --- a/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/tests/test_hr_timesheet_sheet.py @@ -96,11 +96,11 @@ def setUp(self): def test_1(self): sheet = self.sheet_model.sudo(self.user).create({ - 'employee_id': self.employee.id, 'company_id': self.user.company_id.id, }) self.assertEqual(len(sheet.timesheet_ids), 0) self.assertEqual(len(sheet.line_ids), 0) + self.assertTrue(sheet.employee_id) sheet.add_line_project_id = self.project_1 sheet.onchange_add_project_id() diff --git a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml index 8c81beb4b..e4efa41c2 100644 --- a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml +++ b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml @@ -51,7 +51,7 @@ - - + From 43ac91d8a5b394c125096a57eb356c41c5b9b637 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 21 Mar 2019 09:42:26 +0100 Subject: [PATCH 3/8] [IMP] Ease customizations of message_subscribe_users --- hr_timesheet_sheet/models/hr_timesheet_sheet.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index ef5a6ce56..60a71abcb 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -385,6 +385,12 @@ def unlink(self): analytic_timesheet_toremove.unlink() return super().unlink() + def _timesheet_subscribe_users(self): + for sheet in self: + if sheet.employee_id.parent_id.user_id: + self.message_subscribe_users( + user_ids=[sheet.employee_id.parent_id.user_id.id]) + @api.multi def action_timesheet_draft(self): if not self.env.user.has_group('hr_timesheet.group_hr_timesheet_user'): @@ -395,10 +401,7 @@ def action_timesheet_draft(self): @api.multi def action_timesheet_confirm(self): - for sheet in self: - if sheet.employee_id.parent_id.user_id: - self.message_subscribe_users( - user_ids=[sheet.employee_id.parent_id.user_id.id]) + self._timesheet_subscribe_users() self.reset_add_line() self.write({'state': 'confirm'}) From 433b28fc0b39313396f80f423efe3f2a13c086df Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 21 Mar 2019 09:52:36 +0100 Subject: [PATCH 4/8] [IMP] List view easier to read --- hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml index e4efa41c2..d396a3e3b 100644 --- a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml +++ b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml @@ -10,6 +10,7 @@ + From 8829878f100b1cd1a98be7b256a01c9f15be7c39 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 21 Mar 2019 11:47:33 +0100 Subject: [PATCH 5/8] [IMP] Extra code simplification --- .../models/hr_timesheet_sheet.py | 82 ++++++++----------- 1 file changed, 33 insertions(+), 49 deletions(-) diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index 60a71abcb..1fd151adf 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -245,57 +245,44 @@ def _onchange_employee_id(self): def _get_timesheet_sheet_lines_domain(self): self.ensure_one() - domain = [ + return [ ('project_id', '!=', False), ('date', '<=', self.date_end), ('date', '>=', self.date_start), ('employee_id', '=', self.employee_id.id), ('company_id', '=', self.company_id.id), ] - return domain @api.multi def _compute_line_ids(self): for sheet in self: if not all([sheet.date_start, sheet.date_end]): continue - dates = sheet._get_dates() - if not dates: - continue - data_matrix = {} - projects = sheet.timesheet_ids.mapped('project_id') - for date in dates: - for project in projects: - project_timesheets = sheet.timesheet_ids.filtered( - lambda x: x.project_id == project) - tasks = [project_timesheets.mapped('task_id')] - if not project_timesheets or not all( - [t.task_id for t in project_timesheets]): - tasks += [self.env['project.task']] - for task in tasks: - timesheets = project_timesheets.filtered( - lambda t: date == t.date - and t.task_id == task) - unit_amount = sum(t.unit_amount for t in timesheets) - data_matrix[(date, project, task)] = { - 'unit_amount': unit_amount, - 'timesheets': timesheets - } - sheet.line_ids = sheet._create_data_matrix_lines(data_matrix) - - def _create_data_matrix_lines(self, data_matrix): + matrix = sheet._get_data_matrix() + lines = self.env['hr_timesheet.sheet.line'] + for item in sorted(matrix, key=lambda l: self._sort_matrix(l)): + vals = sheet._get_default_sheet_line(matrix, item) + lines |= self.env['hr_timesheet.sheet.line'].create(vals) + sheet.clean_timesheets(matrix[item]) + sheet.line_ids = lines + + def _sort_matrix(self, line): + return [line[0], line[1].name, line[2].name or ''] + + def _get_data_matrix(self): self.ensure_one() - lines = self.env['hr_timesheet.sheet.line'] - for item in data_matrix: - lines |= self.env['hr_timesheet.sheet.line'].create( - self._get_default_sheet_line( - date=item[0], - project=item[1], - task=item[2], - unit_amount=data_matrix[item]['unit_amount'] - )) - self.clean_timesheets(data_matrix[item]['timesheets']) - return lines + matrix = {} + empty_line = self.env['account.analytic.line'] + for line in self.timesheet_ids: + data_key = (line.date, line.project_id, line.task_id) + if data_key not in matrix: + matrix[data_key] = empty_line + matrix[data_key] += line + for date in self._get_dates(): + for item in matrix.copy(): + if (date, item[1], item[2]) not in matrix: + matrix[(date, item[1], item[2])] = empty_line + return matrix @api.onchange('date_start', 'date_end', 'employee_id') def _onchange_dates(self): @@ -466,20 +453,17 @@ def _get_new_line_name(self): self.add_line_task_id, ) - def _get_default_sheet_line(self, date, project, task, unit_amount): - name_y = self._get_line_name(project, task) + def _get_default_sheet_line(self, matrix, item): values = { - 'value_x': self._get_date_name(date), - 'value_y': name_y, - 'date': date, - 'project_id': project.id, - 'task_id': task.id, - 'unit_amount': unit_amount, + 'value_x': self._get_date_name(item[0]), + 'value_y': self._get_line_name(item[1], item[2]), + 'date': item[0], + 'project_id': item[1].id, + 'task_id': item[2].id, + 'unit_amount': sum(t.unit_amount for t in matrix[item]), } if self.id: - values.update({ - 'sheet_id': self.id, - }) + values.update({'sheet_id': self.id}) return values @api.model From d56b8e1b24b77940d1f1b2f5bc0593f121608e51 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 22 Mar 2019 09:16:59 +0100 Subject: [PATCH 6/8] [IMP] Make use of batch create --- hr_timesheet_sheet/models/hr_timesheet_sheet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index 1fd151adf..a4f87c6d9 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -259,11 +259,11 @@ def _compute_line_ids(self): if not all([sheet.date_start, sheet.date_end]): continue matrix = sheet._get_data_matrix() - lines = self.env['hr_timesheet.sheet.line'] + vals_list = [] for item in sorted(matrix, key=lambda l: self._sort_matrix(l)): - vals = sheet._get_default_sheet_line(matrix, item) - lines |= self.env['hr_timesheet.sheet.line'].create(vals) + vals_list.append(sheet._get_default_sheet_line(matrix, item)) sheet.clean_timesheets(matrix[item]) + lines = self.env['hr_timesheet.sheet.line'].create(vals_list) sheet.line_ids = lines def _sort_matrix(self, line): From 6b4c206fba5bb723a17c7d247bf737bbd9ff0fad Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 22 Mar 2019 10:00:50 +0100 Subject: [PATCH 7/8] [FIX] Update company when onchange employee_id --- hr_timesheet_sheet/models/hr_timesheet_sheet.py | 8 ++++++-- hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index a4f87c6d9..bf2ab1835 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -130,6 +130,7 @@ def _default_employee(self): comodel_name='res.company', string='Company', default=lambda self: self.env['res.company']._company_default_get(), + readonly=True, ) department_id = fields.Many2one( comodel_name='hr.department', @@ -242,6 +243,7 @@ def _check_company_id(self): def _onchange_employee_id(self): if self.employee_id: self.department_id = self.employee_id.department_id + self.company_id = self.employee_id.company_id def _get_timesheet_sheet_lines_domain(self): self.ensure_one() @@ -250,7 +252,7 @@ def _get_timesheet_sheet_lines_domain(self): ('date', '<=', self.date_end), ('date', '>=', self.date_start), ('employee_id', '=', self.employee_id.id), - ('company_id', '=', self.company_id.id), + ('company_id', '=', self.employee_id.company_id.id), ] @api.multi @@ -324,10 +326,12 @@ def copy(self, default=None): @api.model def create(self, vals): if 'employee_id' in vals: - if not self.env['hr.employee'].browse(vals['employee_id']).user_id: + employee = self.env['hr.employee'].browse(vals['employee_id']) + if not employee.user_id: raise UserError( _('In order to create a sheet for this employee, ' 'you must link him/her to an user.')) + vals['company_id'] = employee.company_id.id res = super().create(vals) res.write({'state': 'draft'}) self.delete_empty_lines(True) diff --git a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml index d396a3e3b..1cb4af23f 100644 --- a/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml +++ b/hr_timesheet_sheet/views/hr_timesheet_sheet_views.xml @@ -46,7 +46,7 @@
to
- +
From 17e454e535065487d3c951abfbd4aaaee5501afd Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 25 Mar 2019 09:24:57 +0100 Subject: [PATCH 8/8] [IMP] Code review --- hr_timesheet_sheet/models/hr_timesheet_sheet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hr_timesheet_sheet/models/hr_timesheet_sheet.py b/hr_timesheet_sheet/models/hr_timesheet_sheet.py index bf2ab1835..8e5fb04fa 100644 --- a/hr_timesheet_sheet/models/hr_timesheet_sheet.py +++ b/hr_timesheet_sheet/models/hr_timesheet_sheet.py @@ -257,6 +257,7 @@ def _get_timesheet_sheet_lines_domain(self): @api.multi def _compute_line_ids(self): + SheetLine = self.env['hr_timesheet.sheet.line'] for sheet in self: if not all([sheet.date_start, sheet.date_end]): continue @@ -265,8 +266,7 @@ def _compute_line_ids(self): for item in sorted(matrix, key=lambda l: self._sort_matrix(l)): vals_list.append(sheet._get_default_sheet_line(matrix, item)) sheet.clean_timesheets(matrix[item]) - lines = self.env['hr_timesheet.sheet.line'].create(vals_list) - sheet.line_ids = lines + sheet.line_ids = SheetLine.create(vals_list) def _sort_matrix(self, line): return [line[0], line[1].name, line[2].name or '']