summaryrefslogtreecommitdiff
path: root/addons/partner_autocomplete/models/res_partner.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/partner_autocomplete/models/res_partner.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/partner_autocomplete/models/res_partner.py')
-rw-r--r--addons/partner_autocomplete/models/res_partner.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/addons/partner_autocomplete/models/res_partner.py b/addons/partner_autocomplete/models/res_partner.py
new file mode 100644
index 00000000..d53fcf2d
--- /dev/null
+++ b/addons/partner_autocomplete/models/res_partner.py
@@ -0,0 +1,203 @@
+# -*- 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