mirror of
https://github.com/bringout/oca-ocb-crm.git
synced 2026-04-24 05:52:04 +02:00
19.0 vanilla
This commit is contained in:
parent
dc68f80d3f
commit
7221b9ac46
610 changed files with 135477 additions and 161677 deletions
|
|
@ -2,12 +2,12 @@ from math import floor, log10
|
|||
from odoo import api, models
|
||||
|
||||
|
||||
class CRMHelpers(models.Model):
|
||||
class CrmIapLeadHelpers(models.Model):
|
||||
_name = 'crm.iap.lead.helpers'
|
||||
_description = 'Helper methods for crm_iap_mine modules'
|
||||
|
||||
@api.model
|
||||
def notify_no_more_credit(self, service_name, model_name, notification_parameter):
|
||||
def _notify_no_more_credit(self, service_name, model_name, notification_parameter):
|
||||
"""
|
||||
Notify about the number of credit.
|
||||
In order to avoid to spam people each hour, an ir.config_parameter is set
|
||||
|
|
@ -31,26 +31,29 @@ class CRMHelpers(models.Model):
|
|||
|
||||
@api.model
|
||||
def lead_vals_from_response(self, lead_type, team_id, tag_ids, user_id, company_data, people_data):
|
||||
country_id = self.env['res.country'].search([('code', '=', company_data['country_code'])]).id
|
||||
website_url = 'https://www.%s' % company_data['domain'] if company_data['domain'] else False
|
||||
country_id = company_data.get('country_id')
|
||||
if not country_id:
|
||||
country_id = self.env['res.country'].search([('code', '=', company_data['country_code'])]).id
|
||||
website_url = 'https://%s' % company_data['domain'] if company_data.get('domain') else False
|
||||
lead_vals = {
|
||||
# Lead vals from record itself
|
||||
'type': lead_type,
|
||||
'team_id': team_id,
|
||||
'tag_ids': [(6, 0, tag_ids)],
|
||||
'user_id': user_id,
|
||||
'reveal_id': company_data['clearbit_id'],
|
||||
'reveal_id': company_data.get('duns') or company_data.get('clearbit_id', ''),
|
||||
# Lead vals from data
|
||||
'name': company_data['name'] or company_data['domain'],
|
||||
'partner_name': company_data['legal_name'] or company_data['name'],
|
||||
'name': company_data.get('name', '') or company_data.get('domain', ''),
|
||||
'partner_name': company_data.get('name', ''),
|
||||
'email_from': next(iter(company_data.get('email', [])), ''),
|
||||
'phone': company_data['phone'] or (company_data['phone_numbers'] and company_data['phone_numbers'][0]) or '',
|
||||
'phone': company_data.get('phone') or next(iter(company_data.get('phone_numbers', [])), ''),
|
||||
'website': website_url,
|
||||
'street': company_data['location'],
|
||||
'city': company_data['city'],
|
||||
'zip': company_data['postal_code'],
|
||||
'street': company_data.get('street') or company_data.get('location', ''),
|
||||
'street2': company_data.get('street2'),
|
||||
'city': company_data.get('city', ''),
|
||||
'zip': company_data.get('zip') or company_data.get('postal_code', ''),
|
||||
'country_id': country_id,
|
||||
'state_id': self._find_state_id(company_data['state_code'], country_id),
|
||||
'state_id': self._find_state_id(company_data.get('state_code'), country_id),
|
||||
}
|
||||
|
||||
# If type is people then add first contact in lead data
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class CrmIapLeadIndustry(models.Model):
|
|||
color = fields.Integer(string='Color Index')
|
||||
sequence = fields.Integer('Sequence')
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', 'Industry name already exists!'),
|
||||
]
|
||||
_name_uniq = models.Constraint(
|
||||
'unique (name)',
|
||||
'Industry name already exists!',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import api, fields, models, _, release
|
||||
from odoo.addons.iap.tools import iap_tools
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import is_html_empty
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ CREDIT_PER_COMPANY = 1
|
|||
CREDIT_PER_CONTACT = 1
|
||||
|
||||
|
||||
class CRMLeadMiningRequest(models.Model):
|
||||
class CrmIapLeadMiningRequest(models.Model):
|
||||
_name = 'crm.iap.lead.mining.request'
|
||||
_description = 'CRM Lead Mining Request'
|
||||
|
||||
|
|
@ -46,7 +47,6 @@ class CRMLeadMiningRequest(models.Model):
|
|||
# Lead / Opportunity Data
|
||||
|
||||
lead_type = fields.Selection([('lead', 'Leads'), ('opportunity', 'Opportunities')], string='Type', required=True, default=_default_lead_type)
|
||||
display_lead_label = fields.Char(compute='_compute_display_lead_label')
|
||||
team_id = fields.Many2one(
|
||||
'crm.team', string='Sales Team', ondelete="set null",
|
||||
domain="[('use_opportunities', '=', True)]", readonly=False, compute='_compute_team_id', store=True)
|
||||
|
|
@ -76,36 +76,32 @@ class CRMLeadMiningRequest(models.Model):
|
|||
lead_contacts_credits = fields.Char(compute='_compute_tooltip', readonly=True)
|
||||
lead_total_credits = fields.Char(compute='_compute_tooltip', readonly=True)
|
||||
|
||||
@api.depends('lead_type', 'lead_number')
|
||||
def _compute_display_lead_label(self):
|
||||
selection_description_values = {
|
||||
e[0]: e[1] for e in self._fields['lead_type']._description_selection(self.env)}
|
||||
for request in self:
|
||||
lead_type = selection_description_values[request.lead_type]
|
||||
request.display_lead_label = '%s %s' % (request.lead_number, lead_type)
|
||||
|
||||
|
||||
@api.onchange('lead_number', 'contact_number')
|
||||
def _compute_tooltip(self):
|
||||
for record in self:
|
||||
company_credits = CREDIT_PER_COMPANY * record.lead_number
|
||||
contact_credits = CREDIT_PER_CONTACT * record.contact_number
|
||||
total_contact_credits = contact_credits * record.lead_number
|
||||
record.lead_contacts_credits = _("Up to %d additional credits will be consumed to identify %d contacts per company.") % (contact_credits*company_credits, record.contact_number)
|
||||
record.lead_credits = _('%d credits will be consumed to find %d companies.') % (company_credits, record.lead_number)
|
||||
record.lead_total_credits = _("This makes a total of %d credits for this request.") % (total_contact_credits + company_credits)
|
||||
record.lead_contacts_credits = _(
|
||||
"Up to %(credit_count)d additional credits will be consumed to identify %(contact_count)d contacts per company.",
|
||||
credit_count=contact_credits * company_credits,
|
||||
contact_count=record.contact_number,
|
||||
)
|
||||
record.lead_credits = _(
|
||||
"%(credit_count)d credits will be consumed to find %(company_count)d companies.",
|
||||
credit_count=company_credits,
|
||||
company_count=record.lead_number,
|
||||
)
|
||||
record.lead_total_credits = _("This makes a total of %d credits for this request.", total_contact_credits + company_credits)
|
||||
|
||||
@api.depends('lead_ids.lead_mining_request_id')
|
||||
def _compute_lead_count(self):
|
||||
if self.ids:
|
||||
leads_data = self.env['crm.lead']._read_group(
|
||||
[('lead_mining_request_id', 'in', self.ids)],
|
||||
['lead_mining_request_id'], ['lead_mining_request_id'])
|
||||
else:
|
||||
leads_data = []
|
||||
mapped_data = dict(
|
||||
(m['lead_mining_request_id'][0], m['lead_mining_request_id_count'])
|
||||
for m in leads_data)
|
||||
leads_data = self.env['crm.lead']._read_group(
|
||||
[('lead_mining_request_id', 'in', self.ids)],
|
||||
['lead_mining_request_id'], ['__count'])
|
||||
mapped_data = {
|
||||
lead_mining_request.id: count
|
||||
for lead_mining_request, count in leads_data}
|
||||
for request in self:
|
||||
request.lead_count = mapped_data.get(request.id, 0)
|
||||
|
||||
|
|
@ -185,21 +181,30 @@ class CRMLeadMiningRequest(models.Model):
|
|||
self.company_size_max = self.company_size_min
|
||||
|
||||
@api.model
|
||||
def get_empty_list_help(self, help_string):
|
||||
def get_empty_list_help(self, help_message):
|
||||
if not is_html_empty(help_message):
|
||||
return help_message
|
||||
|
||||
help_title = _('Create a Lead Mining Request')
|
||||
sub_title = _('Generate new leads based on their country, industry, size, etc.')
|
||||
return '<p class="o_view_nocontent_smiling_face">%s</p><p class="oe_view_nocontent_alias">%s</p>' % (help_title, sub_title)
|
||||
return super().get_empty_list_help(
|
||||
f'<p class="o_view_nocontent_smiling_face">{help_title}</p><p class="oe_view_nocontent_alias">{sub_title}</p>'
|
||||
)
|
||||
|
||||
def _prepare_iap_payload(self):
|
||||
"""
|
||||
This will prepare the data to send to the server
|
||||
"""
|
||||
self.ensure_one()
|
||||
payload = {'lead_number': self.lead_number,
|
||||
'search_type': self.search_type,
|
||||
'countries': self.country_ids.mapped('code')}
|
||||
if self.state_ids:
|
||||
payload['states'] = self.state_ids.mapped('code')
|
||||
payload = {
|
||||
'lead_number': self.lead_number,
|
||||
'search_type': self.search_type,
|
||||
'countries': [{
|
||||
'code': country.code,
|
||||
'states': self.state_ids.filtered(lambda state: state in country.state_ids).mapped('code'),
|
||||
} for country in self.country_ids],
|
||||
}
|
||||
|
||||
if self.filter_on_size:
|
||||
payload.update({'company_size_min': self.company_size_min,
|
||||
'company_size_max': self.company_size_max})
|
||||
|
|
@ -232,27 +237,34 @@ class CRMLeadMiningRequest(models.Model):
|
|||
server_payload = self._prepare_iap_payload()
|
||||
reveal_account = self.env['iap.account'].get('reveal')
|
||||
dbuuid = self.env['ir.config_parameter'].sudo().get_param('database.uuid')
|
||||
reveal_ids = [lead['reveal_id'] for lead in self.env['crm.lead'].search_read([('reveal_id', '!=', False)], ['reveal_id'])]
|
||||
params = {
|
||||
'account_token': reveal_account.account_token,
|
||||
'dbuuid': dbuuid,
|
||||
'data': server_payload
|
||||
'account_token': reveal_account.sudo().account_token,
|
||||
'db_uuid': dbuuid,
|
||||
'query': server_payload,
|
||||
'db_version': release.version,
|
||||
'db_lang': self.env.lang,
|
||||
'country_code': self.env.company.country_id.code,
|
||||
'reveal_ids': reveal_ids,
|
||||
}
|
||||
try:
|
||||
response = self._iap_contact_mining(params, timeout=300)
|
||||
|
||||
if response.get('credit_error'):
|
||||
self.error_type = 'credits'
|
||||
self.state = 'error'
|
||||
return False
|
||||
|
||||
if not response.get('data'):
|
||||
self.error_type = 'no_result'
|
||||
return False
|
||||
|
||||
return response['data']
|
||||
except iap_tools.InsufficientCreditError as e:
|
||||
self.error_type = 'credits'
|
||||
self.state = 'error'
|
||||
return False
|
||||
except Exception as e:
|
||||
raise UserError(_("Your request could not be executed: %s", e))
|
||||
|
||||
def _iap_contact_mining(self, params, timeout=300):
|
||||
endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/lead_mining_request'
|
||||
endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/api/dnb/1/search_by_criteria'
|
||||
return iap_tools.iap_jsonrpc(endpoint, params=params, timeout=timeout)
|
||||
|
||||
def _create_leads_from_response(self, result):
|
||||
|
|
@ -261,25 +273,33 @@ class CRMLeadMiningRequest(models.Model):
|
|||
lead_vals_list = []
|
||||
messages_to_post = {}
|
||||
for data in result:
|
||||
country = self.env['res.country'].search([('code', '=', data['country_code'])])
|
||||
lead_vals_list.append(self._lead_vals_from_response(data))
|
||||
|
||||
template_values = data['company_data']
|
||||
template_values = data
|
||||
template_values.update({
|
||||
'flavor_text': _("Opportunity created by Odoo Lead Generation"),
|
||||
'people_data': data.get('people_data'),
|
||||
'country': country.name,
|
||||
'zip_code': data.get('zip'),
|
||||
'country_id': country.id,
|
||||
})
|
||||
messages_to_post[data['company_data']['clearbit_id']] = template_values
|
||||
messages_to_post[data['duns']] = template_values
|
||||
leads = self.env['crm.lead'].create(lead_vals_list)
|
||||
for lead in leads:
|
||||
if messages_to_post.get(lead.reveal_id):
|
||||
lead.message_post_with_view('iap_mail.enrich_company', values=messages_to_post[lead.reveal_id], subtype_id=self.env.ref('mail.mt_note').id)
|
||||
lead.message_post_with_source(
|
||||
'iap_mail.enrich_company',
|
||||
render_values=messages_to_post[lead.reveal_id],
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
|
||||
# Methods responsible for format response data into valid odoo lead data
|
||||
@api.model
|
||||
def _lead_vals_from_response(self, data):
|
||||
self.ensure_one()
|
||||
company_data = data.get('company_data')
|
||||
people_data = data.get('people_data')
|
||||
company_data = data
|
||||
people_data = []
|
||||
lead_vals = self.env['crm.iap.lead.helpers'].lead_vals_from_response(self.lead_type, self.team_id.id, self.tag_ids.ids, self.user_id.id, company_data, people_data)
|
||||
lead_vals['lead_mining_request_id'] = self.id
|
||||
return lead_vals
|
||||
|
|
@ -313,7 +333,7 @@ class CRMLeadMiningRequest(models.Model):
|
|||
'target': 'new',
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_id': self.id,
|
||||
'context': dict(self.env.context, edit=True, form_view_initial_mode='edit')
|
||||
'context': dict(self.env.context, edit=True)
|
||||
}
|
||||
else:
|
||||
# will reload the form view and show the error message on top
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PeopleRole(models.Model):
|
||||
class CrmIapLeadRole(models.Model):
|
||||
""" CRM Reveal People Roles for People """
|
||||
_name = 'crm.iap.lead.role'
|
||||
_description = 'People Role'
|
||||
|
|
@ -13,10 +13,11 @@ class PeopleRole(models.Model):
|
|||
reveal_id = fields.Char(required=True)
|
||||
color = fields.Integer(string='Color Index')
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', 'Role name already exists!'),
|
||||
]
|
||||
_name_uniq = models.Constraint(
|
||||
'unique (name)',
|
||||
'Role name already exists!',
|
||||
)
|
||||
|
||||
@api.depends('name')
|
||||
def name_get(self):
|
||||
return [(role.id, role.name.replace('_', ' ').title()) for role in self]
|
||||
def _compute_display_name(self):
|
||||
for role in self:
|
||||
role.display_name = (role.name or '').replace('_', ' ').title()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PeopleSeniority(models.Model):
|
||||
class CrmIapLeadSeniority(models.Model):
|
||||
""" Seniority for People Rules """
|
||||
_name = 'crm.iap.lead.seniority'
|
||||
_description = 'People Seniority'
|
||||
|
|
@ -12,10 +12,12 @@ class PeopleSeniority(models.Model):
|
|||
name = fields.Char(string='Name', required=True, translate=True)
|
||||
reveal_id = fields.Char(required=True)
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', 'Name already exists!'),
|
||||
]
|
||||
_name_uniq = models.Constraint(
|
||||
'unique (name)',
|
||||
'Name already exists!',
|
||||
)
|
||||
|
||||
@api.depends('name')
|
||||
def name_get(self):
|
||||
return [(seniority.id, seniority.name.replace('_', ' ').title()) for seniority in self]
|
||||
def _compute_display_name(self):
|
||||
for seniority in self:
|
||||
seniority.display_name = (seniority.name or '').replace('_', ' ').title()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class Lead(models.Model):
|
||||
class CrmLead(models.Model):
|
||||
_inherit = 'crm.lead'
|
||||
|
||||
lead_mining_request_id = fields.Many2one('crm.iap.lead.mining.request', string='Lead Mining Request', index='btree_not_null')
|
||||
|
||||
def _merge_get_fields(self):
|
||||
return super(Lead, self)._merge_get_fields() + ['lead_mining_request_id']
|
||||
return super()._merge_get_fields() + ['lead_mining_request_id']
|
||||
|
||||
def action_generate_leads(self):
|
||||
return {
|
||||
"name": _("Need help reaching your target?"),
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "crm.iap.lead.mining.request",
|
||||
"target": "new",
|
||||
"views": [[False, "form"]],
|
||||
"context": {"is_modal": True},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue