Skip to content

Commit fb6a169

Browse files
committed
[IMP] l10n_es{,edi_sii,edi_tbai}: move some code to l10n_es
The moved code will also be needed for Veri*Factu - patched http adapter - a function to retrieve partner info part of task-3745982 Part-of: odoo#197635 Signed-off-by: Sven Führ (svfu) <[email protected]>
1 parent eba25b0 commit fb6a169

File tree

8 files changed

+84
-71
lines changed

8 files changed

+84
-71
lines changed

addons/l10n_es/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Part of Odoo. See LICENSE file for full copyright and licensing details.
22
from . import models
3+
from . import tools

addons/l10n_es/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Part of Odoo. See LICENSE file for full copyright and licensing details.
22
from . import account_move
33
from . import account_tax
4+
from . import res_partner
45
from . import template_es_assec
56
from . import template_es_common
67
from . import template_es_coop_full

addons/l10n_es/models/res_partner.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from odoo import models
2+
3+
4+
class ResPartner(models.Model):
5+
_inherit = 'res.partner'
6+
7+
def _l10n_es_edi_get_partner_info(self):
8+
self.ensure_one()
9+
eu_country_codes = set(self.env.ref('base.europe').country_ids.mapped('code'))
10+
11+
partner_info = {}
12+
IDOtro_ID = self.vat or 'NO_DISPONIBLE'
13+
14+
if (not self.country_id or self.country_id.code == 'ES') and self.vat:
15+
# ES partner with VAT.
16+
partner_info['NIF'] = self.vat.removeprefix('ES')
17+
if self.env.context.get('error_1117'):
18+
partner_info['IDOtro'] = {'IDType': '07', 'ID': IDOtro_ID}
19+
20+
elif self.country_id.code in eu_country_codes and self.vat:
21+
# European partner.
22+
partner_info['IDOtro'] = {'IDType': '02', 'ID': IDOtro_ID}
23+
else:
24+
partner_info['IDOtro'] = {'ID': IDOtro_ID}
25+
if self.vat:
26+
partner_info['IDOtro']['IDType'] = '04'
27+
else:
28+
partner_info['IDOtro']['IDType'] = '06'
29+
if self.country_id:
30+
partner_info['IDOtro']['CodigoPais'] = self.country_id.code
31+
return partner_info

addons/l10n_es/tools/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import http_adapter

addons/l10n_es/tools/http_adapter.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import requests
2+
3+
from urllib3.util.ssl_ import create_urllib3_context
4+
from urllib3.contrib.pyopenssl import inject_into_urllib3
5+
from OpenSSL.crypto import load_certificate, load_privatekey, FILETYPE_PEM
6+
7+
# Custom patches to perform the WSDL requests.
8+
# Avoid failure on servers where the DH key is too small
9+
EUSKADI_CIPHERS = "DEFAULT:!DH"
10+
11+
12+
class PatchedHTTPAdapter(requests.adapters.HTTPAdapter):
13+
""" An adapter to block DH ciphers which may not work for the tax agencies called"""
14+
15+
def init_poolmanager(self, *args, **kwargs):
16+
# OVERRIDE
17+
inject_into_urllib3()
18+
kwargs['ssl_context'] = create_urllib3_context(ciphers=EUSKADI_CIPHERS)
19+
return super().init_poolmanager(*args, **kwargs)
20+
21+
def cert_verify(self, conn, url, verify, cert):
22+
# OVERRIDE
23+
# The last parameter is only used by the super method to check if the file exists.
24+
# In our case, cert is an odoo record 'l10n_es_edi.certificate' so not a path to a file.
25+
# By putting 'None' as last parameter, we ensure the check about TLS configuration is
26+
# still made without checking temporary files exist.
27+
super().cert_verify(conn, url, verify, None)
28+
conn.cert_file = cert
29+
conn.key_file = None
30+
31+
def get_connection(self, url, proxies=None):
32+
# OVERRIDE
33+
# Patch the OpenSSLContext to decode the certificate in-memory.
34+
conn = super().get_connection(url, proxies=proxies)
35+
context = conn.conn_kw['ssl_context']
36+
37+
def patched_load_cert_chain(l10n_es_odoo_certificate, keyfile=None, password=None):
38+
cert_file, key_file, _certificate = l10n_es_odoo_certificate.sudo()._decode_certificate()
39+
cert_obj = load_certificate(FILETYPE_PEM, cert_file)
40+
pkey_obj = load_privatekey(FILETYPE_PEM, key_file)
41+
42+
context._ctx.use_certificate(cert_obj)
43+
context._ctx.use_privatekey(pkey_obj)
44+
45+
context.load_cert_chain = patched_load_cert_chain
46+
47+
return conn

addons/l10n_es_edi_sii/models/account_edi_format.py

Lines changed: 2 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,16 @@
11
# -*- coding: utf-8 -*-
22
# Part of Odoo. See LICENSE file for full copyright and licensing details.
33
from collections import defaultdict
4-
from urllib3.util.ssl_ import create_urllib3_context
5-
from urllib3.contrib.pyopenssl import inject_into_urllib3
6-
from OpenSSL.crypto import load_certificate, load_privatekey, FILETYPE_PEM
74

