crm_lead_to_opportunity.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models
  4. from odoo.exceptions import UserError
  5. from odoo.tools.translate import _
  6. class Lead2OpportunityPartner(models.TransientModel):
  7. _name = 'crm.lead2opportunity.partner'
  8. _description = 'Convert Lead to Opportunity (not in mass)'
  9. @api.model
  10. def default_get(self, fields):
  11. """ Allow support of active_id / active_model instead of jut default_lead_id
  12. to ease window action definitions, and be backward compatible. """
  13. result = super(Lead2OpportunityPartner, self).default_get(fields)
  14. if not result.get('lead_id') and self.env.context.get('active_id'):
  15. result['lead_id'] = self.env.context.get('active_id')
  16. if result.get('lead_id'):
  17. if self.env['crm.lead'].browse(result['lead_id']).probability == 100:
  18. raise UserError(_("Closed/Dead leads cannot be converted into opportunities."))
  19. return result
  20. name = fields.Selection([
  21. ('convert', 'Convert to opportunity'),
  22. ('merge', 'Merge with existing opportunities')
  23. ], 'Conversion Action', compute='_compute_name', readonly=False, store=True, compute_sudo=False)
  24. action = fields.Selection([
  25. ('create', 'Create a new customer'),
  26. ('exist', 'Link to an existing customer'),
  27. ('nothing', 'Do not link to a customer')
  28. ], string='Related Customer', compute='_compute_action', readonly=False, store=True, compute_sudo=False)
  29. lead_id = fields.Many2one('crm.lead', 'Associated Lead', required=True)
  30. duplicated_lead_ids = fields.Many2many(
  31. 'crm.lead', string='Opportunities', context={'active_test': False},
  32. compute='_compute_duplicated_lead_ids', readonly=False, store=True, compute_sudo=False)
  33. partner_id = fields.Many2one(
  34. 'res.partner', 'Customer',
  35. compute='_compute_partner_id', readonly=False, store=True, compute_sudo=False)
  36. user_id = fields.Many2one(
  37. 'res.users', 'Salesperson',
  38. compute='_compute_user_id', readonly=False, store=True, compute_sudo=False)
  39. team_id = fields.Many2one(
  40. 'crm.team', 'Sales Team',
  41. compute='_compute_team_id', readonly=False, store=True, compute_sudo=False)
  42. force_assignment = fields.Boolean(
  43. 'Force assignment', default=True,
  44. help='If checked, forces salesman to be updated on updated opportunities even if already set.')
  45. @api.depends('duplicated_lead_ids')
  46. def _compute_name(self):
  47. for convert in self:
  48. if not convert.name:
  49. convert.name = 'merge' if convert.duplicated_lead_ids and len(convert.duplicated_lead_ids) >= 2 else 'convert'
  50. @api.depends('lead_id')
  51. def _compute_action(self):
  52. for convert in self:
  53. if not convert.lead_id:
  54. convert.action = 'nothing'
  55. else:
  56. partner = convert.lead_id._find_matching_partner()
  57. if partner:
  58. convert.action = 'exist'
  59. elif convert.lead_id.contact_name:
  60. convert.action = 'create'
  61. else:
  62. convert.action = 'nothing'
  63. @api.depends('lead_id', 'partner_id')
  64. def _compute_duplicated_lead_ids(self):
  65. for convert in self:
  66. if not convert.lead_id:
  67. convert.duplicated_lead_ids = False
  68. continue
  69. convert.duplicated_lead_ids = self.env['crm.lead']._get_lead_duplicates(
  70. convert.partner_id,
  71. convert.lead_id.partner_id.email if convert.lead_id.partner_id.email else convert.lead_id.email_from,
  72. include_lost=True).ids
  73. @api.depends('action', 'lead_id')
  74. def _compute_partner_id(self):
  75. for convert in self:
  76. if convert.action == 'exist':
  77. convert.partner_id = convert.lead_id._find_matching_partner()
  78. else:
  79. convert.partner_id = False
  80. @api.depends('lead_id')
  81. def _compute_user_id(self):
  82. for convert in self:
  83. convert.user_id = convert.lead_id.user_id if convert.lead_id.user_id else False
  84. @api.depends('user_id')
  85. def _compute_team_id(self):
  86. """ When changing the user, also set a team_id or restrict team id
  87. to the ones user_id is member of. """
  88. for convert in self:
  89. # setting user as void should not trigger a new team computation
  90. if not convert.user_id:
  91. continue
  92. user = convert.user_id
  93. if convert.team_id and user in convert.team_id.member_ids | convert.team_id.user_id:
  94. continue
  95. team = self.env['crm.team']._get_default_team_id(user_id=user.id, domain=None)
  96. convert.team_id = team.id
  97. def action_apply(self):
  98. if self.name == 'merge':
  99. result_opportunity = self._action_merge()
  100. else:
  101. result_opportunity = self._action_convert()
  102. return result_opportunity.redirect_lead_opportunity_view()
  103. def _action_merge(self):
  104. to_merge = self.duplicated_lead_ids
  105. result_opportunity = to_merge.merge_opportunity(auto_unlink=False)
  106. result_opportunity.action_unarchive()
  107. if result_opportunity.type == "lead":
  108. self._convert_and_allocate(result_opportunity, [self.user_id.id], team_id=self.team_id.id)
  109. else:
  110. if not result_opportunity.user_id or self.force_assignment:
  111. result_opportunity.write({
  112. 'user_id': self.user_id.id,
  113. 'team_id': self.team_id.id,
  114. })
  115. (to_merge - result_opportunity).sudo().unlink()
  116. return result_opportunity
  117. def _action_convert(self):
  118. """ """
  119. result_opportunities = self.env['crm.lead'].browse(self._context.get('active_ids', []))
  120. self._convert_and_allocate(result_opportunities, [self.user_id.id], team_id=self.team_id.id)
  121. return result_opportunities[0]
  122. def _convert_and_allocate(self, leads, user_ids, team_id=False):
  123. self.ensure_one()
  124. for lead in leads:
  125. if lead.active and self.action != 'nothing':
  126. self._convert_handle_partner(
  127. lead, self.action, self.partner_id.id or lead.partner_id.id)
  128. lead.convert_opportunity(lead.partner_id, user_ids=False, team_id=False)
  129. leads_to_allocate = leads
  130. if not self.force_assignment:
  131. leads_to_allocate = leads_to_allocate.filtered(lambda lead: not lead.user_id)
  132. if user_ids:
  133. leads_to_allocate._handle_salesmen_assignment(user_ids, team_id=team_id)
  134. def _convert_handle_partner(self, lead, action, partner_id):
  135. # used to propagate user_id (salesman) on created partners during conversion
  136. lead.with_context(default_user_id=self.user_id.id)._handle_partner_assignment(
  137. force_partner_id=partner_id,
  138. create_missing=(action == 'create')
  139. )