diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index e93a3c5deac..f82c68fbda8 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -8,10 +8,10 @@ from odoo.exceptions import UserError, ValidationError class Project(models.Model): _inherit = "project.project" - allow_timesheets = fields.Boolean("Allow timesheets", default=True) + 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="Link this project to an analytic account if you need financial management on projects. " - "It enables you to connect projects with budgets, planning, cost and revenue analysis, timesheets on projects, etc.") + 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): diff --git a/addons/project/models/project.py b/addons/project/models/project.py index b3286c2afe3..dc1044defce 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -185,9 +185,8 @@ class Project(models.Model): default=_get_default_favorite_user_ids, string='Members') is_favorite = fields.Boolean(compute='_compute_is_favorite', inverse='_inverse_is_favorite', string='Show Project on dashboard', - help="Whether this project should be displayed on the dashboard or not") - label_tasks = fields.Char(string='Use Tasks as', default=lambda s: _('Tasks'), translate=True, - help="Gives label to tasks on project's kanban view.") + help="Whether this project should be displayed on your dashboard.") + label_tasks = fields.Char(string='Use Tasks as', default='Tasks', help="Label used for the tasks of the project.") tasks = fields.One2many('project.task', 'project_id', string="Task Activities") resource_calendar_id = fields.Many2one( 'resource.calendar', string='Working Time', @@ -209,27 +208,26 @@ class Project(models.Model): ], string='Privacy', required=True, default='portal', - help="Holds visibility of the tasks or issues that belong to the current project:\n" - "- On invitation only: Employees may only see the followed project, tasks or issues\n" - "- Visible by all employees: Employees may see all project, tasks or issues\n" - "- Visible by following customers: employees see everything;\n" - " if website is activated, portal users may see project, tasks or issues followed by\n" - " them or by someone of their company\n") + help="Defines the visibility of the tasks of the project:\n" + "- On invitation only: employees may only see the followed project and tasks.\n" + "- Visible by all employees: employees may see all project and tasks.\n" + "- Visible by following customers: employees may see everything." + " if website is activated, portal users may see project and tasks followed by.\n" + " them or by someone of their company.") doc_count = fields.Integer(compute='_compute_attached_docs_count', string="Number of documents attached") date_start = fields.Date(string='Start Date') date = fields.Date(string='Expiration Date', index=True, track_visibility='onchange') subtask_project_id = fields.Many2one('project.project', string='Sub-task Project', ondelete="restrict", - help="Choosing a sub-tasks project will both enable sub-tasks and set their default project (possibly the project itself)") + help="Project in which sub-tasks of the current project will be created. It can be the current project itself.") # rating fields percentage_satisfaction_task = fields.Integer( - compute='_compute_percentage_satisfaction_task', string="Happy % on Task", store=True, default=-1) - percentage_satisfaction_project = fields.Integer( - compute="_compute_percentage_satisfaction_project", string="Happy % on Project", store=True, default=-1) + compute='_compute_percentage_satisfaction_task', string="Happy % on Task", help="Satisfaction rate on task.", store=True, default=-1) + percentage_satisfaction_project = fields.Integer(compute="_compute_percentage_satisfaction_project", string="Happy % on Project", help="Satisfaction rate on project.", store=True, default=-1) rating_request_deadline = fields.Datetime(compute='_compute_rating_request_deadline', store=True) - rating_status = fields.Selection([('stage', 'Rating when changing stage'), ('periodic', 'Periodical Rating'), ('no','No rating')], 'Customer(s) Ratings', help="How to get the customer's feedbacks?\n" - "- Rating when changing stage: Email will be sent when a task/issue is pulled in another stage\n" - "- Periodical Rating: Email will be sent periodically\n\n" + rating_status = fields.Selection([('stage', 'Rating when changing stage'), ('periodic', 'Periodical Rating'), ('no','No rating')], 'Customer(s) Ratings', help="How to get customer feedback?\n" + "- Rating when changing stage: an email will be sent when a task is pulled in another stage.\n" + "- Periodical Rating: email will be sent periodically.\n\n" "Don't forget to set up the mail templates on the stages for which you want to get the customer's feedbacks.", default="no", required=True) rating_status_period = fields.Selection([ ('daily', 'Daily'), ('weekly', 'Weekly'), ('bimonthly', 'Twice a Month'), diff --git a/addons/sale_timesheet/models/project.py b/addons/sale_timesheet/models/project.py index f2e7a7ee275..aa2b573f8d0 100644 --- a/addons/sale_timesheet/models/project.py +++ b/addons/sale_timesheet/models/project.py @@ -8,18 +8,23 @@ from odoo.exceptions import ValidationError class Project(models.Model): _inherit = 'project.project' - sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Item', domain="[('is_expense', '=', False), ('order_id', '=', sale_order_id), ('state', 'in', ['sale', 'done'])]", copy=False, help="Sale order line from which the project has been created. Used for tracability.") - sale_order_id = fields.Many2one('sale.order', 'Sales Order', domain="[('partner_id', '=', partner_id)]", readonly=True, copy=False) + sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Item', domain="[('is_expense', '=', False), ('order_id', '=', sale_order_id), ('state', 'in', ['sale', 'done'])]", copy=False, + help="Sales order item to which the project is linked. If an employee timesheets on a task that does not have a " + "sale order item defines, and if this employee is not in the 'Employee/Sales Order Item Mapping' of the project, " + "the timesheet entry will be linked to the sales order item defined on the project.") + sale_order_id = fields.Many2one('sale.order', 'Sales Order', domain="[('partner_id', '=', partner_id)]", readonly=True, copy=False, help="Sales order to which the project is linked.") billable_type = fields.Selection([ ('task_rate', 'At Task Rate'), ('employee_rate', 'At Employee Rate'), ('no', 'No Billable') ], string="Billable Type", compute='_compute_billable_type', compute_sudo=True, store=True, - help='Billable type implies:\n' + help='At which rate timesheets will be billed:\n' ' - At task rate: each time spend on a task is billed at task rate.\n' ' - At employee rate: each employee log time billed at his rate.\n' ' - No Billable: track time without invoicing it') - sale_line_employee_ids = fields.One2many('project.sale.line.employee.map', 'project_id', "Sale line/Employee map", copy=False) + sale_line_employee_ids = fields.One2many('project.sale.line.employee.map', 'project_id', "Sale line/Employee map", copy=False, + help="Employee/Sale Order Item Mapping:\n Defines to which sales order item an employee's timesheet entry will be linked." + "By extension, it defines the rate at which an employee's time on the project is billed.") _sql_constraints = [ ('sale_order_required_if_sale_line', "CHECK((sale_line_id IS NOT NULL AND sale_order_id IS NOT NULL) OR (sale_line_id IS NULL))", 'The Project should be linked to a Sale Order to select an Sale Order Items.'), @@ -142,8 +147,11 @@ class ProjectTask(models.Model): sale_line_id = project.sale_line_id.id return sale_line_id - sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Item', default=_default_sale_line_id, domain="[('is_service', '=', True), ('order_partner_id', '=', partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]") - sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', compute_sudo=True, store=True, readonly=True) + sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Item', default=_default_sale_line_id, domain="[('is_service', '=', True), ('order_partner_id', '=', partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]", + help="Sales order item to which the task is linked. If an employee timesheets on a this task, " + "and if this employee is not in the 'Employee/Sales Order Item Mapping' of the project, the " + "timesheet entry will be linked to this sales order item.") + sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', compute_sudo=True, store=True, readonly=True, help="Sales order to which the task is linked.") billable_type = fields.Selection([ ('task_rate', 'At Task Rate'), ('employee_rate', 'At Employee Rate'),