summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOdoo's Mergebot <robodoo@odoo.com>2020-08-18 15:24:19 +0200
committerGitHub <noreply@github.com>2020-08-18 15:24:19 +0200
commit0ab08f4d0f7dc7ba2bba3fd91c4c0ff16082f0b0 (patch)
tree5cdaa2830952f6ab27e395b113e2d880998cb9ed
parent14a73fa1dffc50295e59cdaa4db2a8427cfcb040 (diff)
parent8280c7d5598cc52996e0da9fd3a28dc5adc51b72 (diff)
[MERGE] iap_*: extract common feature to technical bridge modules (iap_crm/iap_mail)
PURPOSE Currently several integrations of IAP services within CRM exist. However they do not share anything, leading to duplicated code, fields, and lack of integration. SPECIFICATIONS: IAP ORGANIZATION In this commit we reorganize IAP module to better understand its content and ease future cleaning * have models separated from tools; * rename some tools to find their grep. An iap_ prefix is added to ensure we don't clash with other global functions or methods; * perform some linting; To provide backward compatibility support we keep some import in init file of IAP addon. Standard code is about to be updated but we want to avoid too much issues when migrating code to 13.5 . Compatibility layer will be removed after v14 final freeze. SPECIFICATIONS: IAP_MAIL In this commit we create a bridge module between iap and mail to hold notably some notification data. It includes a template shared by several iap modules. We also move its override in the right file and clearly rename assets file in crm_iap_lead in order to clean a bit module organization. SPECIFICATIONS: IAP_CRM In this commit we create a bridge module between iap_mail and crm to hold notably some fields used in various CRM integrations. Now that we have clean bridge module we can safely update crm and partner integrations dependencies. LINKS Task ID-2280177 Community PR odoo/odoo#53214 Enterprise PR odoo/enterprise#11258 Upgrade PR odoo/upgrade#1363 IAP PR odoo/iap-apps#191 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
-rw-r--r--addons/crm_iap_lead/__manifest__.py13
-rw-r--r--addons/crm_iap_lead/models/__init__.py1
-rw-r--r--addons/crm_iap_lead/models/crm_iap_lead_mining_request.py9
-rw-r--r--addons/crm_iap_lead/models/crm_lead.py1
-rw-r--r--addons/crm_iap_lead/models/ir_model_fields.py18
-rw-r--r--addons/crm_iap_lead/views/assets.xml (renamed from addons/crm_iap_lead/views/crm_iap_lead_templates.xml)0
-rw-r--r--addons/crm_iap_lead/views/mail_templates.xml (renamed from addons/crm_iap_lead/data/message_template.xml)2
-rw-r--r--addons/crm_iap_lead_enrich/__manifest__.py7
-rw-r--r--addons/crm_iap_lead_enrich/models/__init__.py1
-rw-r--r--addons/crm_iap_lead_enrich/models/crm_lead.py7
-rw-r--r--addons/crm_iap_lead_enrich/models/iap_enrich_api.py4
-rw-r--r--addons/crm_iap_lead_enrich/models/ir_model_fields.py18
-rw-r--r--addons/crm_iap_lead_enrich/tests/common.py4
-rw-r--r--addons/crm_iap_lead_website/__manifest__.py10
-rw-r--r--addons/crm_iap_lead_website/models/crm_reveal_rule.py6
-rw-r--r--addons/iap/__init__.py10
-rw-r--r--addons/iap/__manifest__.py14
-rw-r--r--addons/iap/models/__init__.py3
-rw-r--r--addons/iap/models/iap.py256
-rw-r--r--addons/iap/models/iap_account.py120
-rw-r--r--addons/iap/tools/__init__.py4
-rw-r--r--addons/iap/tools/iap_tools.py150
-rw-r--r--addons/iap_crm/__init__.py4
-rw-r--r--addons/iap_crm/__manifest__.py20
-rw-r--r--addons/iap_crm/models/__init__.py4
-rw-r--r--addons/iap_crm/models/crm_lead.py10
-rw-r--r--addons/iap_mail/__manifest__.py21
-rw-r--r--addons/iap_mail/views/mail_templates.xml (renamed from addons/partner_autocomplete/views/additional_info_template.xml)3
-rw-r--r--addons/partner_autocomplete/__manifest__.py10
-rw-r--r--addons/partner_autocomplete/models/res_partner.py10
-rw-r--r--addons/sms/__manifest__.py10
-rw-r--r--addons/sms/models/sms_api.py4
-rw-r--r--addons/snailmail/__manifest__.py7
-rw-r--r--addons/snailmail/models/snailmail_letter.py4
-rw-r--r--doc/webservices/iap.rst42
35 files changed, 438 insertions, 369 deletions
diff --git a/addons/crm_iap_lead/__manifest__.py b/addons/crm_iap_lead/__manifest__.py
index a59d254a678..7cd8e7d4e09 100644
--- a/addons/crm_iap_lead/__manifest__.py
+++ b/addons/crm_iap_lead/__manifest__.py
@@ -3,21 +3,26 @@
{
'name': 'Lead Generation',
- 'summary': 'Create Leads/Opportunities based on country, industries, size, etc.',
+ 'summary': 'Generate Leads/Opportunities based on country, industries, size, etc.',
+ 'version': '1.1',
'category': 'Sales/CRM',
- 'depends': ['iap', 'crm', 'partner_autocomplete'],
+ 'version': '1.1',
+ 'depends': [
+ 'iap_crm',
+ 'iap_mail',
+ ],
'data': [
'data/crm.iap.lead.industry.csv',
'data/crm.iap.lead.role.csv',
'data/crm.iap.lead.seniority.csv',
- 'data/message_template.xml',
'data/crm_iap_lead_data.xml',
'data/ir_sequence_data.xml',
'security/ir.model.access.csv',
+ 'views/assets.xml',
'views/crm_lead_view.xml',
'views/crm_iap_lead_views.xml',
'views/res_config_settings_views.xml',
- 'views/crm_iap_lead_templates.xml',
+ 'views/mail_templates.xml',
],
'qweb': [
'static/src/xml/leads_tree_generate_leads_views.xml',
diff --git a/addons/crm_iap_lead/models/__init__.py b/addons/crm_iap_lead/models/__init__.py
index 1ac91ddbc0c..d529ee24678 100644
--- a/addons/crm_iap_lead/models/__init__.py
+++ b/addons/crm_iap_lead/models/__init__.py
@@ -4,4 +4,3 @@ from . import crm_lead
from . import crm_iap_lead
from . import crm_iap_lead_helpers
from . import crm_iap_lead_mining_request
-from . import ir_model_fields
diff --git a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
index f3bedd5905a..ede89baaf54 100644
--- a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
+++ b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py
@@ -4,8 +4,7 @@
import logging
from odoo import api, fields, models, _
-from odoo.exceptions import ValidationError
-from odoo.addons.iap import jsonrpc, InsufficientCreditError
+from odoo.addons.iap.tools import iap_tools
_logger = logging.getLogger(__name__)
@@ -180,9 +179,9 @@ class CRMLeadMiningRequest(models.Model):
'data': server_payload
}
try:
- response = jsonrpc(endpoint, params=params, timeout=300)
+ response = iap_tools.iap_jsonrpc(endpoint, params=params, timeout=300)
return response['data']
- except InsufficientCreditError as e:
+ except iap_tools.InsufficientCreditError as e:
self.error = 'Insufficient credits. Recharge your account and retry.'
self.state = 'error'
self._cr.commit()
@@ -205,7 +204,7 @@ class CRMLeadMiningRequest(models.Model):
leads = self.env['crm.lead'].create(lead_vals_list)
for lead in leads:
if messages_to_post.get(lead.reveal_id):
- lead.message_post_with_view('partner_autocomplete.enrich_service_information', values=messages_to_post[lead.reveal_id], subtype_id=self.env.ref('mail.mt_note').id)
+ lead.message_post_with_view('iap_mail.enrich_company', values=messages_to_post[lead.reveal_id], subtype_id=self.env.ref('mail.mt_note').id)
# Methods responsible for format response data into valid odoo lead data
@api.model
diff --git a/addons/crm_iap_lead/models/crm_lead.py b/addons/crm_iap_lead/models/crm_lead.py
index bbf70174ef7..eaed1d92bd7 100644
--- a/addons/crm_iap_lead/models/crm_lead.py
+++ b/addons/crm_iap_lead/models/crm_lead.py
@@ -7,5 +7,4 @@ from odoo import fields, models
class Lead(models.Model):
_inherit = 'crm.lead'
- reveal_id = fields.Char(string='Reveal ID', index=True)
lead_mining_request_id = fields.Many2one('crm.iap.lead.mining.request', string='Lead Mining Request', index=True)
diff --git a/addons/crm_iap_lead/models/ir_model_fields.py b/addons/crm_iap_lead/models/ir_model_fields.py
deleted file mode 100644
index 06a7fb6eeb0..00000000000
--- a/addons/crm_iap_lead/models/ir_model_fields.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details
-
-from odoo import models
-
-
-class IrModelFields(models.Model):
- _inherit = 'ir.model.fields'
-
- def unlink(self):
- # Nasty hack to prevent the deletion of shared field reveal_id
- self = self.filtered(
- lambda rec: not (
- rec.model == 'crm.lead'
- and rec.name == 'reveal_id'
- )
- )
- return super(IrModelFields, self).unlink()
diff --git a/addons/crm_iap_lead/views/crm_iap_lead_templates.xml b/addons/crm_iap_lead/views/assets.xml
index 107a1140026..107a1140026 100644
--- a/addons/crm_iap_lead/views/crm_iap_lead_templates.xml
+++ b/addons/crm_iap_lead/views/assets.xml
diff --git a/addons/crm_iap_lead/data/message_template.xml b/addons/crm_iap_lead/views/mail_templates.xml
index 7b7667479a6..dbb4fa1a569 100644
--- a/addons/crm_iap_lead/data/message_template.xml
+++ b/addons/crm_iap_lead/views/mail_templates.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
- <template id="enrich_service_information" inherit_id="partner_autocomplete.enrich_service_information">
+ <template id="enrich_company" inherit_id="iap_mail.enrich_company">
<xpath expr="//div[hasclass('o_partner_autocomplete_enrich_info')]" position="inside">
<t t-if="people_data">
<div style="font-size:16px; margin: 9px 0;">
diff --git a/addons/crm_iap_lead_enrich/__manifest__.py b/addons/crm_iap_lead_enrich/__manifest__.py
index e31676329d1..3c82fa6283c 100644
--- a/addons/crm_iap_lead_enrich/__manifest__.py
+++ b/addons/crm_iap_lead_enrich/__manifest__.py
@@ -4,11 +4,12 @@
{
'name': 'Lead Enrichment',
'summary': 'Enrich Leads/Opportunities using email address domain',
+ 'version': '1.1',
'category': 'Sales/CRM',
+ 'version': '1.1',
'depends': [
- 'iap',
- 'crm',
- 'partner_autocomplete'
+ 'iap_crm',
+ 'iap_mail',
],
'data': [
'data/ir_cron.xml',
diff --git a/addons/crm_iap_lead_enrich/models/__init__.py b/addons/crm_iap_lead_enrich/models/__init__.py
index f1f911179a4..dcb5aa3d8a4 100644
--- a/addons/crm_iap_lead_enrich/models/__init__.py
+++ b/addons/crm_iap_lead_enrich/models/__init__.py
@@ -4,4 +4,3 @@
from . import crm_lead
from . import iap_enrich_api
from . import res_config_settings
-from . import ir_model_fields
diff --git a/addons/crm_iap_lead_enrich/models/crm_lead.py b/addons/crm_iap_lead_enrich/models/crm_lead.py
index 0475750dc32..4f679f6a957 100644
--- a/addons/crm_iap_lead_enrich/models/crm_lead.py
+++ b/addons/crm_iap_lead_enrich/models/crm_lead.py
@@ -5,7 +5,7 @@ import datetime
import logging
from odoo import _, api, fields, models, tools
-from odoo.addons.iap import InsufficientCreditError
+from odoo.addons.iap.tools import iap_tools
_logger = logging.getLogger(__name__)
@@ -13,7 +13,6 @@ _logger = logging.getLogger(__name__)
class Lead(models.Model):
_inherit = 'crm.lead'
- reveal_id = fields.Char(string='Reveal ID', index=True)
iap_enrich_done = fields.Boolean(string='Enrichment done', help='Whether IAP service for lead enrichment based on email has been performed on this lead.')
show_enrich_button = fields.Boolean(string='Allow manual enrich', compute="_compute_show_enrich_button")
@@ -58,7 +57,7 @@ class Lead(models.Model):
if lead_emails:
try:
iap_response = self.env['iap.enrich.api']._request_enrich(lead_emails)
- except InsufficientCreditError:
+ except iap_tools.InsufficientCreditError:
_logger.info('Sent batch %s enrich requests: failed because of credit', len(lead_emails))
if not from_cron:
data = {
@@ -114,7 +113,7 @@ class Lead(models.Model):
template_values = iap_data
template_values['flavor_text'] = _("Lead enriched based on email address")
lead.message_post_with_view(
- 'partner_autocomplete.enrich_service_information',
+ 'iap_mail.enrich_company',
values=template_values,
subtype_id=self.env.ref('mail.mt_note').id
)
diff --git a/addons/crm_iap_lead_enrich/models/iap_enrich_api.py b/addons/crm_iap_lead_enrich/models/iap_enrich_api.py
index 9d6961ee0dc..f6a85d287ed 100644
--- a/addons/crm_iap_lead_enrich/models/iap_enrich_api.py
+++ b/addons/crm_iap_lead_enrich/models/iap_enrich_api.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, api
-from odoo.addons import iap
+from odoo.addons.iap.tools import iap_tools
class IapEnrichAPI(models.AbstractModel):
@@ -17,7 +17,7 @@ class IapEnrichAPI(models.AbstractModel):
params['account_token'] = account.account_token
params['dbuuid'] = dbuuid
base_url = self.env['ir.config_parameter'].sudo().get_param('enrich.endpoint', self._DEFAULT_ENDPOINT)
- return iap.jsonrpc(base_url + local_endpoint, params=params, timeout=300)
+ return iap_tools.iap_jsonrpc(base_url + local_endpoint, params=params, timeout=300)
@api.model
def _request_enrich(self, lead_emails):
diff --git a/addons/crm_iap_lead_enrich/models/ir_model_fields.py b/addons/crm_iap_lead_enrich/models/ir_model_fields.py
deleted file mode 100644
index 06a7fb6eeb0..00000000000
--- a/addons/crm_iap_lead_enrich/models/ir_model_fields.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details
-
-from odoo import models
-
-
-class IrModelFields(models.Model):
- _inherit = 'ir.model.fields'
-
- def unlink(self):
- # Nasty hack to prevent the deletion of shared field reveal_id
- self = self.filtered(
- lambda rec: not (
- rec.model == 'crm.lead'
- and rec.name == 'reveal_id'
- )
- )
- return super(IrModelFields, self).unlink()
diff --git a/addons/crm_iap_lead_enrich/tests/common.py b/addons/crm_iap_lead_enrich/tests/common.py
index ccdc604c12a..38ed094f93f 100644
--- a/addons/crm_iap_lead_enrich/tests/common.py
+++ b/addons/crm_iap_lead_enrich/tests/common.py
@@ -5,7 +5,7 @@ from functools import partial
from unittest.mock import patch
from odoo import exceptions
-from odoo.addons import iap
+from odoo.addons.iap.tools import iap_tools
from odoo.addons.crm_iap_lead_enrich.models.iap_enrich_api import IapEnrichAPI
from odoo.tests import common, new_test_user
@@ -36,7 +36,7 @@ class MockIAPEnrich(common.BaseCase):
result = {}
for lead_id, email in params['domains'].items():
if sim_error and sim_error == 'credit':
- raise iap.InsufficientCreditError('InsufficientCreditError')
+ raise iap_tools.InsufficientCreditError('InsufficientCreditError')
elif 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 ' + local_endpoint
diff --git a/addons/crm_iap_lead_website/__manifest__.py b/addons/crm_iap_lead_website/__manifest__.py
index 13d3e1c0890..17f7c00f92b 100644
--- a/addons/crm_iap_lead_website/__manifest__.py
+++ b/addons/crm_iap_lead_website/__manifest__.py
@@ -3,9 +3,15 @@
{
'name': 'Lead Generation From Website Visits',
- 'summary': 'Create Leads/Opportunities from your website\'s traffic',
+ 'summary': 'Generate Leads/Opportunities from your website\'s traffic',
+ 'version': '1.1',
'category': 'Sales/CRM',
- 'depends': ['iap', 'crm', 'website_form', 'crm_iap_lead'],
+ 'depends': [
+ 'iap_crm',
+ 'iap_mail',
+ 'crm_iap_lead',
+ 'website_form'
+ ],
'data': [
'data/reveal_data.xml',
'security/ir.model.access.csv',
diff --git a/addons/crm_iap_lead_website/models/crm_reveal_rule.py b/addons/crm_iap_lead_website/models/crm_reveal_rule.py
index 58cf4093a9c..698a7c64ce4 100644
--- a/addons/crm_iap_lead_website/models/crm_reveal_rule.py
+++ b/addons/crm_iap_lead_website/models/crm_reveal_rule.py
@@ -9,7 +9,7 @@ from dateutil.relativedelta import relativedelta
import odoo
from odoo import api, fields, models, tools, _
-from odoo.addons.iap import jsonrpc
+from odoo.addons.iap.tools import iap_tools
from odoo.addons.crm.models import crm_stage
from odoo.exceptions import ValidationError
@@ -323,7 +323,7 @@ class CRMRevealRule(models.Model):
'account_token': account_token.account_token,
'data': server_payload
}
- result = jsonrpc(endpoint, params=params, timeout=300)
+ result = iap_tools.iap_jsonrpc(endpoint, params=params, timeout=300)
for res in result.get('reveal_data', []):
if not res.get('not_found'):
lead = self._create_lead_from_response(res)
@@ -365,7 +365,7 @@ class CRMRevealRule(models.Model):
'people_data': result.get('people_data'),
})
lead.message_post_with_view(
- 'partner_autocomplete.enrich_service_information',
+ 'iap_mail.enrich_company',
values=template_values,
subtype_id=self.env.ref('mail.mt_note').id
)
diff --git a/addons/iap/__init__.py b/addons/iap/__init__.py
index 69635445a98..39a74f0331b 100644
--- a/addons/iap/__init__.py
+++ b/addons/iap/__init__.py
@@ -2,4 +2,12 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
-from .models.iap import jsonrpc, charge, authorize, capture, cancel, InsufficientCreditError
+from . import tools
+
+# compatibility imports
+from odoo.addons.iap.tools.iap_tools import iap_jsonrpc as jsonrpc
+from odoo.addons.iap.tools.iap_tools import iap_authorize as authorize
+from odoo.addons.iap.tools.iap_tools import iap_cancel as cancel
+from odoo.addons.iap.tools.iap_tools import iap_capture as capture
+from odoo.addons.iap.tools.iap_tools import iap_charge as charge
+from odoo.addons.iap.tools.iap_tools import InsufficientCreditError
diff --git a/addons/iap/__manifest__.py b/addons/iap/__manifest__.py
index ac86a8718fc..5d13d6739bd 100644
--- a/addons/iap/__manifest__.py
+++ b/addons/iap/__manifest__.py
@@ -1,15 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
{
'name': 'In-App Purchases',
'category': 'Hidden/Tools',
+ 'version': '1.1',
'summary': 'Basic models and helpers to support In-App purchases.',
'description': """
-This module provides standard tools (account model, context manager and helpers) to support In-App purchases inside Odoo.
-""",
- 'depends': ['web', 'base_setup'],
+This module provides standard tools (account model, context manager and helpers)
+to support In-App purchases inside Odoo. """,
+ 'depends': [
+ 'web',
+ 'base_setup'
+ ],
'data': [
'security/ir.model.access.csv',
'security/ir_rule.xml',
@@ -17,9 +20,6 @@ This module provides standard tools (account model, context manager and helpers)
'views/iap_views.xml',
'views/res_config_settings.xml',
],
- 'images': [
- 'static/src/img/iap_logo.svg',
- ],
'qweb': [
'static/src/xml/iap_templates.xml',
],
diff --git a/addons/iap/models/__init__.py b/addons/iap/models/__init__.py
index 22e8f027832..d148377834f 100644
--- a/addons/iap/models/__init__.py
+++ b/addons/iap/models/__init__.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from . import iap
+from . import iap_account
from . import res_config_settings
-
diff --git a/addons/iap/models/iap.py b/addons/iap/models/iap.py
deleted file mode 100644
index eb235a0ab5f..00000000000
--- a/addons/iap/models/iap.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# -*- coding: utf-8 -*-
-import contextlib
-import logging
-import json
-import uuid
-
-import werkzeug.urls
-import requests
-
-from odoo import api, fields, models, exceptions, _
-from odoo.tools import pycompat
-
-_logger = logging.getLogger(__name__)
-
-DEFAULT_ENDPOINT = 'https://iap.odoo.com'
-
-
-#----------------------------------------------------------
-# Helpers for both clients and proxy
-#----------------------------------------------------------
-def get_endpoint(env):
- url = env['ir.config_parameter'].sudo().get_param('iap.endpoint', DEFAULT_ENDPOINT)
- return url
-
-
-#----------------------------------------------------------
-# Helpers for clients
-#----------------------------------------------------------
-class InsufficientCreditError(Exception):
- pass
-
-
-class AuthenticationError(Exception):
- pass
-
-
-def jsonrpc(url, method='call', params=None, timeout=15):
- """
- Calls the provided JSON-RPC endpoint, unwraps the result and
- returns JSON-RPC errors as exceptions.
- """
- payload = {
- 'jsonrpc': '2.0',
- 'method': method,
- 'params': params,
- 'id': uuid.uuid4().hex,
- }
-
- _logger.info('iap jsonrpc %s', url)
- try:
- req = requests.post(url, json=payload, timeout=timeout)
- req.raise_for_status()
- response = req.json()
- if 'error' in response:
- name = response['error']['data'].get('name').rpartition('.')[-1]
- message = response['error']['data'].get('message')
- if name == 'InsufficientCreditError':
- e_class = InsufficientCreditError
- elif name == 'AccessError':
- e_class = exceptions.AccessError
- elif name == 'UserError':
- e_class = exceptions.UserError
- else:
- raise requests.exceptions.ConnectionError()
- e = e_class(message)
- e.data = response['error']['data']
- raise e
- return response.get('result')
- except (ValueError, requests.exceptions.ConnectionError, requests.exceptions.MissingSchema, requests.exceptions.Timeout, requests.exceptions.HTTPError) as e:
- 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 %s', url)
- )
-
-#----------------------------------------------------------
-# Helpers for proxy
-#----------------------------------------------------------
-class IapTransaction(object):
-
- def __init__(self):
- self.credit = None
-
-def authorize(env, key, account_token, credit, dbuuid=False, description=None, credit_template=None):
- endpoint = get_endpoint(env)
- params = {
- 'account_token': account_token,
- 'credit': credit,
- 'key': key,
- 'description': description,
- }
- if dbuuid:
- params.update({'dbuuid': dbuuid})
- try:
- transaction_token = jsonrpc(endpoint + '/iap/1/authorize', params=params)
- except InsufficientCreditError as e:
- if credit_template:
- arguments = json.loads(e.args[0])
- arguments['body'] = pycompat.to_text(env['ir.qweb']._render(credit_template))
- e.args = (json.dumps(arguments),)
- raise e
- return transaction_token
-
-def cancel(env, transaction_token, key):
- endpoint = get_endpoint(env)
- params = {
- 'token': transaction_token,
- 'key': key,
- }
- r = jsonrpc(endpoint + '/iap/1/cancel', params=params)
- return r
-
-def capture(env, transaction_token, key, credit):
- endpoint = get_endpoint(env)
- params = {
- 'token': transaction_token,
- 'key': key,
- 'credit_to_capture': credit,
- }
- r = jsonrpc(endpoint + '/iap/1/capture', params=params)
- return r
-
-
-@contextlib.contextmanager
-def charge(env, key, account_token, credit, dbuuid=False, description=None, credit_template=None):
- """
- Account charge context manager: takes a hold for ``credit``
- amount before executing the body, then captures it if there
- is no error, or cancels it if the body generates an exception.
-
- :param str key: service identifier
- :param str account_token: user identifier
- :param int credit: cost of the body's operation
- :param description: a description of the purpose of the charge,
- the user will be able to see it in their
- dashboard
- :type description: str
- :param credit_template: a QWeb template to render and show to the
- user if their account does not have enough
- credits for the requested operation
- :type credit_template: str
- """
- transaction_token = authorize(env, key, account_token, credit, dbuuid, description, credit_template)
- try:
- transaction = IapTransaction()
- transaction.credit = credit
- yield transaction
- except Exception as e:
- r = cancel(env,transaction_token, key)
- raise e
- else:
- r = capture(env,transaction_token, key, transaction.credit)
-
-#----------------------------------------------------------
-# Models for client
-#----------------------------------------------------------
-class IapAccount(models.Model):
- _name = 'iap.account'
- _rec_name = 'service_name'
- _description = 'IAP Account'
-
- service_name = fields.Char()
- account_token = fields.Char(default=lambda s: uuid.uuid4().hex)
- company_ids = fields.Many2many('res.company')
-
- @api.model
- def get(self, service_name, force_create=True):
- domain = [
- ('service_name', '=', service_name),
- '|',
- ('company_ids', 'in', self.env.companies.ids),
- ('company_ids', '=', False)
- ]
- accounts = self.search(domain, order='id desc')
- if not accounts:
- with self.pool.cursor() as cr:
- # Since the account did not exist yet, we will encounter a NoCreditError,
- # which is going to rollback the database and undo the account creation,
- # preventing the process to continue any further.
-
- # Flush the pending operations to avoid a deadlock.
- self.flush()
- IapAccount = self.with_env(self.env(cr=cr))
- account = IapAccount.search(domain, order='id desc', limit=1)
- if not account:
- if not force_create:
- return account
- account = IapAccount.create({'service_name': service_name})
- # fetch 'account_token' into cache with this cursor,
- # as self's cursor cannot see this account
- account_token = account.account_token
- account = self.browse(account.id)
- self.env.cache.set(account, IapAccount._fields['account_token'], account_token)
- return account
- accounts_with_company = accounts.filtered(lambda acc: acc.company_ids)
- if accounts_with_company:
- return accounts_with_company[0]
- return accounts[0]
-
- @api.model
- def get_credits_url(self, service_name, base_url='', credit=0, trial=False):
- dbuuid = self.env['ir.config_parameter'].sudo().get_param('database.uuid')
- if not base_url:
- endpoint = get_endpoint(self.env)
- route = '/iap/1/credit'
- base_url = endpoint + route
- account_token = self.get(service_name).account_token
- d = {
- 'dbuuid': dbuuid,
- 'service_name': service_name,
- 'account_token': account_token,
- 'credit': credit,
- }
- if trial:
- d.update({'trial': trial})
- return '%s?%s' % (base_url, werkzeug.urls.url_encode(d))
-
- @api.model
- def get_account_url(self):
- route = '/iap/services'
- endpoint = get_endpoint(self.env)
- d = {'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid')}
-
- return '%s?%s' % (endpoint + route, werkzeug.urls.url_encode(d))
-
- @api.model
- def get_config_account_url(self):
- account = self.env['iap.account'].get('partner_autocomplete')
- action = self.env.ref('iap.iap_account_action')
- menu = self.env.ref('iap.iap_account_menu')
- no_one = self.user_has_groups('base.group_no_one')
- if account:
- url = "/web#id=%s&action=%s&model=iap.account&view_type=form&menu_id=%s" % (account.id, action.id, menu.id)
- else:
- url = "/web#action=%s&model=iap.account&view_type=form&menu_id=%s" % (action.id, menu.id)
- return no_one and url
-
- @api.model
- def get_credits(self, service_name):
- account = self.get(service_name, force_create=False)
- credit = 0
-
- if account:
- route = '/iap/1/balance'
- endpoint = get_endpoint(self.env)
- url = endpoint + route
- params = {
- 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'),
- 'account_token': account.account_token,
- 'service_name': service_name,
- }
- try:
- credit = jsonrpc(url=url, params=params)
- except Exception as e:
- _logger.info('Get credit error : %s', str(e))
- credit = -1
-
- return credit
diff --git a/addons/iap/models/iap_account.py b/addons/iap/models/iap_account.py
new file mode 100644
index 00000000000..f4be36c7dd4
--- /dev/null
+++ b/addons/iap/models/iap_account.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import logging
+import uuid
+import werkzeug.urls
+
+from odoo import api, fields, models
+from odoo.addons.iap.tools import iap_tools
+
+_logger = logging.getLogger(__name__)
+
+DEFAULT_ENDPOINT = 'https://iap.odoo.com'
+
+
+class IapAccount(models.Model):
+ _name = 'iap.account'
+ _rec_name = 'service_name'
+ _description = 'IAP Account'
+
+ service_name = fields.Char()
+ account_token = fields.Char(default=lambda s: uuid.uuid4().hex)
+ company_ids = fields.Many2many('res.company')
+
+ @api.model
+ def get(self, service_name, force_create=True):
+ domain = [
+ ('service_name', '=', service_name),
+ '|',
+ ('company_ids', 'in', self.env.companies.ids),
+ ('company_ids', '=', False)
+ ]
+ accounts = self.search(domain, order='id desc')
+ if not accounts:
+ with self.pool.cursor() as cr:
+ # Since the account did not exist yet, we will encounter a NoCreditError,
+ # which is going to rollback the database and undo the account creation,
+ # preventing the process to continue any further.
+
+ # Flush the pending operations to avoid a deadlock.
+ self.flush()
+ IapAccount = self.with_env(self.env(cr=cr))
+ account = IapAccount.search(domain, order='id desc', limit=1)
+ if not account:
+ if not force_create:
+ return account
+ account = IapAccount.create({'service_name': service_name})
+ # fetch 'account_token' into cache with this cursor,
+ # as self's cursor cannot see this account
+ account_token = account.account_token
+ account = self.browse(account.id)
+ self.env.cache.set(account, IapAccount._fields['account_token'], account_token)
+ return account
+ accounts_with_company = accounts.filtered(lambda acc: acc.company_ids)
+ if accounts_with_company:
+ return accounts_with_company[0]
+ return accounts[0]
+
+ @api.model
+ def get_credits_url(self, service_name, base_url='', credit=0, trial=False):
+ """ Called notably by ajax crash manager, buy more widget, partner_autocomplete, sanilmail. """
+ dbuuid = self.env['ir.config_parameter'].sudo().get_param('database.uuid')
+ if not base_url:
+ endpoint = iap_tools.iap_get_endpoint(self.env)
+ route = '/iap/1/credit'
+ base_url = endpoint + route
+ account_token = self.get(service_name).account_token
+ d = {
+ 'dbuuid': dbuuid,
+ 'service_name': service_name,
+ 'account_token': account_token,
+ 'credit': credit,
+ }
+ if trial:
+ d.update({'trial': trial})
+ return '%s?%s' % (base_url, werkzeug.urls.url_encode(d))
+
+ @api.model
+ def get_account_url(self):
+ """ Called only by res settings """
+ route = '/iap/services'
+ endpoint = iap_tools.iap_get_endpoint(self.env)
+ d = {'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid')}
+
+ return '%s?%s' % (endpoint + route, werkzeug.urls.url_encode(d))
+
+ @api.model
+ def get_config_account_url(self):
+ """ Called notably by ajax partner_autocomplete. """
+ account = self.env['iap.account'].get('partner_autocomplete')
+ action = self.env.ref('iap.iap_account_action')
+ menu = self.env.ref('iap.iap_account_menu')
+ no_one = self.user_has_groups('base.group_no_one')
+ if account:
+ url = "/web#id=%s&action=%s&model=iap.account&view_type=form&menu_id=%s" % (account.id, action.id, menu.id)
+ else:
+ url = "/web#action=%s&model=iap.account&view_type=form&menu_id=%s" % (action.id, menu.id)
+ return no_one and url
+
+ @api.model
+ def get_credits(self, service_name):
+ account = self.get(service_name, force_create=False)
+ credit = 0
+
+ if account:
+ route = '/iap/1/balance'
+ endpoint = iap_tools.iap_get_endpoint(self.env)
+ url = endpoint + route
+ params = {
+ 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'),
+ 'account_token': account.account_token,
+ 'service_name': service_name,
+ }
+ try:
+ credit = iap_tools.iap_jsonrpc(url=url, params=params)
+ except Exception as e:
+ _logger.info('Get credit error : %s', str(e))
+ credit = -1
+
+ return credit
diff --git a/addons/iap/tools/__init__.py b/addons/iap/tools/__init__.py
new file mode 100644
index 00000000000..d2ad04683aa
--- /dev/null
+++ b/addons/iap/tools/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import iap_tools
diff --git a/addons/iap/tools/iap_tools.py b/addons/iap/tools/iap_tools.py
new file mode 100644
index 00000000000..da17972f0f1
--- /dev/null
+++ b/addons/iap/tools/iap_tools.py
@@ -0,0 +1,150 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import contextlib
+import logging
+import json
+import requests
+import uuid
+
+from odoo import exceptions, _
+from odoo.tools import pycompat
+
+_logger = logging.getLogger(__name__)
+
+DEFAULT_ENDPOINT = 'https://iap.odoo.com'
+
+#----------------------------------------------------------
+# Helpers for both clients and proxy
+#----------------------------------------------------------
+
+def iap_get_endpoint(env):
+ url = env['ir.config_parameter'].sudo().get_param('iap.endpoint', DEFAULT_ENDPOINT)
+ return url
+
+#----------------------------------------------------------
+# Helpers for clients
+#----------------------------------------------------------
+
+class InsufficientCreditError(Exception):
+ pass
+
+
+def iap_jsonrpc(url, method='call', params=None, timeout=15):
+ """
+ Calls the provided JSON-RPC endpoint, unwraps the result and
+ returns JSON-RPC errors as exceptions.
+ """
+ payload = {
+ 'jsonrpc': '2.0',
+ 'method': method,
+ 'params': params,
+ 'id': uuid.uuid4().hex,
+ }
+
+ _logger.info('iap jsonrpc %s', url)
+ try:
+ req = requests.post(url, json=payload, timeout=timeout)
+ req.raise_for_status()
+ response = req.json()
+ if 'error' in response:
+ name = response['error']['data'].get('name').rpartition('.')[-1]
+ message = response['error']['data'].get('message')
+ if name == 'InsufficientCreditError':
+ e_class = InsufficientCreditError
+ elif name == 'AccessError':
+ e_class = exceptions.AccessError
+ elif name == 'UserError':
+ e_class = exceptions.UserError
+ else:
+ raise requests.exceptions.ConnectionError()
+ e = e_class(message)
+ e.data = response['error']['data']
+ raise e
+ return response.get('result')
+ except (ValueError, requests.exceptions.ConnectionError, requests.exceptions.MissingSchema, requests.exceptions.Timeout, requests.exceptions.HTTPError) as e:
+ 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 %s', url)
+ )
+
+#----------------------------------------------------------
+# Helpers for proxy
+#----------------------------------------------------------
+
+class IapTransaction(object):
+
+ def __init__(self):
+ self.credit = None
+
+
+def iap_authorize(env, key, account_token, credit, dbuuid=False, description=None, credit_template=None):
+ endpoint = iap_get_endpoint(env)
+ params = {
+ 'account_token': account_token,
+ 'credit': credit,
+ 'key': key,
+ 'description': description,
+ }
+ if dbuuid:
+ params.update({'dbuuid': dbuuid})
+ try:
+ transaction_token = iap_jsonrpc(endpoint + '/iap/1/authorize', params=params)
+ except InsufficientCreditError as e:
+ if credit_template:
+ arguments = json.loads(e.args[0])
+ arguments['body'] = pycompat.to_text(env['ir.qweb']._render(credit_template))
+ e.args = (json.dumps(arguments),)
+ raise e
+ return transaction_token
+
+
+def iap_cancel(env, transaction_token, key):
+ endpoint = iap_get_endpoint(env)
+ params = {
+ 'token': transaction_token,
+ 'key': key,
+ }
+ r = iap_jsonrpc(endpoint + '/iap/1/cancel', params=params)
+ return r
+
+
+def iap_capture(env, transaction_token, key, credit):
+ endpoint = iap_get_endpoint(env)
+ params = {
+ 'token': transaction_token,
+ 'key': key,
+ 'credit_to_capture': credit,
+ }
+ r = iap_jsonrpc(endpoint + '/iap/1/capture', params=params)
+ return r
+
+
+@contextlib.contextmanager
+def iap_charge(env, key, account_token, credit, dbuuid=False, description=None, credit_template=None):
+ """
+ Account charge context manager: takes a hold for ``credit``
+ amount before executing the body, then captures it if there
+ is no error, or cancels it if the body generates an exception.
+
+ :param str key: service identifier
+ :param str account_token: user identifier
+ :param int credit: cost of the body's operation
+ :param description: a description of the purpose of the charge,
+ the user will be able to see it in their
+ dashboard
+ :type description: str
+ :param credit_template: a QWeb template to render and show to the
+ user if their account does not have enough
+ credits for the requested operation
+ :type credit_template: str
+ """
+ transaction_token = iap_authorize(env, key, account_token, credit, dbuuid, description, credit_template)
+ try:
+ transaction = IapTransaction()
+ transaction.credit = credit
+ yield transaction
+ except Exception as e:
+ r = iap_cancel(env,transaction_token, key)
+ raise e
+ else:
+ r = iap_capture(env,transaction_token, key, transaction.credit)
diff --git a/addons/iap_crm/__init__.py b/addons/iap_crm/__init__.py
new file mode 100644
index 00000000000..dc5e6b693d1
--- /dev/null
+++ b/addons/iap_crm/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import models
diff --git a/addons/iap_crm/__manifest__.py b/addons/iap_crm/__manifest__.py
new file mode 100644
index 00000000000..4f17c4ce3fc
--- /dev/null
+++ b/addons/iap_crm/__manifest__.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+
+{
+ 'name': "IAP / CRM",
+ 'summary': """Bridge between IAP and CRM""",
+ 'description': """Bridge between IAP and CRM""",
+ 'category': 'Hidden/Tools',
+ 'version': '1.0',
+ 'depends': [
+ 'crm',
+ 'iap_mail',
+ ],
+ 'application': False,
+ 'installable': True,
+ 'auto_install': True,
+ 'data': [
+ ],
+}
diff --git a/addons/iap_crm/models/__init__.py b/addons/iap_crm/models/__init__.py
new file mode 100644
index 00000000000..00140f99c9f
--- /dev/null
+++ b/addons/iap_crm/models/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import crm_lead
diff --git a/addons/iap_crm/models/crm_lead.py b/addons/iap_crm/models/crm_lead.py
new file mode 100644
index 00000000000..c45d9da847d
--- /dev/null
+++ b/addons/iap_crm/models/crm_lead.py
@@ -0,0 +1,10 @@
+# -*- 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_id = fields.Char(string='Reveal ID', help="Technical ID of reveal request done by IAP.")
diff --git a/addons/iap_mail/__manifest__.py b/addons/iap_mail/__manifest__.py
new file mode 100644
index 00000000000..aa4f60b867a
--- /dev/null
+++ b/addons/iap_mail/__manifest__.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+
+{
+ 'name': "IAP / Mail",
+ 'summary': """Bridge between IAP and mail""",
+ 'description': """Bridge between IAP and mail""",
+ 'category': 'Hidden/Tools',
+ 'version': '1.0',
+ 'depends': [
+ 'iap',
+ 'mail',
+ ],
+ 'application': False,
+ 'installable': True,
+ 'auto_install': True,
+ 'data': [
+ 'views/mail_templates.xml',
+ ],
+}
diff --git a/addons/partner_autocomplete/views/additional_info_template.xml b/addons/iap_mail/views/mail_templates.xml
index 970e10edcf9..4d4daad4dec 100644
--- a/addons/partner_autocomplete/views/additional_info_template.xml
+++ b/addons/iap_mail/views/mail_templates.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
- <template id="enrich_service_information">
+
+ <template id="enrich_company">
<p t-esc="flavor_text" />
<div class="o_partner_autocomplete_enrich_info bg-white p-3 mt-3 mb-3 mr-5">
<div class="col-12 row p-0 m-0">
diff --git a/addons/partner_autocomplete/__manifest__.py b/addons/partner_autocomplete/__manifest__.py
index 4f898adc995..92ce812ee40 100644
--- a/addons/partner_autocomplete/__manifest__.py
+++ b/addons/partner_autocomplete/__manifest__.py
@@ -1,19 +1,23 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+
{
'name': "Partner Autocomplete",
'summary': "Auto-complete partner companies' data",
+ 'version': '1.1',
'description': """
Auto-complete partner companies' data
""",
'author': "Odoo SA",
'category': 'Hidden/Tools',
'version': '1.0',
-
- 'depends': ['web', 'mail', 'iap'],
+ 'depends': [
+ 'iap_mail',
+ ],
'data': [
'security/ir.model.access.csv',
'views/partner_autocomplete_assets.xml',
- 'views/additional_info_template.xml',
'views/res_partner_views.xml',
'views/res_company_views.xml',
'views/res_config_settings_views.xml',
diff --git a/addons/partner_autocomplete/models/res_partner.py b/addons/partner_autocomplete/models/res_partner.py
index 27113317cd9..d53fcf2dfc9 100644
--- a/addons/partner_autocomplete/models/res_partner.py
+++ b/addons/partner_autocomplete/models/res_partner.py
@@ -4,9 +4,9 @@
import logging
import json
from odoo import api, fields, models, exceptions, _
-from odoo.addons.iap import jsonrpc
+from odoo.addons.iap.tools import iap_tools
+# TDE FIXME: check those errors at iap level ?
from requests.exceptions import ConnectionError, HTTPError
-from odoo.addons.iap.models.iap import InsufficientCreditError
_logger = logging.getLogger(__name__)
@@ -96,11 +96,11 @@ class ResPartner(models.Model):
'zip': self.env.company.zip,
})
try:
- return jsonrpc(url=url, params=params, timeout=timeout), False
+ return iap_tools.iap_jsonrpc(url=url, params=params, timeout=timeout), False
except (ConnectionError, HTTPError, exceptions.AccessError, exceptions.UserError) as exception:
_logger.error('Autocomplete API error: %s' % str(exception))
return False, str(exception)
- except InsufficientCreditError as exception:
+ except iap_tools.InsufficientCreditError as exception:
_logger.warning('Insufficient Credits for Autocomplete Service: %s' % str(exception))
return False, 'Insufficient Credit'
@@ -187,7 +187,7 @@ class ResPartner(models.Model):
template_values = json.loads(partners.additional_info)
template_values['flavor_text'] = _("Partner created by Odoo Partner Autocomplete Service")
partners.message_post_with_view(
- 'partner_autocomplete.enrich_service_information',
+ 'iap_mail.enrich_company',
values=template_values,
subtype_id=self.env.ref('mail.mt_note').id,
)
diff --git a/addons/sms/__manifest__.py b/addons/sms/__manifest__.py
index bb68d2fec7b..086087b5c2d 100644
--- a/addons/sms/__manifest__.py
+++ b/addons/sms/__manifest__.py
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
{
'name': 'SMS gateway',
- 'version': '2.0',
+ 'version': '2.1',
'category': 'Hidden/Tools',
'summary': 'SMS Text Messaging',
'description': """
@@ -11,7 +12,12 @@ This module gives a framework for SMS text messaging
The service is provided by the In App Purchase Odoo platform.
""",
- 'depends': ['base', 'iap', 'mail', 'phone_validation'],
+ 'depends': [
+ 'base',
+ 'iap_mail',
+ 'mail',
+ 'phone_validation'
+ ],
'data': [
'data/ir_cron_data.xml',
'wizard/sms_cancel_views.xml',
diff --git a/addons/sms/models/sms_api.py b/addons/sms/models/sms_api.py
index 6856717a0c2..b1fa69dab6c 100644
--- a/addons/sms/models/sms_api.py
+++ b/addons/sms/models/sms_api.py
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models
-from odoo.addons.iap.models import iap
+from odoo.addons.iap.tools import iap_tools
DEFAULT_ENDPOINT = 'https://iap-sms.odoo.com'
@@ -17,7 +17,7 @@ class SmsApi(models.AbstractModel):
params['account_token'] = account.account_token
endpoint = self.env['ir.config_parameter'].sudo().get_param('sms.endpoint', DEFAULT_ENDPOINT)
# TODO PRO, the default timeout is 15, do we have to increase it ?
- return iap.jsonrpc(endpoint + local_endpoint, params=params)
+ return iap_tools.iap_jsonrpc(endpoint + local_endpoint, params=params)
@api.model
def _send_sms(self, numbers, message):
diff --git a/addons/snailmail/__manifest__.py b/addons/snailmail/__manifest__.py
index 20976fe25d2..dd86463f0ff 100644
--- a/addons/snailmail/__manifest__.py
+++ b/addons/snailmail/__manifest__.py
@@ -6,8 +6,11 @@ Allows users to send documents by post
=====================================================
""",
'category': 'Hidden/Tools',
- 'version': '0.2',
- 'depends': ['iap', 'mail'],
+ 'version': '0.3',
+ 'depends': [
+ 'iap_mail',
+ 'mail'
+ ],
'data': [
'data/snailmail_data.xml',
'views/report_assets.xml',
diff --git a/addons/snailmail/models/snailmail_letter.py b/addons/snailmail/models/snailmail_letter.py
index e60286cec9e..2eb19271b3c 100644
--- a/addons/snailmail/models/snailmail_letter.py
+++ b/addons/snailmail/models/snailmail_letter.py
@@ -4,7 +4,7 @@ import re
import base64
from odoo import fields, models, api, _
-from odoo.addons.iap import jsonrpc
+from odoo.addons.iap.tools import iap_tools
from odoo.tools.safe_eval import safe_eval
DEFAULT_ENDPOINT = 'https://iap-snailmail.odoo.com'
@@ -335,7 +335,7 @@ class SnailmailLetter(models.Model):
endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT)
timeout = int(self.env['ir.config_parameter'].sudo().get_param('snailmail.timeout', DEFAULT_TIMEOUT))
params = self._snailmail_create('print')
- response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params, timeout=timeout)
+ response = iap_tools.iap_jsonrpc(endpoint + PRINT_ENDPOINT, params=params, timeout=timeout)
for doc in response['request']['documents']:
if doc.get('sent') and response['request_code'] == 200:
note = _('The document was correctly sent by post.<br>The tracking id is %s', doc['send_id'])
diff --git a/doc/webservices/iap.rst b/doc/webservices/iap.rst
index 5af45ef7ae3..ce2512c58ad 100644
--- a/doc/webservices/iap.rst
+++ b/doc/webservices/iap.rst
@@ -289,9 +289,9 @@ server*.
There are no requirements when it comes to the server or the communication
protocol between the app and our server, but ``iap`` provides a
-:func:`~odoo.addons.iap.jsonrpc` helper to call a JSON-RPC2_ endpoint on an
+:func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` helper to call a JSON-RPC2_ endpoint on an
other Odoo instance and transparently re-raise relevant Odoo exceptions
-(:class:`~odoo.addons.iap.models.iap.InsufficientCreditError`,
+(:class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError`,
:class:`odoo.exceptions.AccessError` and :class:`odoo.exceptions.UserError`).
In that call, we will need to provide:
@@ -308,17 +308,17 @@ In that call, we will need to provide:
.. note::
``iap`` automatically handles
- :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` coming from the action
+ :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` coming from the action
and prompts the user to add credits to their account.
- :func:`~odoo.addons.iap.jsonrpc` takes care of re-raising
+ :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` takes care of re-raising
:class:`~odoo.addons.iap.models.iap.InsufficientCreditError` for you.
.. danger::
- If you are not using :func:`~odoo.addons.iap.jsonrpc` you *must* be
+ If you are not using :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc` you *must* be
careful to re-raise
- :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` in your handler
+ :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` in your handler
otherwise the user will not be prompted to credit their account, and the
next call will fail the same way.
@@ -330,14 +330,14 @@ Service
.. queue:: iap_service/series
Though that is not *required*, since ``iap`` provides both a client helper
-for JSON-RPC2_ calls (:func:`~odoo.addons.iap.jsonrpc`) and a service helper
-for transactions (:class:`~odoo.addons.iap.models.iap.charge`) we will also be
+for JSON-RPC2_ calls (:func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc`) and a service helper
+for transactions (:class:`~odoo.addons.iap.tools.iap_tools.iap_charge`) we will also be
implementing the service side as an Odoo module:
.. patch::
Since the query from the client comes as JSON-RPC2_ we will need the
-corresponding controller which can call :class:`~odoo.addons.iap.models.iap.charge` and
+corresponding controller which can call :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` and
perform the service within:
.. patch::
@@ -347,7 +347,7 @@ perform the service within:
.. todo:: "My Account" > "Your InApp Services"?
-The :class:`~odoo.addons.iap.models.iap.charge` helper will:
+The :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` helper will:
1. authorize (create) a transaction with the specified number of credits,
if the account does not have enough credits it will raise the relevant
@@ -361,7 +361,7 @@ The :class:`~odoo.addons.iap.models.iap.charge` helper will:
.. danger::
- By default, :class:`~odoo.addons.iap.models.iap.charge` contacts the *production*
+ By default, :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` contacts the *production*
IAP endpoint, https://iap.odoo.com. While developing and testing your
service you may want to point it towards the *development* IAP endpoint
https://iap-sandbox.odoo.com.
@@ -371,7 +371,7 @@ The :class:`~odoo.addons.iap.models.iap.charge` helper will:
Parameters --> System Parameters`, just define an entry for the key
``iap.endpoint`` if none already exists).
-The :class:`~odoo.addons.iap.models.iap.charge` helper has two additional optional
+The :class:`~odoo.addons.iap.tools.iap_tools.iap_charge` helper has two additional optional
parameters we can use to make things clearer to the end-user.
``description``
@@ -543,7 +543,7 @@ care how they are implemented.
Transaction identifier, returned by the authorization process and consumed
by either capturing or cancelling the transaction.
-.. exception:: odoo.addons.iap.models.iap.InsufficientCreditError
+.. exception:: odoo.addons.iap.tools.iap_tools.InsufficientCreditError
Raised during transaction authorization if the credits requested are not
currently available on the account (either not enough credits or too many
@@ -555,7 +555,7 @@ care how they are implemented.
Raised by:
* any operation to which a service token is required, if the service token is invalid; or
- * any failure in an inter-server call. (typically, in :func:`~odoo.addons.iap.jsonrpc`).
+ * any failure in an inter-server call. (typically, in :func:`~odoo.addons.iap.tools.iap_tools.iap_jsonrpc`).
.. exception:: odoo.exceptions.UserError
:noindex:
@@ -576,9 +576,9 @@ In order to test the developped app, we propose a sandbox platform that allows y
The latter consists in specific tokens that will work on **IAP-Sandbox only**.
* Token ``000000``: Represents a non-existing account. Returns
- an :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` on authorize attempt.
+ an :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` on authorize attempt.
* Token ``000111``: Represents an account without sufficient credits to perform any service.
- Returns an :class:`~odoo.addons.iap.models.iap.InsufficientCreditError` on authorize attempt.
+ Returns an :class:`~odoo.addons.iap.tools.iap_tools.InsufficientCreditError` on authorize attempt.
* Token ``111111``: Represents an account with enough credits to perform any service.
An authorize attempt will return a dummy transacion token that is processed by the capture
and cancel routes.
@@ -600,7 +600,7 @@ module provides a few helpers to make IAP flow even simpler.
Charging
--------
-.. class:: odoo.addons.iap.models.iap.charge(env, key, account_token, credit[, dbuuid, description, credit_template])
+.. class:: odoo.addons.iap.tools.iap_tools.iap_charge(env, key, account_token, credit[, dbuuid, description, credit_template])
A *context manager* for authorizing and automatically capturing or
cancelling transactions for use in the backend/proxy.
@@ -633,7 +633,7 @@ Charging
"""
credits = int(MAXIMUM_POWER * factor)
description = "We will demonstrate the power of this station on your home planet of Alderaan."
- with charge(request.env, SERVICE_KEY, user_account, credits, description) as transaction:
+ with iap_charge(request.env, SERVICE_KEY, user_account, credits, description) as transaction:
# TODO: allow other targets
transaction.credit = max(credits, 2)
# Sales ongoing one the energy price,
@@ -647,7 +647,7 @@ Charging
Authorize
---------
-.. class:: odoo.addons.iap.models.iap.authorize(env, key, account_token, credit[, dbuuid, description, credit_template])
+.. class:: odoo.addons.iap.tools.iap_tools.iap_authorize(env, key, account_token, credit[, dbuuid, description, credit_template])
Will authorize everything.
@@ -688,7 +688,7 @@ Authorize
Cancel
------
-.. class:: odoo.addons.iap.models.iap.cancel(env, transaction_token, key)
+.. class:: odoo.addons.iap.tools.iap_tools.iap_cancel(env, transaction_token, key)
Will cancel an authorized transaction.
@@ -726,7 +726,7 @@ Cancel
Capture
-------
-.. class:: odoo.addons.iap.models.iap.capture(env, transaction_token, key, credit)
+.. class:: odoo.addons.iap.tools.iap_tools.iap_capture(env, transaction_token, key, credit)
Will capture the amount ``credit`` on the given transaction.