[MERGE] project, sale_timesheet: multi company fixes
Impacted modules: project, sale, sale_timesheet and project_timesheet_holidays.
Since a5b6f31cf2, the multi company environment is contextualized,
allowing people to see several company documents at the same time. This reveals
some problem in such env.
To solve this, we need to force the "company_id" field as required on some business
model, and to correctly propagate the company when a document generate another one.
The guidelines is to stop using company of current user, but the one of the document
itself.
See subcommits for more details.
Task-1999686
closes odoo/odoo#33739
Signed-off-by: Jérome Maes (jem) <jem@openerp.com>
This commit is contained in:
@@ -408,7 +408,7 @@ class Project(models.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),
|
||||
'company_id': values.get('company_id') or self.env.company.id,
|
||||
'partner_id': values.get('partner_id'),
|
||||
'active': True,
|
||||
})
|
||||
@@ -519,9 +519,7 @@ class Task(models.Model):
|
||||
string='Customer',
|
||||
default=lambda self: self._get_default_partner())
|
||||
manager_id = fields.Many2one('res.users', string='Project Manager', related='project_id.user_id', readonly=True, related_sudo=False)
|
||||
company_id = fields.Many2one('res.company',
|
||||
string='Company',
|
||||
default=lambda self: self.env.company)
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company)
|
||||
color = fields.Integer(string='Color Index')
|
||||
user_email = fields.Char(related='user_id.email', string='User Email', readonly=True, related_sudo=False)
|
||||
attachment_ids = fields.One2many('ir.attachment', compute='_compute_attachment_ids', string="Main Attachments",
|
||||
|
||||
@@ -38,10 +38,7 @@
|
||||
<field name="name">Project: multi-company</field>
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',
|
||||
('company_id', '=', False),
|
||||
('company_id', 'in', company_ids),
|
||||
]</field>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="project_project_manager_rule">
|
||||
@@ -67,10 +64,7 @@
|
||||
<field name="name">Project/Task: multi-company</field>
|
||||
<field name="model_id" ref="model_project_task"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',
|
||||
('company_id', '=', False),
|
||||
('company_id', 'in', company_ids),
|
||||
]</field>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="task_visibility_rule">
|
||||
@@ -100,7 +94,7 @@
|
||||
<field name="name">Task Analysis multi-company</field>
|
||||
<field name="model_id" ref="model_report_project_task_user"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<!-- Portal -->
|
||||
|
||||
@@ -151,15 +151,12 @@
|
||||
<field name="rating_status_period" class="oe_inline" attrs="{'required': [('rating_status','=','periodic')], 'invisible': [('rating_status','!=','periodic')]}" groups="project.group_project_rating"/>
|
||||
<field name="portal_show_rating" attrs="{'invisible': [('rating_status','==','no')]}" groups="project.group_project_rating"/>
|
||||
<field name="subtask_project_id" groups="project.group_subtask_project"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group name="extra_settings">
|
||||
</group>
|
||||
</group>
|
||||
<group name="misc">
|
||||
<group string="Configuration" groups="base.group_no_one" name="configuration">
|
||||
<field name="sequence" groups="base.group_no_one"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group string="Time Scheduling">
|
||||
<field name="resource_calendar_id"/>
|
||||
</group>
|
||||
|
||||
@@ -83,6 +83,7 @@ class Holidays(models.Model):
|
||||
'date': fields.Date.to_string(day_date),
|
||||
'holiday_id': holiday.id,
|
||||
'employee_id': holiday.employee_id.id,
|
||||
'company_id': holiday_task.company_id.id or holiday_project.company_id.id,
|
||||
})
|
||||
|
||||
return super(Holidays, self)._validate_leave_request()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class Company(models.Model):
|
||||
@@ -14,6 +15,13 @@ class Company(models.Model):
|
||||
'project.task', string="Time Off Task",
|
||||
domain="[('project_id', '=', leave_timesheet_project_id)]")
|
||||
|
||||
@api.constrains('leave_timesheet_project_id')
|
||||
def _check_leave_timesheet_project_id_company(self):
|
||||
for company in self:
|
||||
if company.leave_timesheet_project_id:
|
||||
if company.leave_timesheet_project_id.company_id != company:
|
||||
raise ValidationError(_('The Internal Project of a company should be in that company.'))
|
||||
|
||||
def init(self):
|
||||
self.search([('leave_timesheet_project_id', '=', False)])._create_leave_project_task()
|
||||
|
||||
@@ -40,7 +48,7 @@ class Company(models.Model):
|
||||
'name': _('Time Off'),
|
||||
'project_id': company.leave_timesheet_project_id.id,
|
||||
'active': False,
|
||||
'company_id': False,
|
||||
'company_id': company.id,
|
||||
})
|
||||
company.write({
|
||||
'leave_timesheet_task_id': task.id,
|
||||
|
||||
@@ -7,5 +7,5 @@ from odoo import fields, models
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
leave_timesheet_project_id = fields.Many2one(related='company_id.leave_timesheet_project_id', string="Internal Project", readonly=False)
|
||||
leave_timesheet_task_id = fields.Many2one(related='company_id.leave_timesheet_task_id', string="Time Off Task", readonly=False)
|
||||
leave_timesheet_project_id = fields.Many2one(related='company_id.leave_timesheet_project_id', string="Internal Project", domain="[('company_id', '=', company_id)]", readonly=False)
|
||||
leave_timesheet_task_id = fields.Many2one(related='company_id.leave_timesheet_task_id', string="Time Off Task", domain="[('company_id', '=', company_id)]", readonly=False)
|
||||
|
||||
@@ -174,7 +174,7 @@ class SaleOrder(models.Model):
|
||||
|
||||
payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms', oldname='payment_term', help="Payment terms applies to all invoices issued from this order.")
|
||||
fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position', help=" Fiscal positions are used to adapt taxes and accounts for particular customers or sales orders/invoices. The default value comes from the customer.")
|
||||
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
|
||||
company_id = fields.Many2one('res.company', 'Company', required=True, default=lambda self: self.env.company)
|
||||
team_id = fields.Many2one('crm.team', 'Sales Team', change_default=True, default=_get_default_team, oldname='section_id')
|
||||
|
||||
signature = fields.Binary('Signature', help='Signature received through the portal.', copy=False, attachment=True)
|
||||
|
||||
@@ -42,14 +42,14 @@
|
||||
<field name="name">Sales Order multi-company</field>
|
||||
<field name="model_id" ref="model_sale_order"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="sale_order_line_comp_rule">
|
||||
<field name="name">Sales Order Line multi-company</field>
|
||||
<field name="model_id" ref="model_sale_order_line"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule" id="sale_order_report_comp_rule">
|
||||
|
||||
@@ -212,7 +212,7 @@ class SaleOrderLine(models.Model):
|
||||
if 'product_uom_qty' in values:
|
||||
for line in self:
|
||||
if line.task_id:
|
||||
planned_hours = line._convert_qty_company_hours()
|
||||
planned_hours = line._convert_qty_company_hours(line.task_id.company_id)
|
||||
line.task_id.write({'planned_hours': planned_hours})
|
||||
return result
|
||||
|
||||
@@ -220,8 +220,8 @@ class SaleOrderLine(models.Model):
|
||||
# Service : Project and task generation
|
||||
###########################################
|
||||
|
||||
def _convert_qty_company_hours(self):
|
||||
company_time_uom_id = self.env.company.project_time_mode_id
|
||||
def _convert_qty_company_hours(self, dest_company):
|
||||
company_time_uom_id = dest_company.project_time_mode_id
|
||||
if self.product_uom.id != company_time_uom_id.id and self.product_uom.category_id.id == company_time_uom_id.category_id.id:
|
||||
planned_hours = self.product_uom._compute_quantity(self.product_uom_qty, company_time_uom_id)
|
||||
else:
|
||||
@@ -249,6 +249,7 @@ class SaleOrderLine(models.Model):
|
||||
'sale_line_id': self.id,
|
||||
'sale_order_id': self.order_id.id,
|
||||
'active': True,
|
||||
'company_id': self.company_id.id,
|
||||
}
|
||||
if self.product_id.project_template_id:
|
||||
values['name'] = "%s - %s" % (values['name'], self.product_id.project_template_id.name)
|
||||
@@ -270,7 +271,7 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
def _timesheet_create_task_prepare_values(self, project):
|
||||
self.ensure_one()
|
||||
planned_hours = self._convert_qty_company_hours()
|
||||
planned_hours = self._convert_qty_company_hours(self.company_id)
|
||||
sale_line_name_parts = self.name.split('\n')
|
||||
title = sale_line_name_parts[0] or self.product_id.name
|
||||
description = '<br/>'.join(sale_line_name_parts[1:])
|
||||
|
||||
@@ -76,6 +76,7 @@ class ProjectCreateSalesOrder(models.TransientModel):
|
||||
'partner_id': self.partner_id.id,
|
||||
'analytic_account_id': self.project_id.analytic_account_id.id,
|
||||
'client_order_ref': self.project_id.name,
|
||||
'company_id': self.project_id.company_id.id,
|
||||
})
|
||||
sale_order.onchange_partner_id()
|
||||
sale_order.onchange_partner_shipping_id()
|
||||
|
||||
Reference in New Issue
Block a user