[MERGE] crm_iap_*: rename and reorder modules

PURPOSE

Perform a global renaming / cleaning of IAP features often added or merged
with minimal review. Time to cleanup !

SPECIFICATIONS

Rename ``crm_iap_lead_enrich`` to ``crm_iap_enrich`` . Lead naming is not
really required as it is a bridge build on ``crm``.

Rename ``crm_iap_lead_website`` to ``website_crm_iap_reveal``. This module
is an addition to ``website_crm``, notably using visitor based information
to generate leads based on rules.

Rename ``crm_iap_lead`` to ``crm_iap_mine`` . Indeed it adds lead mining
feature on top of crm.

Reorganize addons according to guidelines, notably: split python, views and
data files, rename them according to their content. Globally rename and lint
main code bits.

Add some tests for lead mining and reveal. Provide some light fixes spotted
during code reading.

No functional change should occur with this merge. It contains only code
move and renaming.

LINKS

Task-2630969
Prepares Task-2600047 (code improvements and cleaning)

closes odoo/odoo#75514

Related: odoo/enterprise#20424
Related: odoo/upgrade#2770
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Odoo's Mergebot
2021-08-25 19:48:25 +02:00
committed by GitHub
155 changed files with 907 additions and 227 deletions
+11 -11
View File
@@ -212,19 +212,14 @@ file_filter = addons/crm/i18n/<lang>.po
source_file = addons/crm/i18n/crm.pot
source_lang = en
[odoo-master.crm_iap_lead]
file_filter = addons/crm_iap_lead/i18n/<lang>.po
source_file = addons/crm_iap_lead/i18n/crm_iap_lead.pot
[odoo-master.crm_iap_enrich]
file_filter = addons/crm_iap_enrich/i18n/<lang>.po
source_file = addons/crm_iap_enrich/i18n/crm_iap_enrich.pot
source_lang = en
[odoo-master.crm_iap_lead_enrich]
file_filter = addons/crm_iap_lead_enrich/i18n/<lang>.po
source_file = addons/crm_iap_lead_enrich/i18n/crm_iap_lead_enrich.pot
source_lang = en
[odoo-master.crm_iap_lead_website]
file_filter = addons/crm_iap_lead_website/i18n/<lang>.po
source_file = addons/crm_iap_lead_website/i18n/crm_iap_lead_website.pot
[odoo-master.crm_iap_mine]
file_filter = addons/crm_iap_mine/i18n/<lang>.po
source_file = addons/crm_iap_mine/i18n/crm_iap_mine.pot
source_lang = en
[odoo-master.crm_livechat]
@@ -1007,6 +1002,11 @@ file_filter = addons/website_crm/i18n/<lang>.po
source_file = addons/website_crm/i18n/website_crm.pot
source_lang = en
[odoo-master.website_crm_iap_reveal]
file_filter = addons/website_crm_iap_reveal/i18n/<lang>.po
source_file = addons/website_crm_iap_reveal/i18n/website_crm_iap_reveal.pot
source_lang = en
[odoo-master.website_crm_livechat]
file_filter = addons/website_crm_livechat/i18n/<lang>.po
source_file = addons/website_crm_livechat/i18n/website_crm_livechat.pot
+3 -3
View File
@@ -36,9 +36,9 @@ class ResConfigSettings(models.TransientModel):
string="Auto Assignment Next Execution Date", compute='_compute_crm_auto_assignment_data',
readonly=False, store=True)
# IAP
module_crm_iap_lead = fields.Boolean("Generate new leads based on their country, industries, size, etc.")
module_crm_iap_lead_website = fields.Boolean("Create Leads/Opportunities from your website's traffic")
module_crm_iap_lead_enrich = fields.Boolean("Enrich your leads automatically with company data based on their email address.")
module_crm_iap_mine = fields.Boolean("Generate new leads based on their country, industries, size, etc.")
module_crm_iap_enrich = fields.Boolean("Enrich your leads automatically with company data based on their email address.")
module_website_crm_iap_reveal = fields.Boolean("Create Leads/Opportunities from your website's traffic")
lead_enrich_auto = fields.Selection([
('manual', 'Enrich leads on demand only'),
('auto', 'Enrich all leads automatically'),
+11 -13
View File
@@ -121,29 +121,27 @@
<div class="row mt16 o_settings_container" name="convert_visitor_setting_container">
<div class="col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_crm_iap_lead_enrich"/>
<field name="module_crm_iap_enrich"/>
</div>
<div class="o_setting_right_pane" id="crm_iap_lead_enrich">
<label string="Lead Enrichment" for="module_crm_iap_lead_enrich"/>
<div class="o_setting_right_pane" id="crm_iap_enrich_settings">
<label string="Lead Enrichment" for="module_crm_iap_enrich"/>
<div class="text-muted">
Enrich your leads automatically with company data based on their email address
</div>
<div id="crm_iap_lead_enrich">
<div class="mt8" attrs="{'invisible': [('module_crm_iap_lead_enrich','=',False)]}">
<field name="lead_enrich_auto" class="o_light_label" widget="radio" required="True"/>
</div>
<div class="mt8" attrs="{'invisible': [('module_crm_iap_enrich','=',False)]}">
<field name="lead_enrich_auto" class="o_light_label" widget="radio" required="True"/>
</div>
</div>
</div>
<div class="col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_crm_iap_lead"/>
<field name="module_crm_iap_mine"/>
</div>
<div class="o_setting_right_pane" id="crm_iap_lead_settings">
<label string="Lead Mining" for="module_crm_iap_lead"/>
<div class="o_setting_right_pane" id="crm_iap_mine_settings">
<label string="Lead Mining" for="module_crm_iap_mine"/>
<a href="https://www.odoo.com/documentation/14.0/applications/sales/crm/acquire_leads/lead_mining.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Generate new leads based on their country, industry, size, etc.
@@ -155,11 +153,11 @@
<div class="row mt16 o_settings_container" name="generate_lead_setting_container">
<div class="col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_crm_iap_lead_website"/>
<field name="module_website_crm_iap_reveal"/>
</div>
<div class="o_setting_right_pane" id="crm_iap_lead_website_settings">
<label string="Visits to Leads" for="module_crm_iap_lead_website"/>
<div class="o_setting_right_pane" id="website_crm_iap_reveal_settings">
<label string="Visits to Leads" for="module_website_crm_iap_reveal"/>
<div class="text-muted">
Convert visitors of your website into leads and perform data enrichment based on their IP address
</div>
@@ -8,7 +8,7 @@ from odoo.api import Environment, SUPERUSER_ID
def _synchronize_cron(cr, registry):
env = Environment(cr, SUPERUSER_ID, {'active_test': False})
cron = env.ref('crm_iap_lead_enrich.ir_cron_lead_enrichment')
cron = env.ref('crm_iap_enrich.ir_cron_lead_enrichment')
if cron:
config = env['ir.config_parameter'].get_param('crm.iap.lead.enrich.setting', 'manual')
cron.active = config != 'manual'
@@ -59,7 +59,7 @@ class Lead(models.Model):
normalized_email = tools.email_normalize(lead.email_from)
if not normalized_email:
lead.message_post_with_view(
'crm_iap_lead_enrich.mail_message_lead_enrich_no_email',
'crm_iap_enrich.mail_message_lead_enrich_no_email',
subtype_id=self.env.ref('mail.mt_note').id)
continue
@@ -68,7 +68,7 @@ class Lead(models.Model):
if email_domain in iap_tools._MAIL_DOMAIN_BLACKLIST:
lead.write({'iap_enrich_done': True})
lead.message_post_with_view(
'crm_iap_lead_enrich.mail_message_lead_enrich_notfound',
'crm_iap_enrich.mail_message_lead_enrich_notfound',
subtype_id=self.env.ref('mail.mt_note').id)
else:
lead_emails[lead.id] = email_domain
@@ -83,7 +83,7 @@ class Lead(models.Model):
'url': self.env['iap.account'].get_credits_url('reveal'),
}
leads[0].message_post_with_view(
'crm_iap_lead_enrich.mail_message_lead_enrich_no_credit',
'crm_iap_enrich.mail_message_lead_enrich_no_credit',
values=data,
subtype_id=self.env.ref('mail.mt_note').id)
# Since there are no credits left, there is no point to process the other batches
@@ -110,7 +110,7 @@ class Lead(models.Model):
iap_data = iap_response.get(str(lead.id))
if not iap_data:
lead.write({'iap_enrich_done': True})
lead.message_post_with_view('crm_iap_lead_enrich.mail_message_lead_enrich_notfound', subtype_id=self.env.ref('mail.mt_note').id)
lead.message_post_with_view('crm_iap_enrich.mail_message_lead_enrich_notfound', subtype_id=self.env.ref('mail.mt_note').id)
continue
values = {'iap_enrich_done': True}
@@ -10,12 +10,12 @@ class ResConfigSettings(models.TransientModel):
@api.model
def get_values(self):
values = super(ResConfigSettings, self).get_values()
cron = self.sudo().with_context(active_test=False).env.ref('crm_iap_lead_enrich.ir_cron_lead_enrichment', raise_if_not_found=False)
cron = self.sudo().with_context(active_test=False).env.ref('crm_iap_enrich.ir_cron_lead_enrichment', raise_if_not_found=False)
values['lead_enrich_auto'] = 'auto' if cron and cron.active else 'manual'
return values
def set_values(self):
super(ResConfigSettings, self).set_values()
cron = self.sudo().with_context(active_test=False).env.ref('crm_iap_lead_enrich.ir_cron_lead_enrichment', raise_if_not_found=False)
cron = self.sudo().with_context(active_test=False).env.ref('crm_iap_enrich.ir_cron_lead_enrichment', raise_if_not_found=False)
if cron:
cron.active = self.lead_enrich_auto == 'auto'
@@ -2,7 +2,7 @@
<data>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">crm_iap_lead_enrich rechargement</field>
<field name="name">res.config.settings.view.form.inherit.crm.iap.enrich</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="crm.res_config_settings_view_form"/>
<field name="arch" type="xml">
@@ -1,24 +0,0 @@
"id",name,reveal_ids,sequence
"crm_iap_lead_industry_30_155","Consumer Discretionary","30,155",1
"crm_iap_lead_industry_33","Consumer Staples","33",4
"crm_iap_lead_industry_69_157","Banks & Insurance","69,157",2
"crm_iap_lead_industry_86","Media","86",7
"crm_iap_lead_industry_114","Real Estate","114",21
"crm_iap_lead_industry_136","Transportation","136",16
"crm_iap_lead_industry_138_156","Energy & Utilities ","138",22
"crm_iap_lead_industry_148","Materials","148",17
"crm_iap_lead_industry_149","Telecommunication Services","149",20
"crm_iap_lead_industry_150_151","Consumer Services","150,151",9
"crm_iap_lead_industry_152","Retailing","152",3
"crm_iap_lead_industry_153_154","Food, Beverage & Tobacco","153,154",12
"crm_iap_lead_industry_158_159","Diversified Financials & Financial Services","158,159",15
"crm_iap_lead_industry_160","Health Care Equipment & Services","160",11
"crm_iap_lead_industry_161","Pharmaceuticals, Biotechnology & Life Sciences","161",13
"crm_iap_lead_industry_162","Capital Goods","162",6
"crm_iap_lead_industry_163","Commercial & Professional Services","163",5
"crm_iap_lead_industry_165","Software & Services","165",8
"crm_iap_lead_industry_166","Technology Hardware & Equipment","166",19
"crm_iap_lead_industry_167","Construction Materials","167",23
"crm_iap_lead_industry_168","Independent Power and Renewable Electricity Producers","168",14
"crm_iap_lead_industry_238","Automobiles & Components","238",18
"crm_iap_lead_industry_239","Consumer Durables & Apparel","239",10
1 id name reveal_ids sequence
2 crm_iap_lead_industry_30_155 Consumer Discretionary 30,155 1
3 crm_iap_lead_industry_33 Consumer Staples 33 4
4 crm_iap_lead_industry_69_157 Banks & Insurance 69,157 2
5 crm_iap_lead_industry_86 Media 86 7
6 crm_iap_lead_industry_114 Real Estate 114 21
7 crm_iap_lead_industry_136 Transportation 136 16
8 crm_iap_lead_industry_138_156 Energy & Utilities 138 22
9 crm_iap_lead_industry_148 Materials 148 17
10 crm_iap_lead_industry_149 Telecommunication Services 149 20
11 crm_iap_lead_industry_150_151 Consumer Services 150,151 9
12 crm_iap_lead_industry_152 Retailing 152 3
13 crm_iap_lead_industry_153_154 Food, Beverage & Tobacco 153,154 12
14 crm_iap_lead_industry_158_159 Diversified Financials & Financial Services 158,159 15
15 crm_iap_lead_industry_160 Health Care Equipment & Services 160 11
16 crm_iap_lead_industry_161 Pharmaceuticals, Biotechnology & Life Sciences 161 13
17 crm_iap_lead_industry_162 Capital Goods 162 6
18 crm_iap_lead_industry_163 Commercial & Professional Services 163 5
19 crm_iap_lead_industry_165 Software & Services 165 8
20 crm_iap_lead_industry_166 Technology Hardware & Equipment 166 19
21 crm_iap_lead_industry_167 Construction Materials 167 23
22 crm_iap_lead_industry_168 Independent Power and Renewable Electricity Producers 168 14
23 crm_iap_lead_industry_238 Automobiles & Components 238 18
24 crm_iap_lead_industry_239 Consumer Durables & Apparel 239 10
@@ -1,23 +0,0 @@
"id",name,reveal_id
"crm_iap_lead_role_1","CEO","CEO"
"crm_iap_lead_role_2","communications","communications"
"crm_iap_lead_role_3","consulting","consulting"
"crm_iap_lead_role_4","customer_service","customer_service"
"crm_iap_lead_role_5","education","education"
"crm_iap_lead_role_6","engineering","engineering"
"crm_iap_lead_role_7","finance","finance"
"crm_iap_lead_role_8","founder","founder"
"crm_iap_lead_role_9","health_professional","health_professional"
"crm_iap_lead_role_10","human_resources","human_resources"
"crm_iap_lead_role_11","information_technology","information_technology"
"crm_iap_lead_role_12","legal","legal"
"crm_iap_lead_role_13","marketing","marketing"
"crm_iap_lead_role_14","operations","operations"
"crm_iap_lead_role_15","owner","owner"
"crm_iap_lead_role_16","president","president"
"crm_iap_lead_role_17","product","product"
"crm_iap_lead_role_18","public_relations","public_relations"
"crm_iap_lead_role_19","real_estate","real_estate"
"crm_iap_lead_role_20","recruiting","recruiting"
"crm_iap_lead_role_21","research","research"
"crm_iap_lead_role_22","sale","sale"
1 id name reveal_id
2 crm_iap_lead_role_1 CEO CEO
3 crm_iap_lead_role_2 communications communications
4 crm_iap_lead_role_3 consulting consulting
5 crm_iap_lead_role_4 customer_service customer_service
6 crm_iap_lead_role_5 education education
7 crm_iap_lead_role_6 engineering engineering
8 crm_iap_lead_role_7 finance finance
9 crm_iap_lead_role_8 founder founder
10 crm_iap_lead_role_9 health_professional health_professional
11 crm_iap_lead_role_10 human_resources human_resources
12 crm_iap_lead_role_11 information_technology information_technology
13 crm_iap_lead_role_12 legal legal
14 crm_iap_lead_role_13 marketing marketing
15 crm_iap_lead_role_14 operations operations
16 crm_iap_lead_role_15 owner owner
17 crm_iap_lead_role_16 president president
18 crm_iap_lead_role_17 product product
19 crm_iap_lead_role_18 public_relations public_relations
20 crm_iap_lead_role_19 real_estate real_estate
21 crm_iap_lead_role_20 recruiting recruiting
22 crm_iap_lead_role_21 research research
23 crm_iap_lead_role_22 sale sale
@@ -1,4 +0,0 @@
"id",name,reveal_id
"crm_iap_lead_seniority_1","director","director"
"crm_iap_lead_seniority_2","executive","executive"
"crm_iap_lead_seniority_3","manager","manager"
1 id name reveal_id
2 crm_iap_lead_seniority_1 director director
3 crm_iap_lead_seniority_2 executive executive
4 crm_iap_lead_seniority_3 manager manager
@@ -17,18 +17,19 @@
'data/mail_template_data.xml',
'data/ir_sequence_data.xml',
'security/ir.model.access.csv',
'views/crm_lead_view.xml',
'views/crm_iap_lead_views.xml',
'views/crm_lead_views.xml',
'views/crm_iap_lead_mining_request_views.xml',
'views/res_config_settings_views.xml',
'views/mail_templates.xml',
'views/crm_menus.xml',
],
'auto_install': True,
'assets': {
'web.assets_backend': [
'crm_iap_lead/static/src/js/**/*',
'crm_iap_mine/static/src/js/**/*',
],
'web.assets_qweb': [
'crm_iap_lead/static/src/xml/**/*',
'crm_iap_mine/static/src/xml/**/*',
],
},
'license': 'LGPL-3',
@@ -0,0 +1,24 @@
"id",name,reveal_ids,sequence
"crm_iap_mine_industry_30_155","Consumer Discretionary","30,155",1
"crm_iap_mine_industry_33","Consumer Staples","33",4
"crm_iap_mine_industry_69_157","Banks & Insurance","69,157",2
"crm_iap_mine_industry_86","Media","86",7
"crm_iap_mine_industry_114","Real Estate","114",21
"crm_iap_mine_industry_136","Transportation","136",16
"crm_iap_mine_industry_138_156","Energy & Utilities ","138",22
"crm_iap_mine_industry_148","Materials","148",17
"crm_iap_mine_industry_149","Telecommunication Services","149",20
"crm_iap_mine_industry_150_151","Consumer Services","150,151",9
"crm_iap_mine_industry_152","Retailing","152",3
"crm_iap_mine_industry_153_154","Food, Beverage & Tobacco","153,154",12
"crm_iap_mine_industry_158_159","Diversified Financials & Financial Services","158,159",15
"crm_iap_mine_industry_160","Health Care Equipment & Services","160",11
"crm_iap_mine_industry_161","Pharmaceuticals, Biotechnology & Life Sciences","161",13
"crm_iap_mine_industry_162","Capital Goods","162",6
"crm_iap_mine_industry_163","Commercial & Professional Services","163",5
"crm_iap_mine_industry_165","Software & Services","165",8
"crm_iap_mine_industry_166","Technology Hardware & Equipment","166",19
"crm_iap_mine_industry_167","Construction Materials","167",23
"crm_iap_mine_industry_168","Independent Power and Renewable Electricity Producers","168",14
"crm_iap_mine_industry_238","Automobiles & Components","238",18
"crm_iap_mine_industry_239","Consumer Durables & Apparel","239",10
1 id name reveal_ids sequence
2 crm_iap_mine_industry_30_155 Consumer Discretionary 30,155 1
3 crm_iap_mine_industry_33 Consumer Staples 33 4
4 crm_iap_mine_industry_69_157 Banks & Insurance 69,157 2
5 crm_iap_mine_industry_86 Media 86 7
6 crm_iap_mine_industry_114 Real Estate 114 21
7 crm_iap_mine_industry_136 Transportation 136 16
8 crm_iap_mine_industry_138_156 Energy & Utilities 138 22
9 crm_iap_mine_industry_148 Materials 148 17
10 crm_iap_mine_industry_149 Telecommunication Services 149 20
11 crm_iap_mine_industry_150_151 Consumer Services 150,151 9
12 crm_iap_mine_industry_152 Retailing 152 3
13 crm_iap_mine_industry_153_154 Food, Beverage & Tobacco 153,154 12
14 crm_iap_mine_industry_158_159 Diversified Financials & Financial Services 158,159 15
15 crm_iap_mine_industry_160 Health Care Equipment & Services 160 11
16 crm_iap_mine_industry_161 Pharmaceuticals, Biotechnology & Life Sciences 161 13
17 crm_iap_mine_industry_162 Capital Goods 162 6
18 crm_iap_mine_industry_163 Commercial & Professional Services 163 5
19 crm_iap_mine_industry_165 Software & Services 165 8
20 crm_iap_mine_industry_166 Technology Hardware & Equipment 166 19
21 crm_iap_mine_industry_167 Construction Materials 167 23
22 crm_iap_mine_industry_168 Independent Power and Renewable Electricity Producers 168 14
23 crm_iap_mine_industry_238 Automobiles & Components 238 18
24 crm_iap_mine_industry_239 Consumer Durables & Apparel 239 10
@@ -0,0 +1,23 @@
"id",name,reveal_id
"crm_iap_mine_role_1","CEO","CEO"
"crm_iap_mine_role_2","communications","communications"
"crm_iap_mine_role_3","consulting","consulting"
"crm_iap_mine_role_4","customer_service","customer_service"
"crm_iap_mine_role_5","education","education"
"crm_iap_mine_role_6","engineering","engineering"
"crm_iap_mine_role_7","finance","finance"
"crm_iap_mine_role_8","founder","founder"
"crm_iap_mine_role_9","health_professional","health_professional"
"crm_iap_mine_role_10","human_resources","human_resources"
"crm_iap_mine_role_11","information_technology","information_technology"
"crm_iap_mine_role_12","legal","legal"
"crm_iap_mine_role_13","marketing","marketing"
"crm_iap_mine_role_14","operations","operations"
"crm_iap_mine_role_15","owner","owner"
"crm_iap_mine_role_16","president","president"
"crm_iap_mine_role_17","product","product"
"crm_iap_mine_role_18","public_relations","public_relations"
"crm_iap_mine_role_19","real_estate","real_estate"
"crm_iap_mine_role_20","recruiting","recruiting"
"crm_iap_mine_role_21","research","research"
"crm_iap_mine_role_22","sale","sale"
1 id name reveal_id
2 crm_iap_mine_role_1 CEO CEO
3 crm_iap_mine_role_2 communications communications
4 crm_iap_mine_role_3 consulting consulting
5 crm_iap_mine_role_4 customer_service customer_service
6 crm_iap_mine_role_5 education education
7 crm_iap_mine_role_6 engineering engineering
8 crm_iap_mine_role_7 finance finance
9 crm_iap_mine_role_8 founder founder
10 crm_iap_mine_role_9 health_professional health_professional
11 crm_iap_mine_role_10 human_resources human_resources
12 crm_iap_mine_role_11 information_technology information_technology
13 crm_iap_mine_role_12 legal legal
14 crm_iap_mine_role_13 marketing marketing
15 crm_iap_mine_role_14 operations operations
16 crm_iap_mine_role_15 owner owner
17 crm_iap_mine_role_16 president president
18 crm_iap_mine_role_17 product product
19 crm_iap_mine_role_18 public_relations public_relations
20 crm_iap_mine_role_19 real_estate real_estate
21 crm_iap_mine_role_20 recruiting recruiting
22 crm_iap_mine_role_21 research research
23 crm_iap_mine_role_22 sale sale
@@ -0,0 +1,4 @@
"id",name,reveal_id
"crm_iap_mine_seniority_1","director","director"
"crm_iap_mine_seniority_2","executive","executive"
"crm_iap_mine_seniority_3","manager","manager"
1 id name reveal_id
2 crm_iap_mine_seniority_1 director director
3 crm_iap_mine_seniority_2 executive executive
4 crm_iap_mine_seniority_3 manager manager
@@ -2,7 +2,7 @@
<odoo>
<data noupdate="1">
<!-- Sequences for lead mining requests -->
<record id="seq_crm_iap_lead_mining_request" model="ir.sequence">
<record id="ir_sequence_crm_iap_mine" model="ir.sequence">
<field name="name">Lead Mining Request</field>
<field name="code">crm.iap.lead.mining.request</field>
<field name="prefix">LMR</field>
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import crm_lead
from . import crm_iap_lead
from . import crm_iap_lead_helpers
from . import crm_iap_lead_industry
from . import crm_iap_lead_role
from . import crm_iap_lead_seniority
from . import crm_iap_lead_mining_request
@@ -4,7 +4,7 @@ from odoo import api, models
class CRMHelpers(models.Model):
_name = 'crm.iap.lead.helpers'
_description = 'Helper methods for crm_iap_lead modules'
_description = 'Helper methods for crm_iap_mine modules'
@api.model
def notify_no_more_credit(self, service_name, model_name, notification_parameter):
@@ -15,7 +15,7 @@ class CRMHelpers(models.Model):
already_notified = self.env['ir.config_parameter'].sudo().get_param(notification_parameter, False)
if already_notified:
return
mail_template = self.env.ref('crm_iap_lead.lead_generation_no_credits')
mail_template = self.env.ref('crm_iap_mine.lead_generation_no_credits')
iap_account = self.env['iap.account'].search([('service_name', '=', service_name)], limit=1)
# Get the email address of the creators of the records
res = self.env[model_name].search_read([], ['create_uid'])
@@ -184,7 +184,13 @@ class CRMLeadMiningRequest(models.Model):
def _onchange_company_size_max(self):
if self.company_size_max < self.company_size_min:
self.company_size_max = self.company_size_min
@api.model
def get_empty_list_help(self, help_string):
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)
def _prepare_iap_payload(self):
"""
This will prepare the data to send to the server
@@ -227,14 +233,13 @@ 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')
endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/lead_mining_request'
params = {
'account_token': reveal_account.account_token,
'dbuuid': dbuuid,
'data': server_payload
}
try:
response = iap_tools.iap_jsonrpc(endpoint, params=params, timeout=300)
response = self._iap_contact_mining(params, timeout=300)
if not response.get('data'):
self.error_type = 'no_result'
return False
@@ -247,6 +252,10 @@ class CRMLeadMiningRequest(models.Model):
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'
return iap_tools.iap_jsonrpc(endpoint, params=params, timeout=timeout)
def _create_leads_from_response(self, result):
""" This method will get the response from the service and create the leads accordingly """
self.ensure_one()
@@ -276,12 +285,6 @@ class CRMLeadMiningRequest(models.Model):
lead_vals['lead_mining_request_id'] = self.id
return lead_vals
@api.model
def get_empty_list_help(self, help):
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)
def action_draft(self):
self.ensure_one()
self.name = _('New')
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class PeopleSeniority(models.Model):
""" Seniority for People Rules """
_name = 'crm.iap.lead.seniority'
_description = 'People Seniority'
name = fields.Char(string='Name', required=True, translate=True)
reveal_id = fields.Char(required=True)
_sql_constraints = [
('name_uniq', 'unique (name)', 'Name already exists!'),
]
@api.depends('name')
def name_get(self):
return [(seniority.id, seniority.name.replace('_', ' ').title()) for seniority in self]

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

@@ -1,4 +1,4 @@
odoo.define('crm_iap_lead.generate_leads_steps', function (require) {
odoo.define('crm_iap_mine.generate_leads_steps', function (require) {
"use strict";
var tour = require('web_tour.tour');
@@ -16,7 +16,7 @@ tour.tours.crm_tour.steps.splice(DragOppToWonStepIndex + 1, 0, {
/**
* Add some steps between "Drag your opportunity to <b>Won</b> when you get
* the deal. Congrats !" and "Let’s have a look at an Opportunity." to
* include the steps related to the lead generation (crm_iap_lead).
* include the steps related to the lead generation (crm_iap_mine).
* This eases the on boarding for the Lead Generation process.
*
*/
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_lead_mine
+91
View File
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
from contextlib import contextmanager
from unittest.mock import patch
from odoo import exceptions
from odoo.addons.crm.models.crm_lead import Lead
from odoo.addons.crm_iap_mine.models.crm_iap_lead_mining_request import CRMLeadMiningRequest
from odoo.addons.iap.tests.common import MockIAPEnrich
from odoo.addons.iap.tools import iap_tools
class MockIAPReveal(MockIAPEnrich):
@classmethod
def setUpClass(cls):
super(MockIAPReveal, cls).setUpClass()
cls._new_leads = cls.env['crm.lead'].sudo()
cls.mine = False
@contextmanager
def mock_IAP_mine(self, mine, name_list=None, default_data=None, sim_error=None):
self._new_leads = self.env['crm.lead'].sudo()
self.mine = mine
crm_lead_create_origin = Lead.create
def _crm_lead_create(model, *args, **kwargs):
res = crm_lead_create_origin(model, *args, **kwargs)
self._new_leads += res.sudo()
return res
def _iap_contact_mining(params, timeout):
self.assertMineCallParams(params)
self.assertMinePayload(mine, params['data'])
if sim_error and sim_error == 'credit':
raise iap_tools.InsufficientCreditError('InsufficientCreditError')
if sim_error and sim_error == 'jsonrpc_exception':
raise exceptions.AccessError(
'The url that this service requested returned an error. Please contact the author of the app. The url it tried to contact was [STRIPPED]'
)
if sim_error and sim_error == 'no_result':
return {'credit_error': False, 'data': []}
response = []
for counter in range(0, mine.lead_number):
if name_list:
base_name = name_list[counter % len(name_list)]
else:
base_name = 'heinrich_%d' % counter
iap_payload = {}
company_data = self._get_iap_company_data(base_name, service='mine')
if default_data:
company_data.update(default_data)
iap_payload['company_data'] = company_data
if mine.search_type == 'people':
people_data = self._get_iap_contact_data(base_name, service='mine')
iap_payload['people_data'] = people_data
response.append(iap_payload)
return {
'data': response,
'credit_error': False
}
with patch.object(CRMLeadMiningRequest, '_iap_contact_mining', side_effect=_iap_contact_mining), \
patch.object(Lead, 'create', autospec=True, wraps=Lead, side_effect=_crm_lead_create):
yield
def _get_iap_company_data(self, base_name, service=None, add_values=None):
company_data = super(MockIAPReveal, self)._get_iap_company_data(base_name, service=service, add_values=add_values)
if service == 'mine':
company_data['phone'] = company_data['phone_numbers'][0]
company_data['sector'] = 'Sector Info'
return company_data
def assertMineCallParams(self, params):
self.assertTrue(bool(params['account_token']))
self.assertTrue(bool(params['dbuuid']))
def assertMinePayload(self, mine, payload):
if mine.search_type == 'people':
self.assertEqual(payload['contact_number'], mine.contact_number)
else:
self.assertTrue('contact_number' not in payload)
self.assertEqual(payload['countries'], mine.mapped('country_ids.code'))
self.assertEqual(payload['lead_number'], mine.lead_number)
self.assertEqual(payload['search_type'], mine.search_type)
+142
View File
@@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import exceptions
from odoo.addons.crm.tests.common import TestCrmCommon
from odoo.addons.crm_iap_mine.tests.common import MockIAPReveal
from odoo.tests.common import users
class TestLeadMine(TestCrmCommon, MockIAPReveal):
@classmethod
def setUpClass(cls):
super(TestLeadMine, cls).setUpClass()
cls.registry.enter_test_mode(cls.cr)
cls.test_crm_tags = cls.env['crm.tag'].create([
{'name': 'TestTag1'},
{'name': 'TestTag2'}
])
cls.test_request = cls.env['crm.iap.lead.mining.request'].create({
'contact_number': 3,
'error_type': False,
'lead_number': 3,
'lead_type': 'lead',
'name': 'Test Mine',
'search_type': 'people',
'state': 'draft',
'tag_ids': [(6, 0, cls.test_crm_tags.ids)],
'team_id': cls.sales_team_1.id,
'user_id': cls.user_sales_leads.id,
})
@classmethod
def tearDownClass(cls):
cls.registry.leave_test_mode()
super().tearDownClass()
@users('user_sales_manager')
def test_mine_error_credit(self):
mine_request = self.env['crm.iap.lead.mining.request'].browse(self.test_request.ids)
with self.mock_IAP_mine(mine_request, sim_error='credit'):
mine_request.action_submit()
self.assertEqual(mine_request.error_type, 'credits')
self.assertEqual(mine_request.state, 'error')
@users('user_sales_manager')
def test_mine_error_jsonrpc_exception(self):
mine_request = self.env['crm.iap.lead.mining.request'].browse(self.test_request.ids)
with self.assertRaises(exceptions.UserError):
with self.mock_IAP_mine(mine_request, sim_error='jsonrpc_exception'):
mine_request.action_submit()
@users('user_sales_manager')
def test_mine_error_no_result(self):
mine_request = self.env['crm.iap.lead.mining.request'].browse(self.test_request.ids)
with self.mock_IAP_mine(mine_request, sim_error='no_result'):
mine_request.action_submit()
self.assertEqual(mine_request.error_type, 'no_result')
self.assertEqual(mine_request.state, 'draft')
@users('user_sales_manager')
def test_mine_wpeople(self):
country_de = self.base_de
state_de = self.de_state_st
mine_request = self.env['crm.iap.lead.mining.request'].browse(self.test_request.ids)
with self.mock_IAP_mine(mine_request, name_list=['Heinrich', 'Rivil', 'LidGen']):
mine_request.action_submit()
self.assertFalse(mine_request.error_type)
self.assertEqual(mine_request.state, 'done')
self.assertEqual(len(self._new_leads), 3, 'Number of leads should match mine request')
for base_name in ['Heinrich', 'Rivil', 'LidGen']:
lead = self._new_leads.filtered(lambda lead: lead.name == '%s GmbH' % base_name)
self.assertTrue(bool(lead))
# mine information
self.assertEqual(lead.type, 'lead')
self.assertEqual(lead.tag_ids, self.test_crm_tags)
self.assertEqual(lead.team_id, self.sales_team_1)
self.assertEqual(lead.user_id, self.user_sales_leads)
# iap
self.assertEqual(lead.reveal_id, '123_ClearbitID_%s' % base_name, 'Ensure reveal_id is set to clearbit ID')
# clearbit information
self.assertEqual(lead.contact_name, 'Contact %s 0' % base_name)
self.assertEqual(lead.city, 'Mönchengladbach')
self.assertEqual(lead.country_id, country_de)
self.assertEqual(lead.email_from, 'test.contact.0@%s.example.com' % base_name,
'Lead email should be the one from first contact if search_type people is given')
self.assertEqual(lead.function, 'Doing stuff')
self.assertFalse(lead.partner_id)
self.assertEqual(lead.partner_name, '%s GmbH legal_name' % base_name)
self.assertEqual(lead.phone, '+4930499193937')
self.assertEqual(lead.state_id, state_de)
self.assertEqual(lead.street, 'Mennrather Str. 123456')
self.assertEqual(lead.website, 'https://www.%s.de' % base_name)
self.assertEqual(lead.zip, '41179')
@users('user_sales_manager')
def test_mine_wcompany(self):
country_de = self.base_de
state_de = self.de_state_st
mine_request = self.env['crm.iap.lead.mining.request'].browse(self.test_request.ids)
mine_request.write({'search_type': 'companies'})
with self.mock_IAP_mine(mine_request, name_list=['Heinrich', 'Rivil', 'LidGen']):
mine_request.action_submit()
self.assertFalse(mine_request.error_type)
self.assertEqual(mine_request.state, 'done')
self.assertEqual(len(self._new_leads), 3, 'Number of leads should match mine request')
for base_name in ['Heinrich', 'Rivil', 'LidGen']:
lead = self._new_leads.filtered(lambda lead: lead.name == '%s GmbH' % base_name)
self.assertTrue(bool(lead))
# mine information
self.assertEqual(lead.type, 'lead')
self.assertEqual(lead.tag_ids, self.test_crm_tags)
self.assertEqual(lead.team_id, self.sales_team_1)
self.assertEqual(lead.user_id, self.user_sales_leads)
# iap
self.assertEqual(lead.reveal_id, '123_ClearbitID_%s' % base_name, 'Ensure reveal_id is set to clearbit ID')
# clearbit information
self.assertFalse(lead.contact_name)
self.assertEqual(lead.city, 'Mönchengladbach')
self.assertEqual(lead.country_id, country_de)
self.assertEqual(lead.email_from, 'info@%s.example.com' % base_name)
self.assertFalse(lead.function)
self.assertFalse(lead.partner_id)
self.assertEqual(lead.partner_name, '%s GmbH legal_name' % base_name)
self.assertEqual(lead.phone, '+4930499193937')
self.assertEqual(lead.state_id, state_de)
self.assertEqual(lead.street, 'Mennrather Str. 123456')
self.assertEqual(lead.website, 'https://www.%s.de' % base_name)
self.assertEqual(lead.zip, '41179')
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="crm_iap_lead_mining_request_form" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.form</field>
<record id="crm_iap_lead_mining_request_view_form" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.view.form</field>
<field name="model">crm.iap.lead.mining.request</field>
<field name="arch" type="xml">
<form>
@@ -107,8 +107,8 @@
</field>
</record>
<record id="crm_iap_lead_mining_request_tree" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.tree</field>
<record id="crm_iap_lead_mining_request_view_tree" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.view.tree</field>
<field name="model">crm.iap.lead.mining.request</field>
<field name="arch" type="xml">
<tree>
@@ -124,8 +124,8 @@
</field>
</record>
<record id="crm_iap_lead_mining_request_search" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.search</field>
<record id="crm_iap_lead_mining_request_view_search" model="ir.ui.view">
<field name="name">crm.iap.lead.mining.request.view.search</field>
<field name="model">crm.iap.lead.mining.request</field>
<field name="arch" type="xml">
<search string="Lead Mining Request">
@@ -153,18 +153,4 @@
<field name="res_model">crm.iap.lead.mining.request</field>
<field name="view_mode">tree,form</field>
</record>
<!-- This menu is display in CRM app when crm_iap_lead is installed-->
<menuitem
id="crm_menu_lead_generation"
name="Lead Generation"
parent="crm.crm_menu_config"
sequence="20"/>
<menuitem
id="crm_iap_lead_mining_request_menu_action"
action="crm_iap_lead_mining_request_action"
parent="crm_menu_lead_generation"
sequence="0"/>
</odoo>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="crm_iap_opportunity_tree" model="ir.ui.view">
<field name="name">crm.opportunity.inherited.tree</field>
<record id="crm_lead_view_tree_opportunity" model="ir.ui.view">
<field name="name">crm.lead.view.tree.opportunity.inherit.iap.mine</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_tree_view_oppor" />
<field name="arch" type="xml">
@@ -12,8 +12,8 @@
</field>
</record>
<record id="crm_iap_opportunity_kanban" model="ir.ui.view">
<field name="name">crm.opportunity.inherited.kanban</field>
<record id="crm_lead_view_kanban_opportunity" model="ir.ui.view">
<field name="name">crm.lead.view.kanban.inherit.iap.mine</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_kanban_view_leads" />
<field name="arch" type="xml">
@@ -23,8 +23,8 @@
</field>
</record>
<record id="crm_iap_lead_tree" model="ir.ui.view">
<field name="name">crm.lead.inherited.tree</field>
<record id="crm_lead_view_tree_lead" model="ir.ui.view">
<field name="name">crm.lead.view.tree.lead.inherit.iap.mine</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_tree_view_leads" />
<field name="arch" type="xml">
@@ -34,8 +34,8 @@
</field>
</record>
<record id="crm_iap_lead_kanban" model="ir.ui.view">
<field name="name">crm.lead.inherited.kanban</field>
<record id="crm_lead_view_kanban_lead" model="ir.ui.view">
<field name="name">crm.lead.view.kanban.lead.inherit.iap.mine</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.view_crm_lead_kanban" />
<field name="arch" type="xml">
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- This menu is display in CRM app when crm_iap_lead is installed-->
<menuitem
id="crm_menu_lead_generation"
name="Lead Generation"
parent="crm.crm_menu_config"
sequence="20"/>
<menuitem
id="crm_iap_lead_mining_request_menu_action"
action="crm_iap_lead_mining_request_action"
parent="crm_menu_lead_generation"
sequence="0"/>
</odoo>
@@ -5,7 +5,7 @@
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="crm.res_config_settings_view_form"/>
<field name="arch" type="xml">
<div id="crm_iap_lead_settings" position="inside">
<div id="crm_iap_mine_settings" position="inside">
<widget name="iap_buy_more_credits" service_name="reveal"/>
</div>
</field>
+102 -2
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from contextlib import contextmanager
from functools import partial
from unittest.mock import patch
from odoo import exceptions
@@ -10,7 +9,12 @@ from odoo.addons.iap.models.iap_enrich_api import IapEnrichAPI
from odoo.tests import common
class MockIAPEnrich(common.BaseCase):
class MockIAPEnrich(common.TransactionCase):
@classmethod
def setUpClass(cls):
super(MockIAPEnrich, cls).setUpClass()
cls._init_iap_mock()
@contextmanager
def mockIAPEnrichGateway(self, default_data=None, email_data=None, sim_error=None, failing_emails=None):
@@ -49,3 +53,99 @@ class MockIAPEnrich(common.BaseCase):
yield
finally:
pass
@classmethod
def _init_iap_mock(cls):
cls.base_de = cls.env.ref('base.de')
cls.de_state_st = cls.env['res.country.state'].create({
'name': 'DE ST State',
'code': 'st',
'country_id': cls.base_de.id
})
cls.base_be = cls.env.ref('base.be')
cls.be_state_bw = cls.env['res.country.state'].create({
'name': 'Béwééé dis',
'code': 'bw',
'country_id': cls.base_be.id
})
def _get_iap_company_data(self, base_name, service=None, add_values=None):
return {
'domain': '%s.de' % base_name,
'clearbit_id': '123_ClearbitID_%s' % base_name,
# Company Info
'name': '%s GmbH' % base_name,
'legal_name': '%s GmbH legal_name' % base_name,
'description': '%s GmbH description' % base_name,
'founded_year': '1930',
'logo': 'https://logo.clearbit.com/%slogo.com' % base_name,
'company_type': 'private',
# Contacts
'phone_numbers': ['+4930499193937', '+4930653376208'],
'email': [
'info@%s.example.com' % base_name,
'info2@%s.example.com' % base_name
],
# Timezone
'timezone': 'Europe/Berlin',
'timezone_url': 'https://time.is/Berlin',
# Social
'facebook': "%s Facebook Handle" % base_name,
'linkedin': "%s Linkedin Handle" % base_name,
'crunchbase': "organization/%s" % base_name,
# Twitter
'twitter': '%s Twitter Handle' % base_name,
'twitter_bio': '%s Twitter Bio' % base_name,
'twitter_followers': 1250,
'twitter_location': 'Berlin',
# Metrics
'estimated_annual_revenue': '1000000',
'employees': 3.14,
'market_cap': 6.28,
'raised': 15000,
'annual_revenue': 1000000,
# Category
'sector': '%s sector' % base_name,
'sector_primary': '%s sector_primary' % base_name,
'industry': '%s industry' % base_name,
'industry_group': '%s industry_group' % base_name,
'sub_industry': '%s sub_industry' % base_name,
'tag': ['Automation', 'Construction'],
'tech': ['3d_cart', 'nginx'],
# Site
'website_title': '%s Website Title' % base_name,
# GEO Data
'location': 'Mennrather Str. 123456',
'street_number': '123456',
'street_name': 'Mennrather Str.',
'sub_premise': 'sub premise',
'postal_code': '41179',
'city': 'Mönchengladbach',
'state_code': self.de_state_st.code,
'state_name': self.de_state_st.name,
'country_code': self.base_de.code,
'country_name': self.base_de.name,
}
def _get_iap_contact_data(self, base_name, service=None, add_values=None):
people_data = []
for index in range(2):
payload = {
'full_name': 'Contact %s %s' % (base_name, index),
'email': 'test.contact.%s@%s.example.com' % (index, base_name),
'phone': '+49 30 548406496',
'seniority': 'manager',
'title': 'Doing stuff',
'role': 'health_professional',
}
people_data.append(payload)
return people_data
+5 -3
View File
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Contact Form',
'category': 'Website/Website',
@@ -14,11 +15,12 @@ This module includes contact phone and mobile numbers validation.""",
'depends': ['website', 'crm'],
'data': [
'security/ir.model.access.csv',
'data/website_crm_data.xml',
'views/website_crm_lead_views.xml',
'views/website_crm_templates.xml',
'data/ir_actions_data.xml',
'data/ir_model_data.xml',
'views/crm_lead_views.xml',
'views/res_config_settings_views.xml',
'views/website_visitor_views.xml',
'views/website_templates_contactus.xml',
],
'installable': True,
'auto_install': True,
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main
from . import website_form

Some files were not shown because too many files have changed in this diff Show More