From 299a61ecbcdb25bdd0dc17fa1f4ed5fc68d96e26 Mon Sep 17 00:00:00 2001 From: Geoffroy Larue Date: Thu, 9 May 2019 14:21:02 +0000 Subject: [PATCH 1/5] [IMP] hr_timesheet: remove useless field Remove the field company_uom_id as it is not used anymore. Task-1975022 --- addons/hr_timesheet/models/analytic_account.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/hr_timesheet/models/analytic_account.py b/addons/hr_timesheet/models/analytic_account.py index 574e73962d9..f61059058be 100644 --- a/addons/hr_timesheet/models/analytic_account.py +++ b/addons/hr_timesheet/models/analytic_account.py @@ -9,7 +9,6 @@ class AccountAnalyticAccount(models.Model): _inherit = 'account.analytic.account' _description = 'Analytic Account' - company_uom_id = fields.Many2one('uom.uom', related='company_id.project_time_mode_id', string="Company UOM", readonly=False) project_ids = fields.One2many('project.project', 'analytic_account_id', string='Projects') project_count = fields.Integer("Project Count", compute='_compute_project_count') From db92ca5fce6477dc9f65e904193651403b98b940 Mon Sep 17 00:00:00 2001 From: jem-odoo Date: Wed, 19 Dec 2018 09:04:53 +0000 Subject: [PATCH 2/5] [IMP] project,hr_timesheet: move analytic account business to project When we remove the inheritS between project and analytic account, we move the analytic_accound_id field in timesheet because it was the only use case for a project to be linked to an analytic account. This commit prepares new cost origin for a project (other that timesheet). Register costs on project will required an analytic account to keep analytic costs tracking. The analytic account management is now moved to project, like it was in 10.0, but without the inheritS. Task-1911581 --- addons/hr_timesheet/models/__init__.py | 1 - addons/hr_timesheet/models/project.py | 33 ++---------- .../hr_timesheet/security/ir.model.access.csv | 4 -- .../hr_timesheet/views/hr_timesheet_views.xml | 18 ------- addons/hr_timesheet/views/project_views.xml | 3 -- addons/project/__manifest__.py | 2 + addons/project/models/__init__.py | 1 + .../models/analytic_account.py | 0 addons/project/models/project.py | 50 ++++++++++++++++--- addons/project/security/ir.model.access.csv | 6 ++- addons/project/views/analytic_views.xml | 21 ++++++++ addons/project/views/project_views.xml | 1 + 12 files changed, 77 insertions(+), 63 deletions(-) rename addons/{hr_timesheet => project}/models/analytic_account.py (100%) create mode 100644 addons/project/views/analytic_views.xml diff --git a/addons/hr_timesheet/models/__init__.py b/addons/hr_timesheet/models/__init__.py index ce7d853abca..5e18c694d32 100644 --- a/addons/hr_timesheet/models/__init__.py +++ b/addons/hr_timesheet/models/__init__.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import analytic_account from . import hr from . import hr_timesheet from . import ir_http diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index 3e7a5fc3668..8c6d21eab92 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -9,9 +9,6 @@ class Project(models.Model): _inherit = "project.project" allow_timesheets = fields.Boolean("Allow timesheets", default=True, help="Enable timesheeting on the project.") - analytic_account_id = fields.Many2one('account.analytic.account', string="Analytic Account", copy=False, ondelete='set null', - help="Analytic account to which this project is linked for financial management." - "Use an analytic account to record cost and revenue on your project.") @api.onchange('partner_id') def _onchange_partner_id(self): @@ -47,12 +44,7 @@ class Project(models.Model): """ allow_timesheets = values['allow_timesheets'] if 'allow_timesheets' in values else self.default_get(['allow_timesheets'])['allow_timesheets'] if allow_timesheets and not values.get('analytic_account_id'): - analytic_account = self.env['account.analytic.account'].create({ - 'name': values.get('name', _('Unknown Analytic Account')), - 'company_id': values.get('company_id', self.env.company_id.id), - 'partner_id': values.get('partner_id'), - 'active': True, - }) + analytic_account = self._create_analytic_account_from_values(values) values['analytic_account_id'] = analytic_account.id return super(Project, self).create(values) @@ -66,31 +58,14 @@ class Project(models.Model): result = super(Project, self).write(values) return result - @api.multi - def unlink(self): - """ Delete the empty related analytic account """ - analytic_accounts_to_delete = self.env['account.analytic.account'] - for project in self: - if project.analytic_account_id and not project.analytic_account_id.line_ids: - analytic_accounts_to_delete |= project.analytic_account_id - result = super(Project, self).unlink() - analytic_accounts_to_delete.unlink() - return result + # --------------------------------------------------- + # Business Methods + # --------------------------------------------------- @api.model def _init_data_analytic_account(self): self.search([('analytic_account_id', '=', False), ('allow_timesheets', '=', True)])._create_analytic_account() - def _create_analytic_account(self): - for project in self: - analytic_account = self.env['account.analytic.account'].create({ - 'name': project.name, - 'company_id': project.company_id.id, - 'partner_id': project.partner_id.id, - 'active': True, - }) - project.write({'analytic_account_id': analytic_account.id}) - class Task(models.Model): _inherit = "project.task" diff --git a/addons/hr_timesheet/security/ir.model.access.csv b/addons/hr_timesheet/security/ir.model.access.csv index c6776df9364..96723f93935 100644 --- a/addons/hr_timesheet/security/ir.model.access.csv +++ b/addons/hr_timesheet/security/ir.model.access.csv @@ -2,10 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_account_analytic_line_user,analytic.account.analytic.line.timesheet.user,analytic.model_account_analytic_line,hr_timesheet.group_hr_timesheet_user,1,1,1,1 access_account_analytic_line_portal,access_timesheets_portal,analytic.model_account_analytic_line,base.group_portal,1,0,0,0 access_account_analytic_user,analytic.account.analytic.timesheet.user,analytic.model_account_analytic_account,hr_timesheet.group_hr_timesheet_user,1,1,0,0 -access_account_analytic_account_user,account.analytic.account,analytic.model_account_analytic_account,project.group_project_user,1,0,0,0 -access_account_analytic_account_manager,account.analytic.account,analytic.model_account_analytic_account,project.group_project_manager,1,1,1,1 -access_account_analytic_account_portal,account_analytic_account,analytic.model_account_analytic_account,base.group_portal,1,0,0,0 -access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1 access_uom_uom_hr_timesheet,uom.uom.timesheet.user,uom.model_uom_uom,hr_timesheet.group_hr_timesheet_user,1,0,0,0 access_project_project,project.project.timesheet.user,model_project_project,hr_timesheet.group_hr_timesheet_user,1,0,0,0 access_project_task,project.task.timesheet.user,model_project_task,hr_timesheet.group_hr_timesheet_user,1,1,0,0 diff --git a/addons/hr_timesheet/views/hr_timesheet_views.xml b/addons/hr_timesheet/views/hr_timesheet_views.xml index f5a5c8a1929..700feb230fe 100644 --- a/addons/hr_timesheet/views/hr_timesheet_views.xml +++ b/addons/hr_timesheet/views/hr_timesheet_views.xml @@ -1,24 +1,6 @@ - - - account.analytic.account.form.inherit - account.analytic.account - - - - - - - - - - - - diff --git a/addons/project/__manifest__.py b/addons/project/__manifest__.py index 3620923b452..e71a47d8286 100644 --- a/addons/project/__manifest__.py +++ b/addons/project/__manifest__.py @@ -9,6 +9,7 @@ 'sequence': 10, 'summary': 'Organize and schedule your projects ', 'depends': [ + 'analytic', 'base_setup', 'mail', 'portal', @@ -23,6 +24,7 @@ 'security/project_security.xml', 'security/ir.model.access.csv', 'report/project_report_views.xml', + 'views/analytic_views.xml', 'views/digest_views.xml', 'views/rating_views.xml', 'views/project_views.xml', diff --git a/addons/project/models/__init__.py b/addons/project/models/__init__.py index c796777486b..22a31e4bc71 100644 --- a/addons/project/models/__init__.py +++ b/addons/project/models/__init__.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import analytic_account from . import project from . import res_config_settings from . import res_partner diff --git a/addons/hr_timesheet/models/analytic_account.py b/addons/project/models/analytic_account.py similarity index 100% rename from addons/hr_timesheet/models/analytic_account.py rename to addons/project/models/analytic_account.py diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 4e53288d2a8..b615467e909 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -80,13 +80,6 @@ class Project(models.Model): values['alias_defaults'] = {'project_id': self.id} return values - @api.multi - def unlink(self): - for project in self: - if project.tasks: - raise UserError(_('You cannot delete a project containing tasks. You can either archive it or first delete all of its tasks.')) - return super(Project, self).unlink() - def _compute_attached_docs_count(self): Attachment = self.env['ir.attachment'] for project in self: @@ -180,6 +173,9 @@ class Project(models.Model): partner_id = fields.Many2one('res.partner', string='Customer', auto_join=True, tracking=True) company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company_id) currency_id = fields.Many2one('res.currency', related="company_id.currency_id", string="Currency", readonly=True) + analytic_account_id = fields.Many2one('account.analytic.account', string="Analytic Account", copy=False, ondelete='set null', + help="Analytic account to which this project is linked for financial management." + "Use an analytic account to record cost and revenue on your project.") favorite_user_ids = fields.Many2many( 'res.users', 'project_favorite_user_rel', 'project_id', 'user_id', @@ -324,6 +320,21 @@ class Project(models.Model): project.message_subscribe(project.partner_id.ids) return res + @api.multi + def unlink(self): + # Check project is empty + for project in self: + if project.tasks: + raise UserError(_('You cannot delete a project containing tasks. You can either archive it or first delete all of its tasks.')) + # Delete the empty related analytic account + analytic_accounts_to_delete = self.env['account.analytic.account'] + for project in self: + if project.analytic_account_id and not project.analytic_account_id.line_ids: + analytic_accounts_to_delete |= project.analytic_account_id + result = super(Project, self).unlink() + analytic_accounts_to_delete.unlink() + return result + @api.multi def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None): """ Subscribe to all existing active tasks when subscribing to a project """ @@ -383,6 +394,31 @@ class Project(models.Model): action_context.pop('group_by', None) return dict(action, context=action_context) + # --------------------------------------------------- + # Business Methods + # --------------------------------------------------- + + @api.model + def _create_analytic_account_from_values(self, values): + analytic_account = self.env['account.analytic.account'].create({ + 'name': values.get('name', _('Unknown Analytic Account')), + 'company_id': values.get('company_id', self.env.user.company_id.id), + 'partner_id': values.get('partner_id'), + 'active': True, + }) + return analytic_account + + @api.multi + def _create_analytic_account(self): + for project in self: + analytic_account = self.env['account.analytic.account'].create({ + 'name': project.name, + 'company_id': project.company_id.id, + 'partner_id': project.partner_id.id, + 'active': True, + }) + project.write({'analytic_account_id': analytic_account.id}) + # --------------------------------------------------- # Rating business # --------------------------------------------------- diff --git a/addons/project/security/ir.model.access.csv b/addons/project/security/ir.model.access.csv index ed22a1b4da7..f7bf080c5cf 100644 --- a/addons/project/security/ir.model.access.csv +++ b/addons/project/security/ir.model.access.csv @@ -19,4 +19,8 @@ access_project_tags_all,project.project_tags_all,model_project_tags,,1,0,0,0 access_project_tags_manager,project.project_tags_manager,model_project_tags,project.group_project_manager,1,1,1,1 access_project_tags_portal,project_tags_portal,project.model_project_tags,base.group_portal,1,0,0,0 access_mail_alias,mail.alias,mail.model_mail_alias,project.group_project_manager,1,1,1,1 -access_mail_activity_type_project_manager,mail.activity.type.project.manager,mail.model_mail_activity_type,project.group_project_manager,1,1,1,1 \ No newline at end of file +access_mail_activity_type_project_manager,mail.activity.type.project.manager,mail.model_mail_activity_type,project.group_project_manager,1,1,1,1 +access_account_analytic_account_user,account.analytic.account,analytic.model_account_analytic_account,project.group_project_user,1,0,0,0 +access_account_analytic_account_manager,account.analytic.account,analytic.model_account_analytic_account,project.group_project_manager,1,1,1,1 +access_account_analytic_account_portal,account_analytic_account,analytic.model_account_analytic_account,base.group_portal,1,0,0,0 +access_account_analytic_line_project,account.analytic.line project,analytic.model_account_analytic_line,project.group_project_manager,1,1,1,1 \ No newline at end of file diff --git a/addons/project/views/analytic_views.xml b/addons/project/views/analytic_views.xml new file mode 100644 index 00000000000..bf6809dc5c4 --- /dev/null +++ b/addons/project/views/analytic_views.xml @@ -0,0 +1,21 @@ + + + + + account.analytic.account.form.inherit + account.analytic.account + + + + + + + + + + diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 54eb70b7935..9b8840ce0b6 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -140,6 +140,7 @@ + diff --git a/addons/project/models/project.py b/addons/project/models/project.py index b615467e909..679a63930f2 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -376,6 +376,13 @@ class Project(models.Model): action = self.env['ir.actions.act_window'].for_xml_id('project', 'act_project_project_2_project_task_all') return dict(action, context=ctx) + def action_view_account_analytic_line(self): + """ return the action to see all the analytic lines of the project's analytic account """ + action = self.env.ref('analytic.account_analytic_line_action').read()[0] + action['context'] = {'default_account_id': self.analytic_account_id.id} + action['domain'] = [('account_id', '=', self.analytic_account_id.id)] + return action + @api.multi def action_view_all_rating(self): """ return the action to see all the rating of the project, and activate default filters """ diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 9b8840ce0b6..da0d1921500 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -304,6 +304,7 @@ +
@@ -360,6 +361,11 @@
+ +
+ Profitability +
+
From 3ab9b5192c71073a5c3d629ce598d5bafd3407a5 Mon Sep 17 00:00:00 2001 From: Geoffroy Larue Date: Thu, 9 May 2019 14:09:40 +0000 Subject: [PATCH 5/5] [IMP] project, sale_timesheet: usability Fix a tiny typo in project and rename two fields in Project Overview to improve usability. Task-1975022 --- addons/project/models/project.py | 2 +- addons/sale_timesheet/views/hr_timesheet_templates.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 679a63930f2..627ec77b643 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -174,7 +174,7 @@ class Project(models.Model): company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company_id) currency_id = fields.Many2one('res.currency', related="company_id.currency_id", string="Currency", readonly=True) analytic_account_id = fields.Many2one('account.analytic.account', string="Analytic Account", copy=False, ondelete='set null', - help="Analytic account to which this project is linked for financial management." + help="Analytic account to which this project is linked for financial management. " "Use an analytic account to record cost and revenue on your project.") favorite_user_ids = fields.Many2many( diff --git a/addons/sale_timesheet/views/hr_timesheet_templates.xml b/addons/sale_timesheet/views/hr_timesheet_templates.xml index 7f999d9e27c..200d9af637d 100644 --- a/addons/sale_timesheet/views/hr_timesheet_templates.xml +++ b/addons/sale_timesheet/views/hr_timesheet_templates.xml @@ -71,7 +71,7 @@ - Invoiced + Time invoiced @@ -85,7 +85,7 @@ - To invoice + Time to invoice