85
from odoo import fields, models, _
6+
from odoo.addons.l10n_es.tools.http_adapter import PatchedHTTPAdapter
97
from odoo.tools import html_escape, zeep
108

119
import math
1210
import json
1311
import requests
1412

1513

16-
# Custom patches to perform the WSDL requests.
17-
# Avoid failure on servers where the DH key is too small
18-
EUSKADI_CIPHERS = "DEFAULT:!DH"
19-
20-
21-
class PatchedHTTPAdapter(requests.adapters.HTTPAdapter):
22-
""" An adapter to block DH ciphers which may not work for the tax agencies called"""
23-
24-
def init_poolmanager(self, *args, **kwargs):
25-
# OVERRIDE
26-
inject_into_urllib3()
27-
kwargs['ssl_context'] = create_urllib3_context(ciphers=EUSKADI_CIPHERS)
28-
return super().init_poolmanager(*args, **kwargs)
29-
30-
def cert_verify(self, conn, url, verify, cert):
31-
# OVERRIDE
32-
# The last parameter is only used by the super method to check if the file exists.
33-
# In our case, cert is an odoo record 'l10n_es_edi.certificate' so not a path to a file.
34-
# By putting 'None' as last parameter, we ensure the check about TLS configuration is
35-
# still made without checking temporary files exist.
36-
super().cert_verify(conn, url, verify, None)
37-
conn.cert_file = cert
38-
conn.key_file = None
39-
40-
def get_connection(self, url, proxies=None):
41-
# OVERRIDE
42-
# Patch the OpenSSLContext to decode the certificate in-memory.
43-
conn = super().get_connection(url, proxies=proxies)
44-
context = conn.conn_kw['ssl_context']
45-
46-
def patched_load_cert_chain(l10n_es_odoo_certificate, keyfile=None, password=None):
47-
cert_file, key_file, _certificate = l10n_es_odoo_certificate.sudo()._decode_certificate()
48-
cert_obj = load_certificate(FILETYPE_PEM, cert_file)
49-
pkey_obj = load_privatekey(FILETYPE_PEM, key_file)
50-
51-
context._ctx.use_certificate(cert_obj)
52-
context._ctx.use_privatekey(pkey_obj)
53-
54-
context.load_cert_chain = patched_load_cert_chain
55-
56-
return conn
57-
58-
5914
class AccountEdiFormat(models.Model):
6015
_inherit = 'account.edi.format'
6116

@@ -237,29 +192,7 @@ def full_filter_invl_to_apply(invoice_line):
237192
}
238193

239194
def _l10n_es_edi_get_partner_info(self, partner):
240-
eu_country_codes = set(self.env.ref('base.europe').country_ids.mapped('code'))
241-
242-
partner_info = {}
243-
IDOtro_ID = partner.vat or 'NO_DISPONIBLE'
244-
245-
if (not partner.country_id or partner.country_id.code == 'ES') and partner.vat:
246-
# ES partner with VAT.
247-
partner_info['NIF'] = partner.vat[2:] if partner.vat.startswith('ES') else partner.vat
248-
if self.env.context.get('error_1117'):
249-
partner_info['IDOtro'] = {'IDType': '07', 'ID': IDOtro_ID}
250-
251-
elif partner.country_id.code in eu_country_codes and partner.vat:
252-
# European partner.
253-
partner_info['IDOtro'] = {'IDType': '02', 'ID': IDOtro_ID}
254-
else:
255-
partner_info['IDOtro'] = {'ID': IDOtro_ID}
256-
if partner.vat:
257-
partner_info['IDOtro']['IDType'] = '04'
258-
else:
259-
partner_info['IDOtro']['IDType'] = '06'
260-
if partner.country_id:
261-
partner_info['IDOtro']['CodigoPais'] = partner.country_id.code
262-
return partner_info
195+
return partner._l10n_es_edi_get_partner_info()
263196

264197
def _l10n_es_edi_get_invoices_info(self, invoices):
265198
eu_country_codes = set(self.env.ref('base.europe').country_ids.mapped('code'))

addons/l10n_es_edi_tbai/models/account_edi_format.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from requests.exceptions import RequestException
1818

1919
from odoo import _, models, release
20-
from odoo.addons.l10n_es_edi_sii.models.account_edi_format import PatchedHTTPAdapter
20+
from odoo.addons.l10n_es.tools.http_adapter import PatchedHTTPAdapter
2121
from odoo.addons.l10n_es_edi_tbai.models.l10n_es_edi_tbai_agencies import get_key
2222
from odoo.addons.l10n_es_edi_tbai.models.xml_utils import (
2323
NS_MAP, bytes_as_block, calculate_references_digests,

addons/l10n_es_pos/__manifest__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
'category': 'Accounting/Localizations/Point of Sale',
77
'summary': """Spanish localization for Point of Sale""",
88
'depends': ['point_of_sale', 'l10n_es'],
9-
'auto_install': True,
109
'license': 'LGPL-3',
1110
'data': [
1211
'views/res_config_settings_views.xml',

0 commit comments

Comments
 (0)