Files
odoo_source/addons/partner_autocomplete/models/res_partner.py
T
Thibault Delavallée 323890f7ea [ADD] iap_mail: bridge between mail and iap
PURPOSE

Clean and improve IAP services integration in Odoo. Clean IAP integrations
tools and improve data sharing with base modules, notably for CRM and Partner.

SPECIFICATIONS

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.

LINKS

Task ID-2248367
Community PR odoo/odoo#53214
Enterprise PR odoo/enterprise#11258
Upgrade PR odoo/upgrade#1363
IAP PR odoo/iap-apps#191rade#
2020-08-18 11:41:59 +00:00

204 lines
7.5 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import json
from odoo import api, fields, models, exceptions, _
from odoo.addons.iap.tools import iap_tools
# TDE FIXME: check those errors at iap level ?
from requests.exceptions import ConnectionError, HTTPError
_logger = logging.getLogger(__name__)
DEFAULT_ENDPOINT = 'https://partner-autocomplete.odoo.com'
class ResPartner(models.Model):
_name = 'res.partner'
_inherit = 'res.partner'
partner_gid = fields.Integer('Company database ID')
additional_info = fields.Char('Additional info')
@api.model
def _replace_location_code_by_id(self, record):
record['country_id'], record['state_id'] = self._find_country_data(
state_code=record.pop('state_code', False),
state_name=record.pop('state_name', False),
country_code=record.pop('country_code', False),
country_name=record.pop('country_name', False)
)
return record
@api.model
def _format_data_company(self, company):
self._replace_location_code_by_id(company)
if company.get('child_ids'):
child_ids = []
for child in company.get('child_ids'):
child_ids.append(self._replace_location_code_by_id(child))
company['child_ids'] = child_ids
if company.get('additional_info'):
company['additional_info'] = json.dumps(company['additional_info'])
return company
@api.model
def _find_country_data(self, state_code, state_name, country_code, country_name):
country = self.env['res.country'].search([['code', '=ilike', country_code]])
if not country:
country = self.env['res.country'].search([['name', '=ilike', country_name]])
state_id = False
country_id = False
if country:
country_id = {
'id': country.id,
'display_name': country.display_name
}
if state_name or state_code:
state = self.env['res.country.state'].search([
('country_id', '=', country_id.get('id')),
'|',
('name', '=ilike', state_name),
('code', '=ilike', state_code)
], limit=1)
if state:
state_id = {
'id': state.id,
'display_name': state.display_name
}
else:
_logger.info('Country code not found: %s', country_code)
return country_id, state_id
@api.model
def get_endpoint(self):
url = self.env['ir.config_parameter'].sudo().get_param('iap.partner_autocomplete.endpoint', DEFAULT_ENDPOINT)
url += '/iap/partner_autocomplete'
return url
@api.model
def _rpc_remote_api(self, action, params, timeout=15):
if self.env.registry.in_test_mode() :
return False, 'Insufficient Credit'
url = '%s/%s' % (self.get_endpoint(), action)
account = self.env['iap.account'].get('partner_autocomplete')
if not account.account_token:
return False, 'No Account Token'
params.update({
'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'),
'account_token': account.account_token,
'country_code': self.env.company.country_id.code,
'zip': self.env.company.zip,
})
try:
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 iap_tools.InsufficientCreditError as exception:
_logger.warning('Insufficient Credits for Autocomplete Service: %s' % str(exception))
return False, 'Insufficient Credit'
@api.model
def autocomplete(self, query):
suggestions, error = self._rpc_remote_api('search', {
'query': query,
})
if suggestions:
results = []
for suggestion in suggestions:
results.append(self._format_data_company(suggestion))
return results
else:
return []
@api.model
def enrich_company(self, company_domain, partner_gid, vat):
response, error = self._rpc_remote_api('enrich', {
'domain': company_domain,
'partner_gid': partner_gid,
'vat': vat,
})
if response and response.get('company_data'):
result = self._format_data_company(response.get('company_data'))
else:
result = {}
if response and response.get('credit_error'):
result.update({
'error': True,
'error_message': 'Insufficient Credit'
})
elif error:
result.update({
'error': True,
'error_message': error
})
return result
@api.model
def read_by_vat(self, vat):
vies_vat_data, error = self._rpc_remote_api('search_vat', {
'vat': vat,
})
if vies_vat_data:
return [self._format_data_company(vies_vat_data)]
else:
return []
@api.model
def _is_company_in_europe(self, country_code):
country = self.env['res.country'].search([('code', '=ilike', country_code)])
if country:
country_id = country.id
europe = self.env.ref('base.europe')
if not europe:
europe = self.env["res.country.group"].search([('name', '=', 'Europe')], limit=1)
if not europe or country_id not in europe.country_ids.ids:
return False
return True
def _is_vat_syncable(self, vat):
vat_country_code = vat[:2]
partner_country_code = self.country_id.code if self.country_id else ''
return self._is_company_in_europe(vat_country_code) and (partner_country_code == vat_country_code or not partner_country_code)
def _is_synchable(self):
already_synched = self.env['res.partner.autocomplete.sync'].search([('partner_id', '=', self.id), ('synched', '=', True)])
return self.is_company and self.partner_gid and not already_synched
def _update_autocomplete_data(self, vat):
self.ensure_one()
if vat and self._is_synchable() and self._is_vat_syncable(vat):
self.env['res.partner.autocomplete.sync'].sudo().add_to_queue(self.id)
@api.model_create_multi
def create(self, vals_list):
partners = super(ResPartner, self).create(vals_list)
if len(vals_list) == 1:
partners._update_autocomplete_data(vals_list[0].get('vat', False))
if partners.additional_info:
template_values = json.loads(partners.additional_info)
template_values['flavor_text'] = _("Partner created by Odoo Partner Autocomplete Service")
partners.message_post_with_view(
'iap_mail.enrich_company',
values=template_values,
subtype_id=self.env.ref('mail.mt_note').id,
)
partners.write({'additional_info': False})
return partners
def write(self, values):
res = super(ResPartner, self).write(values)
if len(self) == 1:
self._update_autocomplete_data(values.get('vat', False))
return res