[ADD] crm_reveal: New IAP module

crm_reveal will allow the automated generation of leads based on the
visits of the website.
This commit is contained in:
TWA
2018-09-20 13:58:33 +02:00
committed by Rémi Rahir
parent 067754f0f6
commit eebaf55fde
20 changed files with 3243 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
+20
View File
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Lead Generation',
'summary': 'Create Leads/Opportunities from your website\'s traffic',
'category': 'CRM',
'depends': ['iap', 'crm', 'website_form'],
'data': [
'data/crm.reveal.industry.csv',
'data/crm.reveal.role.csv',
'data/crm.reveal.seniority.csv',
'data/message_template.xml',
'data/reveal_data.xml',
'security/ir.model.access.csv',
'views/crm_lead_view.xml',
'views/crm_reveal_views.xml',
'views/res_config_settings_views.xml'
]
}
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main
+19
View File
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
import json
from odoo import http
from odoo.addons.website_form.controllers.main import WebsiteForm
from odoo.http import request
class ContactController(WebsiteForm):
@http.route('/website_form/<string:model_name>', type='http', auth="public", methods=['POST'], website=True)
def website_form(self, model_name, **kwargs):
if model_name == 'crm.lead':
# Add the ip_address to the request in order to add this to the lead
# that will be created. With this, we avoid to create a lead from
# reveal if a lead is already created from the contact form.
request.params['reveal_ip'] = request.httprequest.remote_addr
return super(ContactController, self).website_form(model_name, **kwargs)
@@ -0,0 +1,238 @@
"id",name,reveal_id
"crm_reveal_industry_1","3D Printing","1"
"crm_reveal_industry_2","Accounting","2"
"crm_reveal_industry_3","Aerospace & Defense","3"
"crm_reveal_industry_4","Agriculture","4"
"crm_reveal_industry_5","Airlines","5"
"crm_reveal_industry_6","Alternative Medicine","6"
"crm_reveal_industry_7","Animation","7"
"crm_reveal_industry_8","Apparel & Footwear","8"
"crm_reveal_industry_9","Architecture","9"
"crm_reveal_industry_10","Arts","10"
"crm_reveal_industry_11","Arts & Crafts","11"
"crm_reveal_industry_12","Asset Management","12"
"crm_reveal_industry_13","Audio","13"
"crm_reveal_industry_14","Automation","14"
"crm_reveal_industry_15","Automotive","15"
"crm_reveal_industry_16","Banking & Mortgages","16"
"crm_reveal_industry_17","Beverages","17"
"crm_reveal_industry_18","Biotechnology","18"
"crm_reveal_industry_19","Broadcasting","19"
"crm_reveal_industry_20","Building Materials","20"
"crm_reveal_industry_21","Business Supplies","21"
"crm_reveal_industry_22","Chemicals","22"
"crm_reveal_industry_23","Civil Engineering","23"
"crm_reveal_industry_24","Cloud Services","24"
"crm_reveal_industry_25","Communications","25"
"crm_reveal_industry_26","Computer Hardware","26"
"crm_reveal_industry_27","Construction","27"
"crm_reveal_industry_28","Construction Contractors & Services","28"
"crm_reveal_industry_29","Consulting & Professional Services","29"
"crm_reveal_industry_30","Consumer Discretionary","30"
"crm_reveal_industry_31","Consumer Electronics","31"
"crm_reveal_industry_32","Consumer Goods","32"
"crm_reveal_industry_33","Consumer Staples","33"
"crm_reveal_industry_34","Corporate & Business","34"
"crm_reveal_industry_35","Cosmetics","35"
"crm_reveal_industry_36","Design","36"
"crm_reveal_industry_37","E-Commerce & Marketplaces","37"
"crm_reveal_industry_38","E-Learning","38"
"crm_reveal_industry_39","Education","39"
"crm_reveal_industry_40","Electrical","40"
"crm_reveal_industry_41","Energy","41"
"crm_reveal_industry_42","Energy & Utilities","42"
"crm_reveal_industry_43","Entertainment & Recreation","43"
"crm_reveal_industry_44","Events","44"
"crm_reveal_industry_45","Eyewear","45"
"crm_reveal_industry_46","Facilities","46"
"crm_reveal_industry_47","Family Services","47"
"crm_reveal_industry_48","Finance","48"
"crm_reveal_industry_49","Financial Services","49"
"crm_reveal_industry_50","Fine Art","50"
"crm_reveal_industry_51","Firearms","51"
"crm_reveal_industry_52","Fishery","52"
"crm_reveal_industry_53","Food","53"
"crm_reveal_industry_54","Food Production","54"
"crm_reveal_industry_55","Forums","55"
"crm_reveal_industry_56","Fundraising","56"
"crm_reveal_industry_57","Gambling & Casinos","57"
"crm_reveal_industry_58","Government","58"
"crm_reveal_industry_59","Ground Transportation","59"
"crm_reveal_industry_60","Health & Wellness","60"
"crm_reveal_industry_61","Health Care","61"
"crm_reveal_industry_62","Higher Education","62"
"crm_reveal_industry_63","Home & Furniture","63"
"crm_reveal_industry_64","Home Improvement","64"
"crm_reveal_industry_65","Human Resources","65"
"crm_reveal_industry_66","Import & Export","66"
"crm_reveal_industry_67","Industrials & Manufacturing","67"
"crm_reveal_industry_68","Information Technology & Services","68"
"crm_reveal_industry_69","Insurance","69"
"crm_reveal_industry_70","International Relations","70"
"crm_reveal_industry_71","International Trade","71"
"crm_reveal_industry_72","Internet","72"
"crm_reveal_industry_73","Investment","73"
"crm_reveal_industry_74","Investment Banking","74"
"crm_reveal_industry_75","Investment Management","75"
"crm_reveal_industry_76","Jewelry, Watches & Luxury Goods","76"
"crm_reveal_industry_77","Judiciary","77"
"crm_reveal_industry_78","Law Enforcement","78"
"crm_reveal_industry_79","Legal Services","79"
"crm_reveal_industry_80","Libraries","80"
"crm_reveal_industry_81","Machinery","81"
"crm_reveal_industry_82","Maritime","82"
"crm_reveal_industry_83","Market Research","83"
"crm_reveal_industry_84","Marketing & Advertising","84"
"crm_reveal_industry_85","Mechanical Engineering","85"
"crm_reveal_industry_86","Media","86"
"crm_reveal_industry_87","Medicine","87"
"crm_reveal_industry_88","Military","88"
"crm_reveal_industry_89","Mining & Metals","89"
"crm_reveal_industry_90","Movies & TV","90"
"crm_reveal_industry_91","Museums","91"
"crm_reveal_industry_92","Music","92"
"crm_reveal_industry_93","Nanotechnology","93"
"crm_reveal_industry_94","Networking","94"
"crm_reveal_industry_95","Non-Profit & Philanthropy","95"
"crm_reveal_industry_96","Oil & Gas","96"
"crm_reveal_industry_97","Outsourcing","97"
"crm_reveal_industry_98","Packaging & Containers","98"
"crm_reveal_industry_99","Paper Goods","99"
"crm_reveal_industry_100","Payments","100"
"crm_reveal_industry_101","Performing Arts","101"
"crm_reveal_industry_102","Pharmaceuticals","102"
"crm_reveal_industry_103","Pharmacy","103"
"crm_reveal_industry_104","Photography","104"
"crm_reveal_industry_105","Plastics","105"
"crm_reveal_industry_106","Plumbing","106"
"crm_reveal_industry_107","Political Organization","107"
"crm_reveal_industry_108","Pornography","108"
"crm_reveal_industry_109","Primary & Secondary Education","109"
"crm_reveal_industry_110","Printing","110"
"crm_reveal_industry_111","Public Relations","111"
"crm_reveal_industry_112","Publishing","112"
"crm_reveal_industry_113","Ranching","113"
"crm_reveal_industry_114","Real Estate","114"
"crm_reveal_industry_115","Religion","115"
"crm_reveal_industry_116","Renewables & Environment","116"
"crm_reveal_industry_117","Restaurants","117"
"crm_reveal_industry_118","Retail","118"
"crm_reveal_industry_119","Sanitization Services","119"
"crm_reveal_industry_120","Scientific & Academic Research","120"
"crm_reveal_industry_121","Security","121"
"crm_reveal_industry_122","Services","122"
"crm_reveal_industry_123","Shipbuilding","123"
"crm_reveal_industry_124","Shipping & Logistics","124"
"crm_reveal_industry_125","Society","125"
"crm_reveal_industry_126","Sporting Goods","126"
"crm_reveal_industry_127","Sports & Fitness","127"
"crm_reveal_industry_128","Stores","128"
"crm_reveal_industry_129","Talent Agencies","129"
"crm_reveal_industry_130","Technology","130"
"crm_reveal_industry_131","Telecommunications","131"
"crm_reveal_industry_132","Textiles","132"
"crm_reveal_industry_133","Tobacco","133"
"crm_reveal_industry_134","Tools","134"
"crm_reveal_industry_135","Translation","135"
"crm_reveal_industry_136","Transportation","136"
"crm_reveal_industry_137","Travel & Leisure","137"
"crm_reveal_industry_138","Utilities","138"
"crm_reveal_industry_139","Venture Capital","139"
"crm_reveal_industry_140","Veterinary","140"
"crm_reveal_industry_141","Video Games","141"
"crm_reveal_industry_142","Warehousing","142"
"crm_reveal_industry_143","Web Services & Apps","143"
"crm_reveal_industry_144","Wholesale","144"
"crm_reveal_industry_145","Financials","145"
"crm_reveal_industry_146","Industrials","146"
"crm_reveal_industry_147","Information Technology","147"
"crm_reveal_industry_148","Materials","148"
"crm_reveal_industry_149","Telecommunication Services","149"
"crm_reveal_industry_150","Consumer Services","150"
"crm_reveal_industry_151","Diversified Consumer Services","151"
"crm_reveal_industry_152","Retailing","152"
"crm_reveal_industry_153","Food & Staples Retailing","153"
"crm_reveal_industry_154","Food, Beverage & Tobacco","154"
"crm_reveal_industry_155","Household & Personal Products","155"
"crm_reveal_industry_156","Energy Equipment & Services","156"
"crm_reveal_industry_157","Banks","157"
"crm_reveal_industry_158","Diversified Financial Services","158"
"crm_reveal_industry_159","Diversified Financials","159"
"crm_reveal_industry_160","Health Care Equipment & Services","160"
"crm_reveal_industry_161","Pharmaceuticals, Biotechnology & Life Sciences","161"
"crm_reveal_industry_162","Capital Goods","162"
"crm_reveal_industry_163","Commercial & Professional Services","163"
"crm_reveal_industry_164","Semiconductors & Semiconductor Equipment","164"
"crm_reveal_industry_165","Software & Services","165"
"crm_reveal_industry_166","Technology Hardware & Equipment","166"
"crm_reveal_industry_167","Construction Materials","167"
"crm_reveal_industry_168","Independent Power and Renewable Electricity Producers","168"
"crm_reveal_industry_169","Hotels, Restaurants & Leisure","169"
"crm_reveal_industry_170","Education Services","170"
"crm_reveal_industry_171","Specialized Consumer Services","171"
"crm_reveal_industry_172","Distributors","172"
"crm_reveal_industry_173","Specialty Retail","173"
"crm_reveal_industry_174","Food Products","174"
"crm_reveal_industry_175","Personal Products","175"
"crm_reveal_industry_176","Gas Utilities","176"
"crm_reveal_industry_177","Capital Markets","177"
"crm_reveal_industry_178","Health Care Equipment & Supplies","178"
"crm_reveal_industry_179","Health Care Providers & Services","179"
"crm_reveal_industry_180","Life Sciences Tools & Services","180"
"crm_reveal_industry_181","Commercial Services & Supplies","181"
"crm_reveal_industry_182","Construction & Engineering","182"
"crm_reveal_industry_183","Electrical Equipment","183"
"crm_reveal_industry_184","Industrial Conglomerates","184"
"crm_reveal_industry_185","Trading Companies & Distributors","185"
"crm_reveal_industry_186","Professional Services","186"
"crm_reveal_industry_187","Air Freight & Logistics","187"
"crm_reveal_industry_188","Marine","188"
"crm_reveal_industry_189","Road & Rail","189"
"crm_reveal_industry_190","Internet Software & Services","190"
"crm_reveal_industry_191","IT Services","191"
"crm_reveal_industry_192","Software","192"
"crm_reveal_industry_193","Communications Equipment","193"
"crm_reveal_industry_194","Electronic Equipment, Instruments & Components","194"
"crm_reveal_industry_195","Technology Hardware, Storage & Peripherals","195"
"crm_reveal_industry_196","Containers & Packaging","196"
"crm_reveal_industry_197","Metals & Mining","197"
"crm_reveal_industry_198","Paper & Forest Products","198"
"crm_reveal_industry_199","Diversified Telecommunication Services","199"
"crm_reveal_industry_200","Wireless Telecommunication Services","200"
"crm_reveal_industry_201","Renewable Electricity","201"
"crm_reveal_industry_202","Electric Utilities","202"
"crm_reveal_industry_203","Casinos & Gaming","203"
"crm_reveal_industry_204","Leisure Facilities","204"
"crm_reveal_industry_205","Advertising","205"
"crm_reveal_industry_206","Movies & Entertainment","206"
"crm_reveal_industry_207","Home Improvement Retail","207"
"crm_reveal_industry_208","Homefurnishing Retail","208"
"crm_reveal_industry_209","Food Retail","209"
"crm_reveal_industry_210","Agricultural Products","210"
"crm_reveal_industry_211","Packaged Foods & Meats","211"
"crm_reveal_industry_212","Asset Management & Custody Banks","212"
"crm_reveal_industry_213","Diversified Capital Markets","213"
"crm_reveal_industry_214","Investment Banking & Brokerage","214"
"crm_reveal_industry_215","Health Care Services","215"
"crm_reveal_industry_216","Commercial Printing","216"
"crm_reveal_industry_217","Industrial Machinery","217"
"crm_reveal_industry_218","Consulting","218"
"crm_reveal_industry_219","Human Resource & Employment Services","219"
"crm_reveal_industry_220","Research & Consulting Services","220"
"crm_reveal_industry_221","Semiconductors","221"
"crm_reveal_industry_222","Data Processing & Outsourced Services","222"
"crm_reveal_industry_223","Graphic Design","223"
"crm_reveal_industry_224","Computer Networking","224"
"crm_reveal_industry_225","Commodity Chemicals","225"
"crm_reveal_industry_226","Gold","226"
"crm_reveal_industry_227","Paper Products","227"
"crm_reveal_industry_228","Integrated Telecommunication Services","228"
"crm_reveal_industry_229","Renewable Energy","229"
"crm_reveal_industry_230","B2B","230"
"crm_reveal_industry_231","B2C","231"
"crm_reveal_industry_232","E-Commerce","232"
"crm_reveal_industry_233","Enterprise","233"
"crm_reveal_industry_234","ISP","234"
"crm_reveal_industry_235","Marketplace","235"
"crm_reveal_industry_236","Mobile","236"
"crm_reveal_industry_237","SAAS","237"
1 id name reveal_id
2 crm_reveal_industry_1 3D Printing 1
3 crm_reveal_industry_2 Accounting 2
4 crm_reveal_industry_3 Aerospace & Defense 3
5 crm_reveal_industry_4 Agriculture 4
6 crm_reveal_industry_5 Airlines 5
7 crm_reveal_industry_6 Alternative Medicine 6
8 crm_reveal_industry_7 Animation 7
9 crm_reveal_industry_8 Apparel & Footwear 8
10 crm_reveal_industry_9 Architecture 9
11 crm_reveal_industry_10 Arts 10
12 crm_reveal_industry_11 Arts & Crafts 11
13 crm_reveal_industry_12 Asset Management 12
14 crm_reveal_industry_13 Audio 13
15 crm_reveal_industry_14 Automation 14
16 crm_reveal_industry_15 Automotive 15
17 crm_reveal_industry_16 Banking & Mortgages 16
18 crm_reveal_industry_17 Beverages 17
19 crm_reveal_industry_18 Biotechnology 18
20 crm_reveal_industry_19 Broadcasting 19
21 crm_reveal_industry_20 Building Materials 20
22 crm_reveal_industry_21 Business Supplies 21
23 crm_reveal_industry_22 Chemicals 22
24 crm_reveal_industry_23 Civil Engineering 23
25 crm_reveal_industry_24 Cloud Services 24
26 crm_reveal_industry_25 Communications 25
27 crm_reveal_industry_26 Computer Hardware 26
28 crm_reveal_industry_27 Construction 27
29 crm_reveal_industry_28 Construction Contractors & Services 28
30 crm_reveal_industry_29 Consulting & Professional Services 29
31 crm_reveal_industry_30 Consumer Discretionary 30
32 crm_reveal_industry_31 Consumer Electronics 31
33 crm_reveal_industry_32 Consumer Goods 32
34 crm_reveal_industry_33 Consumer Staples 33
35 crm_reveal_industry_34 Corporate & Business 34
36 crm_reveal_industry_35 Cosmetics 35
37 crm_reveal_industry_36 Design 36
38 crm_reveal_industry_37 E-Commerce & Marketplaces 37
39 crm_reveal_industry_38 E-Learning 38
40 crm_reveal_industry_39 Education 39
41 crm_reveal_industry_40 Electrical 40
42 crm_reveal_industry_41 Energy 41
43 crm_reveal_industry_42 Energy & Utilities 42
44 crm_reveal_industry_43 Entertainment & Recreation 43
45 crm_reveal_industry_44 Events 44
46 crm_reveal_industry_45 Eyewear 45
47 crm_reveal_industry_46 Facilities 46
48 crm_reveal_industry_47 Family Services 47
49 crm_reveal_industry_48 Finance 48
50 crm_reveal_industry_49 Financial Services 49
51 crm_reveal_industry_50 Fine Art 50
52 crm_reveal_industry_51 Firearms 51
53 crm_reveal_industry_52 Fishery 52
54 crm_reveal_industry_53 Food 53
55 crm_reveal_industry_54 Food Production 54
56 crm_reveal_industry_55 Forums 55
57 crm_reveal_industry_56 Fundraising 56
58 crm_reveal_industry_57 Gambling & Casinos 57
59 crm_reveal_industry_58 Government 58
60 crm_reveal_industry_59 Ground Transportation 59
61 crm_reveal_industry_60 Health & Wellness 60
62 crm_reveal_industry_61 Health Care 61
63 crm_reveal_industry_62 Higher Education 62
64 crm_reveal_industry_63 Home & Furniture 63
65 crm_reveal_industry_64 Home Improvement 64
66 crm_reveal_industry_65 Human Resources 65
67 crm_reveal_industry_66 Import & Export 66
68 crm_reveal_industry_67 Industrials & Manufacturing 67
69 crm_reveal_industry_68 Information Technology & Services 68
70 crm_reveal_industry_69 Insurance 69
71 crm_reveal_industry_70 International Relations 70
72 crm_reveal_industry_71 International Trade 71
73 crm_reveal_industry_72 Internet 72
74 crm_reveal_industry_73 Investment 73
75 crm_reveal_industry_74 Investment Banking 74
76 crm_reveal_industry_75 Investment Management 75
77 crm_reveal_industry_76 Jewelry, Watches & Luxury Goods 76
78 crm_reveal_industry_77 Judiciary 77
79 crm_reveal_industry_78 Law Enforcement 78
80 crm_reveal_industry_79 Legal Services 79
81 crm_reveal_industry_80 Libraries 80
82 crm_reveal_industry_81 Machinery 81
83 crm_reveal_industry_82 Maritime 82
84 crm_reveal_industry_83 Market Research 83
85 crm_reveal_industry_84 Marketing & Advertising 84
86 crm_reveal_industry_85 Mechanical Engineering 85
87 crm_reveal_industry_86 Media 86
88 crm_reveal_industry_87 Medicine 87
89 crm_reveal_industry_88 Military 88
90 crm_reveal_industry_89 Mining & Metals 89
91 crm_reveal_industry_90 Movies & TV 90
92 crm_reveal_industry_91 Museums 91
93 crm_reveal_industry_92 Music 92
94 crm_reveal_industry_93 Nanotechnology 93
95 crm_reveal_industry_94 Networking 94
96 crm_reveal_industry_95 Non-Profit & Philanthropy 95
97 crm_reveal_industry_96 Oil & Gas 96
98 crm_reveal_industry_97 Outsourcing 97
99 crm_reveal_industry_98 Packaging & Containers 98
100 crm_reveal_industry_99 Paper Goods 99
101 crm_reveal_industry_100 Payments 100
102 crm_reveal_industry_101 Performing Arts 101
103 crm_reveal_industry_102 Pharmaceuticals 102
104 crm_reveal_industry_103 Pharmacy 103
105 crm_reveal_industry_104 Photography 104
106 crm_reveal_industry_105 Plastics 105
107 crm_reveal_industry_106 Plumbing 106
108 crm_reveal_industry_107 Political Organization 107
109 crm_reveal_industry_108 Pornography 108
110 crm_reveal_industry_109 Primary & Secondary Education 109
111 crm_reveal_industry_110 Printing 110
112 crm_reveal_industry_111 Public Relations 111
113 crm_reveal_industry_112 Publishing 112
114 crm_reveal_industry_113 Ranching 113
115 crm_reveal_industry_114 Real Estate 114
116 crm_reveal_industry_115 Religion 115
117 crm_reveal_industry_116 Renewables & Environment 116
118 crm_reveal_industry_117 Restaurants 117
119 crm_reveal_industry_118 Retail 118
120 crm_reveal_industry_119 Sanitization Services 119
121 crm_reveal_industry_120 Scientific & Academic Research 120
122 crm_reveal_industry_121 Security 121
123 crm_reveal_industry_122 Services 122
124 crm_reveal_industry_123 Shipbuilding 123
125 crm_reveal_industry_124 Shipping & Logistics 124
126 crm_reveal_industry_125 Society 125
127 crm_reveal_industry_126 Sporting Goods 126
128 crm_reveal_industry_127 Sports & Fitness 127
129 crm_reveal_industry_128 Stores 128
130 crm_reveal_industry_129 Talent Agencies 129
131 crm_reveal_industry_130 Technology 130
132 crm_reveal_industry_131 Telecommunications 131
133 crm_reveal_industry_132 Textiles 132
134 crm_reveal_industry_133 Tobacco 133
135 crm_reveal_industry_134 Tools 134
136 crm_reveal_industry_135 Translation 135
137 crm_reveal_industry_136 Transportation 136
138 crm_reveal_industry_137 Travel & Leisure 137
139 crm_reveal_industry_138 Utilities 138
140 crm_reveal_industry_139 Venture Capital 139
141 crm_reveal_industry_140 Veterinary 140
142 crm_reveal_industry_141 Video Games 141
143 crm_reveal_industry_142 Warehousing 142
144 crm_reveal_industry_143 Web Services & Apps 143
145 crm_reveal_industry_144 Wholesale 144
146 crm_reveal_industry_145 Financials 145
147 crm_reveal_industry_146 Industrials 146
148 crm_reveal_industry_147 Information Technology 147
149 crm_reveal_industry_148 Materials 148
150 crm_reveal_industry_149 Telecommunication Services 149
151 crm_reveal_industry_150 Consumer Services 150
152 crm_reveal_industry_151 Diversified Consumer Services 151
153 crm_reveal_industry_152 Retailing 152
154 crm_reveal_industry_153 Food & Staples Retailing 153
155 crm_reveal_industry_154 Food, Beverage & Tobacco 154
156 crm_reveal_industry_155 Household & Personal Products 155
157 crm_reveal_industry_156 Energy Equipment & Services 156
158 crm_reveal_industry_157 Banks 157
159 crm_reveal_industry_158 Diversified Financial Services 158
160 crm_reveal_industry_159 Diversified Financials 159
161 crm_reveal_industry_160 Health Care Equipment & Services 160
162 crm_reveal_industry_161 Pharmaceuticals, Biotechnology & Life Sciences 161
163 crm_reveal_industry_162 Capital Goods 162
164 crm_reveal_industry_163 Commercial & Professional Services 163
165 crm_reveal_industry_164 Semiconductors & Semiconductor Equipment 164
166 crm_reveal_industry_165 Software & Services 165
167 crm_reveal_industry_166 Technology Hardware & Equipment 166
168 crm_reveal_industry_167 Construction Materials 167
169 crm_reveal_industry_168 Independent Power and Renewable Electricity Producers 168
170 crm_reveal_industry_169 Hotels, Restaurants & Leisure 169
171 crm_reveal_industry_170 Education Services 170
172 crm_reveal_industry_171 Specialized Consumer Services 171
173 crm_reveal_industry_172 Distributors 172
174 crm_reveal_industry_173 Specialty Retail 173
175 crm_reveal_industry_174 Food Products 174
176 crm_reveal_industry_175 Personal Products 175
177 crm_reveal_industry_176 Gas Utilities 176
178 crm_reveal_industry_177 Capital Markets 177
179 crm_reveal_industry_178 Health Care Equipment & Supplies 178
180 crm_reveal_industry_179 Health Care Providers & Services 179
181 crm_reveal_industry_180 Life Sciences Tools & Services 180
182 crm_reveal_industry_181 Commercial Services & Supplies 181
183 crm_reveal_industry_182 Construction & Engineering 182
184 crm_reveal_industry_183 Electrical Equipment 183
185 crm_reveal_industry_184 Industrial Conglomerates 184
186 crm_reveal_industry_185 Trading Companies & Distributors 185
187 crm_reveal_industry_186 Professional Services 186
188 crm_reveal_industry_187 Air Freight & Logistics 187
189 crm_reveal_industry_188 Marine 188
190 crm_reveal_industry_189 Road & Rail 189
191 crm_reveal_industry_190 Internet Software & Services 190
192 crm_reveal_industry_191 IT Services 191
193 crm_reveal_industry_192 Software 192
194 crm_reveal_industry_193 Communications Equipment 193
195 crm_reveal_industry_194 Electronic Equipment, Instruments & Components 194
196 crm_reveal_industry_195 Technology Hardware, Storage & Peripherals 195
197 crm_reveal_industry_196 Containers & Packaging 196
198 crm_reveal_industry_197 Metals & Mining 197
199 crm_reveal_industry_198 Paper & Forest Products 198
200 crm_reveal_industry_199 Diversified Telecommunication Services 199
201 crm_reveal_industry_200 Wireless Telecommunication Services 200
202 crm_reveal_industry_201 Renewable Electricity 201
203 crm_reveal_industry_202 Electric Utilities 202
204 crm_reveal_industry_203 Casinos & Gaming 203
205 crm_reveal_industry_204 Leisure Facilities 204
206 crm_reveal_industry_205 Advertising 205
207 crm_reveal_industry_206 Movies & Entertainment 206
208 crm_reveal_industry_207 Home Improvement Retail 207
209 crm_reveal_industry_208 Homefurnishing Retail 208
210 crm_reveal_industry_209 Food Retail 209
211 crm_reveal_industry_210 Agricultural Products 210
212 crm_reveal_industry_211 Packaged Foods & Meats 211
213 crm_reveal_industry_212 Asset Management & Custody Banks 212
214 crm_reveal_industry_213 Diversified Capital Markets 213
215 crm_reveal_industry_214 Investment Banking & Brokerage 214
216 crm_reveal_industry_215 Health Care Services 215
217 crm_reveal_industry_216 Commercial Printing 216
218 crm_reveal_industry_217 Industrial Machinery 217
219 crm_reveal_industry_218 Consulting 218
220 crm_reveal_industry_219 Human Resource & Employment Services 219
221 crm_reveal_industry_220 Research & Consulting Services 220
222 crm_reveal_industry_221 Semiconductors 221
223 crm_reveal_industry_222 Data Processing & Outsourced Services 222
224 crm_reveal_industry_223 Graphic Design 223
225 crm_reveal_industry_224 Computer Networking 224
226 crm_reveal_industry_225 Commodity Chemicals 225
227 crm_reveal_industry_226 Gold 226
228 crm_reveal_industry_227 Paper Products 227
229 crm_reveal_industry_228 Integrated Telecommunication Services 228
230 crm_reveal_industry_229 Renewable Energy 229
231 crm_reveal_industry_230 B2B 230
232 crm_reveal_industry_231 B2C 231
233 crm_reveal_industry_232 E-Commerce 232
234 crm_reveal_industry_233 Enterprise 233
235 crm_reveal_industry_234 ISP 234
236 crm_reveal_industry_235 Marketplace 235
237 crm_reveal_industry_236 Mobile 236
238 crm_reveal_industry_237 SAAS 237
@@ -0,0 +1,23 @@
"id",name,reveal_id
"crm_reveal_role_1","ceo","ceo"
"crm_reveal_role_2","communications","communications"
"crm_reveal_role_3","consulting","consulting"
"crm_reveal_role_4","customer_service","customer_service"
"crm_reveal_role_5","education","education"
"crm_reveal_role_6","engineering","engineering"
"crm_reveal_role_7","finance","finance"
"crm_reveal_role_8","founder","founder"
"crm_reveal_role_9","health_professional","health_professional"
"crm_reveal_role_10","human_resources","human_resources"
"crm_reveal_role_11","information_technology","information_technology"
"crm_reveal_role_12","legal","legal"
"crm_reveal_role_13","marketing","marketing"
"crm_reveal_role_14","operations","operations"
"crm_reveal_role_15","owner","owner"
"crm_reveal_role_16","president","president"
"crm_reveal_role_17","product","product"
"crm_reveal_role_18","public_relations","public_relations"
"crm_reveal_role_19","real_estate","real_estate"
"crm_reveal_role_20","recruiting","recruiting"
"crm_reveal_role_21","research","research"
"crm_reveal_role_22","sale","sale"
1 id name reveal_id
2 crm_reveal_role_1 ceo ceo
3 crm_reveal_role_2 communications communications
4 crm_reveal_role_3 consulting consulting
5 crm_reveal_role_4 customer_service customer_service
6 crm_reveal_role_5 education education
7 crm_reveal_role_6 engineering engineering
8 crm_reveal_role_7 finance finance
9 crm_reveal_role_8 founder founder
10 crm_reveal_role_9 health_professional health_professional
11 crm_reveal_role_10 human_resources human_resources
12 crm_reveal_role_11 information_technology information_technology
13 crm_reveal_role_12 legal legal
14 crm_reveal_role_13 marketing marketing
15 crm_reveal_role_14 operations operations
16 crm_reveal_role_15 owner owner
17 crm_reveal_role_16 president president
18 crm_reveal_role_17 product product
19 crm_reveal_role_18 public_relations public_relations
20 crm_reveal_role_19 real_estate real_estate
21 crm_reveal_role_20 recruiting recruiting
22 crm_reveal_role_21 research research
23 crm_reveal_role_22 sale sale
@@ -0,0 +1,4 @@
"id",name,reveal_id
"crm_reveal_seniority_1","director","director"
"crm_reveal_seniority_2","executive","executive"
"crm_reveal_seniority_3","manager","manager"
1 id name reveal_id
2 crm_reveal_seniority_1 director director
3 crm_reveal_seniority_2 executive executive
4 crm_reveal_seniority_3 manager manager
+123
View File
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="lead_message_template">
<p>Opportunity created by Odoo Lead Generation</p>
<div style="width:80%;background-color:#ffffff;padding:15px;margin:16px 10%;">
<table style="width:100%">
<tr>
<td></td>
<td style="padding: 25px;" rowspan="6">
<img style="max-width: 80px;" t-attf-src="{{logo}}"/>
</td>
</tr>
<tr>
<td style="padding: 0 0 5px 0;">
<span style="font-size:25px;vertical-align: middle;">
<b><t t-esc="name"/></b>
</span>
<span style="">
<a t-if="twitter" style="margin: 0 0 0 8px;" target="blank" t-attf-href="http://www.twitter.com/{{twitter}}">
<img src="/web_editor/font_to_img/61569/rgb(0,132,180)/22"/>
</a>
<a t-if="facebook" style="margin: 0 0 0 8px;" target="blank" t-attf-href="http://www.facebook.com/{{facebook}}">
<img src="/web_editor/font_to_img/61570/rgb(59,89,152)/22"/>
</a>
<a t-if="linkedin" style="margin: 0 0 0 8px;" target="blank" t-attf-href="https://www.linkedin.com/{{linkedin}}">
<img src="/web_editor/font_to_img/61580/rgb(0,119,181)/22"/>
</a>
<a t-if="crunchbase" style="margin: 0 0 0 8px;" target="blank" t-attf-href="https://www.crunchbase.com/{{crunchbase}}">
<img width="18px" height="18px" src="/crm_reveal/static/img/crunchbase.ico"/>
</a>
</span>
</td>
</tr>
<tr>
<td style="padding: 0 0 5px 0;">
<span><t t-esc="description"/></span>
</td>
</tr>
<tr>
<td t-if="timezone" style="padding: 0 0 5px 0;">
<img src="/web_editor/font_to_img/61463/rgb(135,90,123)/16"/>
<b>Timezone : </b>
<span><t t-esc="timezone"/></span>
<span>
<a target="blank" t-attf-href="https://www.timeanddate.com/worldclock/{{timezone_link}}">(Time Now)</a>
</span>
</td>
</tr>
<tr>
<td t-if="phone_numbers" style="padding: 0 0 5px 0;">
<img src="/web_editor/font_to_img/61589/rgb(135,90,123)/16"/>
<b>Phone :</b>
<t t-foreach="phone_numbers" t-as="phone_number">
<span style="margin:0 5px;">
<a target="blank" t-attf-href="tel:{{phone_number}}"><t t-esc="phone_number"/></a>
</span>
</t>
</td>
</tr>
<tr>
<td t-if="tech">
<b><img src="/web_editor/font_to_img/61874/rgb(135,90,123)/16"/> Technology Used :</b>
<t t-foreach="tech" t-as="t">
<label style="font-weight:normal;padding: 2px 10px;background-color: #eeeeee;margin: 0 0 4px 2px;border-radius: 13px;">
<t t-esc="t"/>
</label>
</t>
</td>
</tr>
</table>
<div t-if="people_data" style="font-size:16px;margin: 9px 0;">
<b>Contacts</b>
</div>
<table style="width:100%;
border-top-style: solid;border-top-color: #eeeeee;border-top-width: 1px;
border-bottom-style: solid;border-bottom-color: #eeeeee;border-bottom-width: 1px;
border-left-style: solid;border-left-color: #eeeeee;border-left-width: 1px;
border-right-style: solid;border-right-color: #eeeeee;border-right-width: 1px;" t-if="people_data">
<thead>
<tr style="background-color: #eeeeee">
<th style="padding: 5px">
Name
</th>
<th style="padding: 5px">
Title
</th>
<th style="padding: 5px">
<img src="web_editor/font_to_img/61664/rgb(102,102,102)/13"/>
Email
</th>
<th style="padding: 5px">
<img src="web_editor/font_to_img/61589/rgb(102,102,102)/13"/>
Phone
</th>
</tr>
</thead>
<tbody>
<t t-foreach="people_data" t-as="people">
<tr t-att-style="people_odd and 'background-color:#eeeeee' or None">
<td style="padding: 5px">
<t t-esc="people['full_name'] or ''"/>
</td>
<td style="padding: 5px">
<t t-esc="people['title'] or ''"/>
</td>
<td style="padding: 5px">
<a t-if="people['email']" t-attf-href="mailto:{{people['email']}}" target="_top">
<t t-esc="people['email']"/>
</a>
</td>
<td style="padding: 5px">
<a t-if="people['phone']" t-attf-href="tel:{{people['phone']}}">
<t t-esc="people['phone']"/>
</a>
</td>
</tr>
</t>
</tbody>
</table>
</div>
</template>
</odoo>
+40
View File
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Scheduler for Lead Generation -->
<record id="ir_cron_crm_reveal_lead" model="ir.cron">
<field name="name">Lead Generation: Leads/Opportunities Generation</field>
<field name="model_id" ref="model_crm_reveal_rule"/>
<field name="state">code</field>
<field name="code">model._process_lead_generation()</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
<record id="reveal_no_credits" model="mail.template">
<field name="name">IAP Lead Generation Notification</field>
<field name="email_from">iap@odoo.com</field>
<field name="email_to">iap@odoo.com</field>
<field name="subject">IAP Lead Generation Notification</field>
<field name="model_id" ref="iap.model_iap_account"/>
<field name="body_html">
<![CDATA[
<p>Dear,</p>
<p>There is no more credits on your IAP Lead Generation account.<br/>
You can charge your IAP Lead Generation account in the settings of the CRM app.<br/>
<p>Best regards,</p>
<p>Odoo S.A.</p>
]]>
</field>
</record>
</data>
<function model="ir.model.fields" name="formbuilder_whitelist">
<value>crm.lead</value>
<value eval="['reveal_ip']"/>
</function>
</odoo>
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import crm_lead
from . import crm_reveal_rule
from . import crm_reveal_view
from . import ir
from . import res_config_settings
+13
View File
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class Lead(models.Model):
_inherit = 'crm.lead'
reveal_ip = fields.Char(string='IP Address')
reveal_iap_credits = fields.Integer(string='IAP Credits')
reveal_rule_id = fields.Many2one('crm.reveal.rule', string='Lead Generation Rule', index=True)
reveal_id = fields.Char(string='Reveal ID', index=True)
+517
View File
@@ -0,0 +1,517 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
import itertools
import logging
import re
from dateutil.relativedelta import relativedelta
from math import floor, log10
from odoo import api, fields, models, tools, _
from odoo.addons.iap import jsonrpc
from odoo.addons.crm.models import crm_stage
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
DEFAULT_ENDPOINT = 'https://iap-services.odoo.com'
DEFAULT_REVEAL_BATCH_LIMIT = 25
DEFAULT_REVEAL_MONTH_VALID = 6
class CRMRevealRule(models.Model):
_name = 'crm.reveal.rule'
_description = 'CRM Lead Generation Rules'
_order = 'sequence'
name = fields.Char(string='Rule Name', required=True)
active = fields.Boolean(default=True)
# Website Traffic Filter
country_ids = fields.Many2many('res.country', string='Countries', help='Only visitors of following countries will be converted into leads/opportunities (using GeoIP).')
regex_url = fields.Char(string='URL Expression', help='Regex to track website pages. Leave empty to track the entire website, or / to target the homepage. Example: /page* to track all the pages which begin with /page')
sequence = fields.Integer(help='Used to order the rules with same URL and countries. '
'Rules with a lower sequence number will be processed first.')
# Company Criteria Filter
industry_tag_ids = fields.Many2many('crm.reveal.industry', string='Industry Tags', help='Leave empty to always match. Odoo will not create lead if no match')
company_size_min = fields.Integer(string='Min Company Size', help="Leave it as 0 if you don't want to use this filter.")
company_size_max = fields.Integer(string='Max Company Size', help="Leave it as 0 if you don't want to use this filter.")
# Contact Generation Filter
preferred_role_id = fields.Many2one('crm.reveal.role', string='Preferred Role')
other_role_ids = fields.Many2many('crm.reveal.role', string='Other Roles')
seniority_id = fields.Many2one('crm.reveal.seniority', string='Seniority')
extra_contacts = fields.Integer(string='Extra Contacts', help='This is the number of extra contacts to track if their role and seniority match your criteria.Their details will show up in the history thread of generated leads/opportunities. One credit is consumed per tracked contact.')
calculate_credits = fields.Integer(compute='_compute_credit_count', string='Credit Used', readonly=True)
# Lead / Opportunity Data
lead_for = fields.Selection([('companies', 'Companies'), ('people', 'Companies + Contacts')], string='Data Tracking', required=True, default='companies', help='If you track company data, one credit will be consumed per lead/opportunity created. If you track company and contacts data, two credits will be consumed. Such data will be visible in the lead/opportunity.')
lead_type = fields.Selection([('lead', 'Lead'), ('opportunity', 'Opportunity')], string='Type', required=True, default='opportunity')
suffix = fields.Char(string='Suffix', help='This will be appended in name of generated lead so you can identify lead/opportunity is generated with this rule')
team_id = fields.Many2one('crm.team', string='Sales Channel')
tag_ids = fields.Many2many('crm.lead.tag', string='Tags')
user_id = fields.Many2one('res.users', string='Salesperson')
priority = fields.Selection(crm_stage.AVAILABLE_PRIORITIES, string='Priority')
lead_ids = fields.One2many('crm.lead', 'reveal_rule_id', string='Generated Lead / Opportunity')
leads_count = fields.Integer(compute='_compute_leads_count', string='Number of Generated Leads')
opportunity_count = fields.Integer(compute='_compute_leads_count', string='Number of Generated Opportunity')
# This limits the number of extra contact.
# Even if more than 5 extra contacts provided service will return only 5 contacts (see service module for more)
_sql_constraints = [
('limit_extra_contacts', 'check(extra_contacts >= 0 and extra_contacts <= 5)', 'Maximum 5 extra contacts are allowed!'),
]
@api.constrains('regex_url')
def _check_regex_url(self):
try:
if self.regex_url:
re.compile(self.regex_url)
except Exception:
raise ValidationError(_('Enter Valid Regex.'))
@api.model
def create(self, vals):
self.clear_caches() # Clear the cache in order to recompute _get_active_rules
return super(CRMRevealRule, self).create(vals)
def write(self, vals):
fields_set = {
'country_ids', 'regex_url', 'active'
}
if set(vals.keys()) & fields_set:
self.clear_caches() # Clear the cache in order to recompute _get_active_rules
return super(CRMRevealRule, self).write(vals)
def unlink(self):
self.clear_caches() # Clear the cache in order to recompute _get_active_rules
return super(CRMRevealRule, self).unlink()
@api.depends('extra_contacts', 'lead_for')
def _compute_credit_count(self):
""" Computes maximum IAP credit can be consumed per lead """
credit = 1
if self.lead_for == 'people':
credit += 1
if self.extra_contacts:
credit += self.extra_contacts
self.calculate_credits = credit
def _compute_leads_count(self):
leads = self.env['crm.lead'].read_group([
('reveal_rule_id', 'in', self.ids)
], fields=['reveal_rule_id', 'type'], groupby=['reveal_rule_id', 'type'], lazy=False)
mapping = {(lead['reveal_rule_id'][0], lead['type']): lead['__count'] for lead in leads}
for rule in self:
rule.leads_count = mapping.get((rule.id, 'lead'), 0)
rule.opportunity_count = mapping.get((rule.id, 'opportunity'), 0)
def action_get_lead_tree_view(self):
action = self.env.ref('crm.crm_lead_all_leads').read()[0]
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'lead')]
return action
def action_get_opportunity_tree_view(self):
action = self.env.ref('crm.crm_lead_opportunities').read()[0]
action['domain'] = [('id', 'in', self.lead_ids.ids), ('type', '=', 'opportunity')]
return action
@api.model
@tools.ormcache()
def _get_active_rules(self):
"""
Returns informations about the all rules.
The return is in the form :
{
'country_rules': {
'BE': [0, 1],
'US': [0]
},
'rules': [
{
'id': 0,
'url': ***,
'country_codes': ['BE', 'US']
},
{
'id': 1,
'url': ***,
'country_codes': ['BE']
}
]
}
"""
country_rules = {}
rules_records = self.search([])
rules = []
# Fixes for special cases
for rule in rules_records:
regex_url = rule['regex_url']
if not regex_url:
regex_url = '.*' # for all pages if url not given
elif regex_url == '/':
regex_url = '.*/$' # for home
countries = rule.country_ids.mapped('code')
rules.append({
'id': rule.id,
'regex': regex_url,
'country_codes': countries
})
for country in countries:
country_rules = self._add_to_country(country_rules, country, len(rules) - 1)
return {
'country_rules': country_rules,
'rules': rules,
}
def _add_to_country(self, country_rules, country, rule_index):
"""
Add the rule index to the country code in the country_rules
"""
if country not in country_rules:
country_rules[country] = []
country_rules[country].append(rule_index)
return country_rules
def _match_url(self, url, country_code, rules_excluded):
"""
Return the matching rule based on the country and URL.
"""
all_rules = self._get_active_rules()
rules_id = all_rules['country_rules'].get(country_code, [])
rules_matched = []
for rule_index in rules_id:
rule = all_rules['rules'][rule_index]
if str(rule['id']) not in rules_excluded and re.search(rule['regex'], url):
rules_matched.append(rule)
return rules_matched
@api.model
def _process_lead_generation(self, autocommit=True):
""" Cron Job for lead generation from page view """
_logger.info('Start Reveal Lead Generation')
self.env['crm.reveal.view']._clean_reveal_views()
self._unlink_unrelevant_reveal_view()
reveal_views = self._get_reveal_views_to_process()
view_count = 0
while reveal_views:
view_count += len(reveal_views)
server_payload = self._prepare_iap_payload(dict(reveal_views))
enough_credit = self._perform_reveal_service(server_payload)
if autocommit:
# auto-commit for batch processing
self._cr.commit()
if enough_credit:
reveal_views = self._get_reveal_views_to_process()
else:
reveal_views = False
_logger.info('End Reveal Lead Generation - %s views processed', view_count)
@api.model
def _unlink_unrelevant_reveal_view(self):
"""
We don't want to create the lead if in past (<6 months) we already
created lead with given IP. So, we unlink crm.reveal.view with same IP
as a already created lead.
"""
months_valid = self.env['ir.config_parameter'].sudo().get_param('reveal.lead_month_valid', DEFAULT_REVEAL_MONTH_VALID)
try:
months_valid = int(months_valid)
except ValueError:
months_valid = DEFAULT_REVEAL_MONTH_VALID
domain = []
domain.append(('reveal_ip', '!=', False))
domain.append(('create_date', '>', fields.Datetime.to_string(datetime.date.today() - relativedelta(months=months_valid))))
leads = self.env['crm.lead'].with_context(active_test=False).search(domain)
self.env['crm.reveal.view'].search([('reveal_ip', 'in', [lead.reveal_ip for lead in leads])]).unlink()
@api.model
def _get_reveal_views_to_process(self):
""" Return list of reveal rule ids grouped by IPs """
batch_limit = self.env['ir.config_parameter'].sudo().get_param('reveal.fetch_limit', DEFAULT_REVEAL_BATCH_LIMIT)
try:
batch_limit = int(batch_limit)
except ValueError:
batch_limit = DEFAULT_REVEAL_BATCH_LIMIT
query = """
SELECT v.reveal_ip, array_agg(v.reveal_rule_id ORDER BY r.sequence)
FROM crm_reveal_view v
INNER JOIN crm_reveal_rule r
ON v.reveal_rule_id = r.id
WHERE v.reveal_state='to_process'
GROUP BY v.reveal_ip
LIMIT %d
""" % batch_limit
self.env.cr.execute(query)
return self.env.cr.fetchall()
def _prepare_iap_payload(self, pgv):
""" This will prepare the page view and returns payload
Payload sample
{
ips: {
'192.168.1.1': [1,4],
'192.168.1.6': [2,4]
},
rules: {
1: {rule_data},
2: {rule_data},
4: {rule_data}
}
}
"""
new_list = list(set(itertools.chain.from_iterable(pgv.values())))
rule_records = self.browse(new_list)
return {
'ips': pgv,
'rules': rule_records._get_rules_payload()
}
def _get_rules_payload(self):
company_country = self.env.user.company_id.country_id
rule_payload = {}
for rule in self:
data = {
'rule_id': rule.id,
'lead_for': rule.lead_for,
'countries': rule.country_ids.mapped('code'),
'company_size_min': rule.company_size_min,
'company_size_max': rule.company_size_max,
'industry_tags': rule.industry_tag_ids.mapped('reveal_id'),
'user_country': company_country and company_country.code or False
}
if rule.lead_for == 'people':
data.update({
'preferred_role': rule.preferred_role_id.reveal_id or '',
'other_roles': rule.other_role_ids.mapped('reveal_id'),
'seniority': rule.seniority_id.reveal_id or '',
'extra_contacts': rule.extra_contacts
})
rule_payload[rule.id] = data
return rule_payload
def _perform_reveal_service(self, server_payload):
result = False
account_token = self.env['iap.account'].get('reveal')
endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/reveal'
params = {
'account_token': account_token.account_token,
'data': server_payload
}
result = jsonrpc(endpoint, params=params)
for res in result.get('reveal_data', []):
if not res.get('not_found'):
lead = self._create_lead_from_response(res)
self.env['crm.reveal.view'].search([('reveal_ip', '=', res['ip'])]).unlink()
else:
self.env['crm.reveal.view'].search([('reveal_ip', '=', res['ip'])]).write({
'reveal_state': 'not_found'
})
if result.get('credit_error'):
self._notify_no_more_credit()
return False
else:
self.env['ir.config_parameter'].sudo().set_param('reveal.already_notified', False)
return True
def _notify_no_more_credit(self):
"""
Notify about the number of credit.
In order to avoid to spam people each hour, an ir.config_parameter is set
"""
already_notified = self.env['ir.config_parameter'].sudo().get_param('reveal.already_notified', False)
if already_notified:
return
mail_template = self.env.ref('crm_reveal.reveal_no_credits')
iap_account = self.env['iap.account'].search([('service_name', '=', 'reveal')], limit=1)
# Get the email address of the creators of the Lead Generation Rules
res = self.env['crm.reveal.rule'].search_read([], ['create_uid'])
uids = set(r['create_uid'][0] for r in res if r.get('create_uid'))
res = self.env['res.users'].search_read([('id', 'in', list(uids))], ['email'])
emails = set(r['email'] for r in res if r.get('email'))
mail_values = mail_template.generate_email(iap_account.id)
mail_values['email_to'] = ','.join(emails)
mail = self.env['mail.mail'].create(mail_values)
mail.send()
self.env['ir.config_parameter'].sudo().set_param('reveal.already_notified', True)
def _create_lead_from_response(self, result):
""" This method will get response from service and create the lead accordingly """
if result['rule_id']:
rule = self.browse(result['rule_id'])
else:
# Not create a lead if the information match no rule
# If there is no match, the service still returns all informations
# in order to let custom code use it.
return False
if not result['clearbit_id']:
return False
already_created_lead = self.env['crm.lead'].search([('reveal_id', '=', result['clearbit_id'])])
if already_created_lead:
_logger.info('Existing lead for this clearbit_id [%s]', result['clearbit_id'])
# Does not create a lead if the reveal_id is already known
return False
lead_vals = rule._lead_vals_from_response(result)
lead = self.env['crm.lead'].create(lead_vals)
lead.message_post_with_view(
'crm_reveal.lead_message_template',
values=self._format_data_for_message_post(result),
subtype_id=self.env.ref('mail.mt_note').id
)
return lead
# Methods responsible for format response data in to valid odoo lead data
def _lead_vals_from_response(self, result):
self.ensure_one()
reveal_data = result['reveal_data']
people_data = result.get('people_data')
country_id = self.env['res.country'].search([('code', '=', reveal_data['country_code'])]).id
website_url = 'https://www.%s' % reveal_data['domain'] if reveal_data['domain'] else False
lead_vals = {
# Lead vals from rule itself
'type': self.lead_type,
'team_id': self.team_id.id,
'tag_ids': [(6, 0, self.tag_ids.ids)],
'priority': self.priority,
'user_id': self.user_id.id,
'reveal_ip': result['ip'],
'reveal_rule_id': self.id,
'reveal_id': result['clearbit_id'],
'referred': 'Website Visitor',
# Lead vals from response
'name': reveal_data['name'],
'reveal_iap_credits': result['credit'],
'partner_name': reveal_data['legal_name'] or reveal_data['name'],
'email_from': ",".join(reveal_data['email'] or []),
'phone': reveal_data['phone'] or (reveal_data['phone_numbers'] and reveal_data['phone_numbers'][0]) or '',
'website': website_url,
'street': reveal_data['location'],
'city': reveal_data['city'],
'zip': reveal_data['postal_code'],
'country_id': country_id,
'state_id': self._find_state_id(reveal_data['state_name'], reveal_data['state_code'], country_id),
'description': self._prepare_lead_description(reveal_data),
}
if self.suffix:
lead_vals['name'] = '%s - %s' % (lead_vals['name'], self.suffix)
# If type is people then add first contact in lead data
if people_data:
lead_vals.update({
'contact_name': people_data[0]['full_name'],
'email_from': people_data[0]['email'],
'function': people_data[0]['title'],
})
return lead_vals
def _find_state_id(self, state_code, state_name, country_id):
state_id = self.env['res.country.state'].search([('code', '=', state_code), ('country_id', '=', country_id)])
if state_id:
return state_id.id
return False
def _prepare_lead_description(self, reveal_data):
description = ''
if reveal_data['sector']:
description += reveal_data['sector']
if reveal_data['website_title']:
description += '\n' + reveal_data['website_title']
if reveal_data['twitter_bio']:
description += '\n' + "Twitter Bio: " + reveal_data['twitter_bio']
if reveal_data['twitter_followers']:
description += ('\nTwitter %s followers, %s \n') % (reveal_data['twitter_followers'], reveal_data['twitter_location'] or '')
numbers = ['raised', 'market_cap', 'employees', 'estimated_annual_revenue']
millnames = ['', ' K', ' M', ' B', 'T']
def millify(n):
try:
n = float(n)
millidx = max(0, min(len(millnames) - 1, int(floor(0 if n == 0 else log10(abs(n)) / 3))))
return '{:.0f}{}'.format(n / 10**(3 * millidx), millnames[millidx])
except Exception:
return n
for key in numbers:
if reveal_data.get(key):
description += ' %s : %s,' % (key.replace('_', ' ').title(), millify(reveal_data[key]))
return description
def _format_data_for_message_post(self, result):
reveal_data = result['reveal_data']
people_data = result.get('people_data')
log_data = {
'twitter': reveal_data['twitter'],
'description': reveal_data['description'],
'logo': reveal_data['logo'],
'name': reveal_data['name'],
'phone_numbers': reveal_data['phone_numbers'],
'facebook': reveal_data['facebook'],
'linkedin': reveal_data['linkedin'],
'crunchbase': reveal_data['crunchbase'],
'tech': [t.replace('_', ' ').title() for t in reveal_data['tech']],
'people_data': people_data,
}
timezone = result['ip_time_zone'] or reveal_data['timezone']
if timezone:
log_data.update({
'timezone': timezone.replace('_', ' ').title(),
'timezone_link': timezone.lower().replace('_', '-'),
})
return log_data
class IndustryTag(models.Model):
""" Industry Tags of Acquisition Rules """
_name = 'crm.reveal.industry'
_description = 'Industry Tag'
name = fields.Char(string='Tag Name', required=True, translate=True)
reveal_id = fields.Char(required=True)
color = fields.Integer(string='Color Index')
_sql_constraints = [
('name_uniq', 'unique (name)', 'Tag name already exists!'),
]
class PeopleRole(models.Model):
""" CRM Reveal People Roles for People """
_name = 'crm.reveal.role'
_description = 'People Role'
name = fields.Char(string='Role Name', required=True, translate=True)
reveal_id = fields.Char(required=True)
color = fields.Integer(string='Color Index')
_sql_constraints = [
('name_uniq', 'unique (name)', 'Role name already exists!'),
]
@api.depends('name')
def name_get(self):
return [(role.id, role.name.replace('_', ' ').title()) for role in self]
class PeopleSeniority(models.Model):
""" Seniority for People Rules """
_name = 'crm.reveal.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]
@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
DEFAULT_REVEAL_VIEW_WEEKS_VALID = 5
class CRMRevealView(models.Model):
_name = 'crm.reveal.view'
_order = 'id desc'
reveal_ip = fields.Char(string='IP Address', index=True)
reveal_rule_id = fields.Many2one('crm.reveal.rule', string='Lead Generation Rule', index=True)
reveal_state = fields.Selection([('to_process', 'To Process'), ('not_found', 'Not Found')], default='to_process', string="State", index=True)
create_date = fields.Datetime(index=True)
@api.model_cr
def init(self):
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('crm_reveal_view_ip_rule_id',))
if not self._cr.fetchone():
self._cr.execute('CREATE UNIQUE INDEX crm_reveal_view_ip_rule_id ON crm_reveal_view (reveal_rule_id,reveal_ip)')
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('crm_reveal_view_state_create_date',))
if not self._cr.fetchone():
self._cr.execute('CREATE INDEX crm_reveal_view_state_create_date ON crm_reveal_view (reveal_state,create_date)')
@api.model
def _clean_reveal_views(self):
""" Remove old views (> 1 month) """
weeks_valid = self.env['ir.config_parameter'].sudo().get_param('reveal.view_weeks_valid', DEFAULT_REVEAL_VIEW_WEEKS_VALID)
try:
weeks_valid = int(weeks_valid)
except ValueError:
weeks_valid = DEFAULT_REVEAL_VIEW_WEEKS_VALID
domain = []
domain.append(('reveal_state', '=', 'not_found'))
domain.append(('create_date', '<', fields.Datetime.to_string(datetime.date.today() - relativedelta(weeks=weeks_valid))))
self.search(domain).unlink()
def _create_reveal_view(self, url, ip_address, country_code, rules_excluded):
# we are avoiding reveal if reveal_view already created for this IP
rules = self.env['crm.reveal.rule']._match_url(url, country_code, rules_excluded)
if rules:
query = """
INSERT INTO crm_reveal_view (reveal_ip, reveal_rule_id, reveal_state, create_date)
VALUES (%s, %s, 'to_process', now() at time zone 'UTC')
ON CONFLICT DO NOTHING;
""" * len(rules)
params = []
for rule in rules:
params += [ip_address, rule['id']]
rules_excluded.append(str(rule['id']))
self.env.cr.execute(query, params)
return rules_excluded
return False
+38
View File
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
import logging
import time
from odoo import models
from odoo.http import request
_logger = logging.getLogger(__name__)
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
@classmethod
def _serve_page(cls):
response = super(IrHttp, cls)._serve_page()
if response and getattr(response, 'status_code', 0) == 200 and request.env.user._is_public():
lead_id = request.httprequest.cookies.get('lead_id')
# We are avoiding to create a reveal_view if a lead is already
# created from another module, e.g. website_form
if not lead_id:
country_code = 'geoip' in request.session and request.session['geoip'].get('country_code')
if country_code:
try:
url = request.httprequest.url
ip_address = request.httprequest.remote_addr
rules_excluded = (request.httprequest.cookies.get('rule_ids') or '').split(',')
before = time.time()
new_rules_excluded = request.env['crm.reveal.view'].sudo()._create_reveal_view(url, ip_address, country_code, rules_excluded)
# even when we match, no view may have been created if this is a duplicate
_logger.info('Reveal process time: [%s], match rule: [%s?], country code: [%s], ip: [%s]',
time.time() - before, new_rules_excluded == rules_excluded, country_code,
ip_address)
if new_rules_excluded:
response.set_cookie('rule_ids', ','.join(new_rules_excluded))
except Exception:
# just in case - we never want to crash a page view
_logger.exception("Failed to process reveal rules")
return response
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
@api.multi
def action_buy_reveal_iap_credits(self):
url = self.env['iap.account'].get_credits_url('reveal', 'https://iap.odoo.com/iap/1/credit', 0)
return {
'type': 'ir.actions.act_url',
'url': url,
'target': 'new',
}
@@ -0,0 +1,6 @@
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_crm_reveal_rule,access_crm_reveal_rule,model_crm_reveal_rule,sales_team.group_sale_manager,1,1,1,1
access_crm_reveal_view,access_crm_reveal_view,model_crm_reveal_view,sales_team.group_sale_manager,1,1,1,1
access_crm_reveal_industry,access_crm_reveal_industry,model_crm_reveal_industry,sales_team.group_sale_manager,1,1,1,1
access_crm_reveal_role,access_crm_reveal_role,model_crm_reveal_role,sales_team.group_sale_manager,1,1,1,1
access_crm_reveal_seniority,access_crm_reveal_seniority,model_crm_reveal_seniority,sales_team.group_sale_manager,1,1,1,1
1 id name model_id/id group_id/id perm_read perm_write perm_create perm_unlink
2 access_crm_reveal_rule access_crm_reveal_rule model_crm_reveal_rule sales_team.group_sale_manager 1 1 1 1
3 access_crm_reveal_view access_crm_reveal_view model_crm_reveal_view sales_team.group_sale_manager 1 1 1 1
4 access_crm_reveal_industry access_crm_reveal_industry model_crm_reveal_industry sales_team.group_sale_manager 1 1 1 1
5 access_crm_reveal_role access_crm_reveal_role model_crm_reveal_role sales_team.group_sale_manager 1 1 1 1
6 access_crm_reveal_seniority access_crm_reveal_seniority model_crm_reveal_seniority sales_team.group_sale_manager 1 1 1 1
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="crm_reveal_lead_form" model="ir.ui.view">
<field name="name">crm.lead.form</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_leads" />
<field name="arch" type="xml">
<xpath expr="//page[@name='extra']/group" position="inside">
<group string="Lead Generation Information" attrs="{'invisible': [('reveal_ip', '=', False)]}" groups="base.group_no_one">
<field name="reveal_ip"/>
<field name="reveal_iap_credits"/>
<field name="reveal_rule_id"/>
</group>
</xpath>
</field>
</record>
<record id="crm_reveal_lead_opportunity_form" model="ir.ui.view">
<field name="name">crm.lead.opportunity.inherited.crm</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_oppor"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='lead']/group" position="after">
<group string="Lead Generation Information" attrs="{'invisible': [('reveal_ip', '=', False)]}" groups="base.group_no_one">
<field name="reveal_ip"/>
<field name="reveal_iap_credits"/>
<field name="reveal_rule_id"/>
</group>
</xpath>
</field>
</record>
</odoo>
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="crm_reveal_rule_form" model="ir.ui.view">
<field name="name">crm.reveal.rule.form</field>
<field name="model">crm.reveal.rule</field>
<field name="arch" type="xml">
<form>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_get_opportunity_tree_view" class="oe_stat_button" type="object" icon="fa-handshake-o" attrs="{'invisible': [('lead_type', '!=', 'opportunity'), ('opportunity_count', '=' , 0)]}">
<div class="o_stat_info">
<field name="opportunity_count"/>
<span class="o_stat_text"> Opportunities </span>
</div>
</button>
<button name="action_get_lead_tree_view" class="oe_stat_button" type="object" icon="fa-handshake-o" groups="crm.group_use_lead" attrs="{'invisible': [('lead_type', '!=', 'lead'), ('leads_count', '=' , 0)]}">
<div class="o_stat_info">
<field name="leads_count"/>
<span class="o_stat_text"> Leads </span>
</div>
</button>
<button name="toggle_active" type="object" groups="base.group_user" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button" options="{'terminology': 'archive'}"/>
</button>
</div>
<div>
<div class="alert alert-info pull-right" role="alert">
No credit is consumed if the company is not found.<br/>
1 credit is consumed if the company is found.<br/>
<span attrs="{'invisible': [('lead_for', '!=', 'people')]}"><field name="calculate_credits" class="mb0"/> credits are consumed if the company matches the rule.</span>
</div>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1 class="o_row">
<field name="name" placeholder="e.g. US Visitors"/>
</h1>
</div>
<group>
<field name="lead_for" widget="radio"/>
</group>
<group>
<group string="Website Traffic Conditions">
<field name="country_ids" widget="many2many_tags"/>
<field name="regex_url" widget="website_urls"/>
<field name="sequence"/>
</group>
</group>
<group>
<group string="Opportunity Generation Conditions">
<field name="industry_tag_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True, 'no_quick_create': True}"/>
<label for="company_size_min"/>
<div>
<field name="company_size_min" class="oe_inline" />
<span> people </span>
</div>
<label for="company_size_max"/>
<div>
<field name="company_size_max" class="oe_inline" />
<span> people </span>
</div>
</group>
<group string="Contact Filter" attrs="{'invisible': [('lead_for', '!=', 'people')]}">
<field name="preferred_role_id" options="{'no_create_edit': True, 'no_quick_create': True}"/>
<field name="other_role_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True, 'no_quick_create': True}" attrs="{'invisible': [('preferred_role_id','=', False)]}"/>
<field name="seniority_id" options="{'no_create_edit': True, 'no_quick_create': True}"/>
<field name="extra_contacts"/>
</group>
</group>
<separator attrs="{'invisible': [('lead_type', '!=', 'lead')]}" string="Lead Data" />
<separator attrs="{'invisible': [('lead_type', '!=', 'opportunity')]}" string="Opportunity Data" />
<group>
<group>
<field name="lead_type" groups="crm.group_use_lead"/>
<field name="suffix"/>
<field name="team_id"/>
<field name="user_id"/>
</group>
<group>
<field name="tag_ids" widget="many2many_tags"/>
<field name="priority" widget="priority"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="crm_reveal_rule_tree" model="ir.ui.view">
<field name="name">crm.reveal.rule.tree</field>
<field name="model">crm.reveal.rule</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="lead_type"/>
</tree>
</field>
</record>
<record id="crm_reveal_rule_action" model="ir.actions.act_window">
<field name="name">Lead Generation Rules</field>
<field name="res_model">crm.reveal.rule</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No rule found
</p><p>
Create rules to generate B2B leads/opportunities by tracking data of your website visitors.
</p>
</field>
</record>
<record id="crm_reveal_view_form" model="ir.ui.view">
<field name="name">crm.reveal.view.form</field>
<field name="model">crm.reveal.view</field>
<field name="arch" type="xml">
<form>
<header>
<field name="reveal_state" widget="statusbar"/>
</header>
<sheet>
<group>
<field name="reveal_ip"/>
<field name="reveal_rule_id"/>
<field name="reveal_state"/>
<field name="create_date"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="crm_reveal_view_tree" model="ir.ui.view">
<field name="name">crm.reveal.view.tree</field>
<field name="model">crm.reveal.view</field>
<field name="arch" type="xml">
<tree>
<field name="reveal_ip"/>
<field name="reveal_rule_id"/>
<field name="reveal_state"/>
<field name="create_date"/>
</tree>
</field>
</record>
<record id="crm_reveal_view_action" model="ir.actions.act_window">
<field name="name">Lead Generation Views</field>
<field name="res_model">crm.reveal.view</field>
<field name="view_mode">tree,form</field>
</record>
<!-- This menu is display in CRM app when crm_reveal is installed-->
<menuitem
id="crm_reveal_rule_menu_action"
action="crm_reveal_rule_action"
parent="crm.crm_menu_config"/>
<menuitem
id="crm_reveal_view_menu_action"
parent="crm.crm_menu_report"
action="crm_reveal_view_action"
groups="base.group_no_one"/>
</odoo>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.crm.reveal</field>
<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_lead" position="after">
<div class="col-xs-12 col-md-6 o_setting_box" id="crm_reveal">
<div class="o_setting_right_pane">
<label string="IAP Lead Generations" for="action_buy_reveal_iap_credits"/>
<div class="text-muted">
Charge your IAP account to generate Leads/Opportunities from your website's traffic
</div>
<div class="content-group">
<button name="action_buy_reveal_iap_credits" string="Buy IAP Credits" type="object" class="oe_link" icon="fa-arrow-right"/>
</div>
</div>
</div>
</div>
</field>
</record>
</odoo>