mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 03:52:02 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,211 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, exceptions, fields, models, _
|
||||
|
||||
|
||||
class CrmTeamMember(models.Model):
|
||||
_name = 'crm.team.member'
|
||||
_inherit = ['mail.thread']
|
||||
_description = 'Sales Team Member'
|
||||
_rec_name = 'user_id'
|
||||
_order = 'create_date ASC, id'
|
||||
_check_company_auto = True
|
||||
|
||||
crm_team_id = fields.Many2one(
|
||||
'crm.team', string='Sales Team', group_expand='_read_group_crm_team_id',
|
||||
default=False, # TDE: temporary fix to activate depending computed fields
|
||||
check_company=True, index=True, ondelete="cascade", required=True)
|
||||
user_id = fields.Many2one(
|
||||
'res.users', string='Salesperson', # TDE FIXME check responsible field
|
||||
check_company=True, index=True, ondelete='cascade', required=True,
|
||||
domain="[('share', '=', False), ('id', 'not in', user_in_teams_ids), ('company_ids', 'in', user_company_ids)]")
|
||||
user_in_teams_ids = fields.Many2many(
|
||||
'res.users', compute='_compute_user_in_teams_ids',
|
||||
help='UX: Give users not to add in the currently chosen team to avoid duplicates')
|
||||
user_company_ids = fields.Many2many(
|
||||
'res.company', compute='_compute_user_company_ids',
|
||||
help='UX: Limit to team company or all if no company')
|
||||
active = fields.Boolean(string='Active', default=True)
|
||||
is_membership_multi = fields.Boolean(
|
||||
'Multiple Memberships Allowed', compute='_compute_is_membership_multi',
|
||||
help='If True, users may belong to several sales teams. Otherwise membership is limited to a single sales team.')
|
||||
member_warning = fields.Text(compute='_compute_member_warning')
|
||||
# salesman information
|
||||
image_1920 = fields.Image("Image", related="user_id.image_1920", max_width=1920, max_height=1920)
|
||||
image_128 = fields.Image("Image (128)", related="user_id.image_128", max_width=128, max_height=128)
|
||||
name = fields.Char(string='Name', related='user_id.display_name', readonly=False)
|
||||
email = fields.Char(string='Email', related='user_id.email')
|
||||
phone = fields.Char(string='Phone', related='user_id.phone')
|
||||
mobile = fields.Char(string='Mobile', related='user_id.mobile')
|
||||
company_id = fields.Many2one('res.company', string='Company', related='user_id.company_id')
|
||||
|
||||
@api.constrains('crm_team_id', 'user_id', 'active')
|
||||
def _constrains_membership(self):
|
||||
# In mono membership mode: check crm_team_id / user_id is unique for active
|
||||
# memberships. Inactive memberships can create duplicate pairs which is whyy
|
||||
# we don't use a SQL constraint. Include "self" in search in case we use create
|
||||
# multi with duplicated user / team pairs in it. Use an explicit active leaf
|
||||
# in domain as we may have an active_test in context that would break computation
|
||||
existing = self.env['crm.team.member'].search([
|
||||
('crm_team_id', 'in', self.crm_team_id.ids),
|
||||
('user_id', 'in', self.user_id.ids),
|
||||
('active', '=', True)
|
||||
])
|
||||
duplicates = self.env['crm.team.member']
|
||||
|
||||
active_records = dict(
|
||||
(membership.user_id.id, membership.crm_team_id.id)
|
||||
for membership in self if membership.active
|
||||
)
|
||||
for membership in self:
|
||||
potential = existing.filtered(lambda m: m.user_id == membership.user_id and \
|
||||
m.crm_team_id == membership.crm_team_id and m.id != membership.id
|
||||
)
|
||||
if not potential or len(potential) > 1:
|
||||
duplicates += potential
|
||||
continue
|
||||
if active_records.get(potential.user_id.id):
|
||||
duplicates += potential
|
||||
else:
|
||||
active_records[potential.user_id.id] = potential.crm_team_id.id
|
||||
|
||||
if duplicates:
|
||||
raise exceptions.ValidationError(
|
||||
_("You are trying to create duplicate membership(s). We found that %(duplicates)s already exist(s).",
|
||||
duplicates=", ".join("%s (%s)" % (m.user_id.name, m.crm_team_id.name) for m in duplicates)
|
||||
))
|
||||
|
||||
@api.depends('crm_team_id', 'is_membership_multi', 'user_id')
|
||||
@api.depends_context('default_crm_team_id')
|
||||
def _compute_user_in_teams_ids(self):
|
||||
""" Give users not to add in the currently chosen team to avoid duplicates.
|
||||
In multi membership mode this field is empty as duplicates are allowed. """
|
||||
if all(m.is_membership_multi for m in self):
|
||||
member_user_ids = self.env['res.users']
|
||||
elif self.ids:
|
||||
member_user_ids = self.env['crm.team.member'].search([('id', 'not in', self.ids)]).user_id
|
||||
else:
|
||||
member_user_ids = self.env['crm.team.member'].search([]).user_id
|
||||
for member in self:
|
||||
if member_user_ids:
|
||||
member.user_in_teams_ids = member_user_ids
|
||||
elif member.crm_team_id:
|
||||
member.user_in_teams_ids = member.crm_team_id.member_ids
|
||||
elif self.env.context.get('default_crm_team_id'):
|
||||
member.user_in_teams_ids = self.env['crm.team'].browse(self.env.context['default_crm_team_id']).member_ids
|
||||
else:
|
||||
member.user_in_teams_ids = self.env['res.users']
|
||||
|
||||
@api.depends('crm_team_id')
|
||||
def _compute_user_company_ids(self):
|
||||
all_companies = self.env['res.company'].search([])
|
||||
for member in self:
|
||||
member.user_company_ids = member.crm_team_id.company_id or all_companies
|
||||
|
||||
@api.depends('crm_team_id')
|
||||
def _compute_is_membership_multi(self):
|
||||
multi_enabled = self.env['ir.config_parameter'].sudo().get_param('sales_team.membership_multi', False)
|
||||
self.is_membership_multi = multi_enabled
|
||||
|
||||
@api.depends('is_membership_multi', 'active', 'user_id', 'crm_team_id')
|
||||
def _compute_member_warning(self):
|
||||
""" Display a warning message to warn user they are about to archive
|
||||
other memberships. Only valid in mono-membership mode and take into
|
||||
account only active memberships as we may keep several archived
|
||||
memberships. """
|
||||
if all(m.is_membership_multi for m in self):
|
||||
self.member_warning = False
|
||||
else:
|
||||
active = self.filtered('active')
|
||||
(self - active).member_warning = False
|
||||
if not active:
|
||||
return
|
||||
existing = self.env['crm.team.member'].search([('user_id', 'in', active.user_id.ids)])
|
||||
user_mapping = dict.fromkeys(existing.user_id, self.env['crm.team'])
|
||||
for membership in existing:
|
||||
user_mapping[membership.user_id] |= membership.crm_team_id
|
||||
|
||||
for member in active:
|
||||
teams = user_mapping.get(member.user_id, self.env['crm.team'])
|
||||
remaining = teams - (member.crm_team_id | member._origin.crm_team_id)
|
||||
if remaining:
|
||||
member.member_warning = _("Adding %(user_name)s in this team would remove him/her from its current teams %(team_names)s.",
|
||||
user_name=member.user_id.name,
|
||||
team_names=", ".join(remaining.mapped('name'))
|
||||
)
|
||||
else:
|
||||
member.member_warning = False
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, values_list):
|
||||
""" Specific behavior implemented on create
|
||||
|
||||
* mono membership mode: other user memberships are automatically
|
||||
archived (a warning already told it in form view);
|
||||
* creating a membership already existing as archived: do nothing as
|
||||
people can manage them from specific menu "Members";
|
||||
|
||||
Also remove autofollow on create. No need to follow team members
|
||||
when creating them as chatter is mainly used for information purpose
|
||||
(tracked fields).
|
||||
"""
|
||||
is_membership_multi = self.env['ir.config_parameter'].sudo().get_param('sales_team.membership_multi', False)
|
||||
if not is_membership_multi:
|
||||
self._synchronize_memberships(values_list)
|
||||
return super(CrmTeamMember, self.with_context(
|
||||
mail_create_nosubscribe=True
|
||||
)).create(values_list)
|
||||
|
||||
def write(self, values):
|
||||
""" Specific behavior about active. If you change user_id / team_id user
|
||||
get warnings in form view and a raise in constraint check. We support
|
||||
archive / activation of memberships that toggles other memberships. But
|
||||
we do not support manual creation or update of user_id / team_id. This
|
||||
either works, either crashes). Indeed supporting it would lead to complex
|
||||
code with low added value. Users should create or remove members, and
|
||||
maybe archive / activate them. Updating manually memberships by
|
||||
modifying user_id or team_id is advanced and does not benefit from our
|
||||
support. """
|
||||
is_membership_multi = self.env['ir.config_parameter'].sudo().get_param('sales_team.membership_multi', False)
|
||||
if not is_membership_multi and values.get('active'):
|
||||
self._synchronize_memberships([
|
||||
dict(user_id=membership.user_id.id, crm_team_id=membership.crm_team_id.id)
|
||||
for membership in self
|
||||
])
|
||||
return super(CrmTeamMember, self).write(values)
|
||||
|
||||
@api.model
|
||||
def _read_group_crm_team_id(self, teams, domain, order):
|
||||
"""Read group customization in order to display all the teams in
|
||||
Kanban view, even if they are empty.
|
||||
"""
|
||||
return self.env['crm.team'].search([], order=order)
|
||||
|
||||
def _synchronize_memberships(self, user_team_ids):
|
||||
""" Synchronize memberships: archive other memberships.
|
||||
|
||||
:param user_team_ids: list of pairs (user_id, crm_team_id)
|
||||
"""
|
||||
existing = self.search([
|
||||
('active', '=', True), # explicit search on active only, whatever context
|
||||
('user_id', 'in', [values['user_id'] for values in user_team_ids])
|
||||
])
|
||||
user_memberships = dict.fromkeys(existing.user_id.ids, self.env['crm.team.member'])
|
||||
for membership in existing:
|
||||
user_memberships[membership.user_id.id] += membership
|
||||
|
||||
existing_to_archive = self.env['crm.team.member']
|
||||
for values in user_team_ids:
|
||||
existing_to_archive += user_memberships.get(values['user_id'], self.env['crm.team.member']).filtered(
|
||||
lambda m: m.crm_team_id.id != values['crm_team_id']
|
||||
)
|
||||
|
||||
if existing_to_archive:
|
||||
existing_to_archive.action_archive()
|
||||
|
||||
return existing_to_archive
|
||||
Loading…
Add table
Add a link
Reference in a new issue