[IMP] account_*: Proxy user refactor
- Proxy user is no longer a computed store=True field, but a proper one. The type cannot be deduced just by some field on the company. A company may be Italian and also use Peppol, so the two Proxy Users must be different. - The Proxy user `get_proxy_identification` method needs a proxy_type argument, otherwise the method won't know if the current override is to be applied or not. It cannot be handled by a field of the user itself because it is also used contextually to the user creation. - new `_get_default_enable_send_by_post` function on the Send and Print wizard, so that it can be overridden by the features of the move - Renamed `_compute_send_mail_extra_fields` to `_compute_fields_from_moves_state` Part-of: odoo/odoo#122194
This commit is contained in:
@@ -96,6 +96,9 @@ class IrAttachment(models.Model):
|
||||
This function is meant to be overriden to add formats.
|
||||
|
||||
:returns: A list of dictionary.
|
||||
* format: Optional but helps debugging.
|
||||
There are other methods that require the attachment
|
||||
to be an XML other than the standard one.
|
||||
* check: Function to be called on the attachment to pre-check if decoding will work.
|
||||
* decoder: Function to be called on the attachment to unwrap it.
|
||||
"""
|
||||
@@ -109,14 +112,17 @@ class IrAttachment(models.Model):
|
||||
|
||||
return [
|
||||
{
|
||||
'format': 'pdf',
|
||||
'check': lambda attachment: 'pdf' in attachment.mimetype,
|
||||
'decoder': self._decode_edi_pdf,
|
||||
},
|
||||
{
|
||||
'format': 'xml',
|
||||
'check': is_xml,
|
||||
'decoder': self._decode_edi_xml,
|
||||
},
|
||||
{
|
||||
'format': 'binary',
|
||||
'check': lambda attachment: True,
|
||||
'decoder': self._decode_edi_binary,
|
||||
},
|
||||
|
||||
@@ -47,13 +47,7 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
private_key = fields.Binary(required=True, attachment=False, groups="base.group_system", help="The key to encrypt all the user's data")
|
||||
private_key_filename = fields.Char(compute='_compute_private_key_filename')
|
||||
refresh_token = fields.Char(groups="base.group_system")
|
||||
proxy_type = fields.Selection(
|
||||
selection=[],
|
||||
string="Proxy type",
|
||||
compute='_compute_proxy_type',
|
||||
readonly=False,
|
||||
store=True,
|
||||
)
|
||||
proxy_type = fields.Selection(selection=[], required=True)
|
||||
edi_mode = fields.Selection(
|
||||
selection=[
|
||||
('prod', 'Production mode'),
|
||||
@@ -84,11 +78,6 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
WHERE (active = True)
|
||||
""")
|
||||
|
||||
@api.depends('company_id')
|
||||
def _compute_proxy_type(self):
|
||||
for user in self:
|
||||
user.proxy_type = False
|
||||
|
||||
def _compute_private_key_filename(self):
|
||||
for record in self:
|
||||
record.private_key_filename = f'{record.id_client}_{record.edi_identification}.key'
|
||||
@@ -109,7 +98,7 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
'''
|
||||
return company.account_edi_proxy_client_ids.filtered(lambda u: u.proxy_type == proxy_type)
|
||||
|
||||
def _get_proxy_identification(self, company):
|
||||
def _get_proxy_identification(self, company, proxy_type):
|
||||
'''Returns the key that will identify company uniquely
|
||||
within a specific proxy type and edi operating mode.
|
||||
or raises a UserError (if the user didn't fill the related field).
|
||||
@@ -127,9 +116,9 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
'id': uuid.uuid4().hex,
|
||||
}
|
||||
|
||||
# Last barrier : in case the demo mode is not handled by the caller, we block access.
|
||||
if self.edi_mode == 'demo':
|
||||
# Last barrier : in case the demo mode is not handled by the caller, we block access.
|
||||
raise Exception("Can't access the proxy in demo mode")
|
||||
raise AccountEdiProxyError("block_demo_mode", "Can't access the proxy in demo mode")
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
@@ -162,13 +151,11 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
|
||||
return response['result']
|
||||
|
||||
def _register_proxy_user(self, company, proxy_type, edi_mode, edi_identification):
|
||||
def _register_proxy_user(self, company, proxy_type, edi_mode):
|
||||
''' Generate the public_key/private_key that will be used to encrypt the file, send a request to the proxy
|
||||
to register the user with the public key and create the user with the private key.
|
||||
|
||||
:param company: the company of the user.
|
||||
:param edi_identification: The unique ID that identifies this user on this edi network and to which the files will be addressed.
|
||||
Typically the vat.
|
||||
'''
|
||||
# public_exponent=65537 is a default value that should be used most of the time, as per the documentation of cryptography.
|
||||
# key_size=2048 is considered a reasonable default key size, as per the documentation of cryptography.
|
||||
@@ -188,6 +175,7 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
edi_identification = self._get_proxy_identification(company, proxy_type)
|
||||
if edi_mode == 'demo':
|
||||
# simulate registration
|
||||
response = {'id_client': f'demo{company.id}', 'refresh_token': 'demo'}
|
||||
|
||||
@@ -14,9 +14,7 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
_inherit = 'account_edi_proxy_client.user'
|
||||
|
||||
peppol_verification_code = fields.Char(string='SMS verification code')
|
||||
proxy_type = fields.Selection(
|
||||
selection_add=[('peppol', 'PEPPOL')],
|
||||
)
|
||||
proxy_type = fields.Selection(selection_add=[('peppol', 'PEPPOL')], ondelete={'peppol': 'cascade'})
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# HELPER METHODS
|
||||
@@ -65,26 +63,18 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
|
||||
return super()._get_server_url(proxy_type, edi_mode)
|
||||
|
||||
def _get_proxy_identification(self, company):
|
||||
if not company.peppol_eas or not company.peppol_endpoint:
|
||||
raise UserError(_("Please fill in the EAS code and the Participant ID code."))
|
||||
return f'{company.peppol_eas}:{company.peppol_endpoint}'
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# COMPUTE METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _compute_proxy_type(self):
|
||||
# Extends account_edi_proxy_client
|
||||
super()._compute_proxy_type()
|
||||
for user in self:
|
||||
if user.company_id.is_account_peppol_participant:
|
||||
user.proxy_type = 'peppol'
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# BUSINESS ACTIONS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _get_proxy_identification(self, company, proxy_type):
|
||||
if proxy_type == 'peppol':
|
||||
if not company.peppol_eas or not company.peppol_endpoint:
|
||||
raise UserError(
|
||||
_("Please fill in the EAS code and the Participant ID code."))
|
||||
return f'{company.peppol_eas}:{company.peppol_endpoint}'
|
||||
return super()._get_proxy_identification(company, proxy_type)
|
||||
|
||||
def _cron_peppol_get_new_documents(self):
|
||||
# Retrieve all new Peppol documents for every edi user in the database
|
||||
edi_users = self.env['account_edi_proxy_client.user'].search(
|
||||
|
||||
@@ -118,9 +118,7 @@ class ResConfigSettings(models.TransientModel):
|
||||
|
||||
company = self.company_id
|
||||
edi_proxy_client = self.env['account_edi_proxy_client.user']
|
||||
edi_identification = edi_proxy_client._get_proxy_identification(company)
|
||||
edi_user = edi_proxy_client.sudo()._register_proxy_user(
|
||||
company, 'peppol', 'prod', edi_identification)
|
||||
edi_user = edi_proxy_client.sudo()._register_proxy_user(company, 'peppol', 'prod')
|
||||
self.account_peppol_proxy_state = 'not_verified'
|
||||
|
||||
# if there is an error when activating the participant below,
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestPeppolMessage(TestAccountMoveSendCommon):
|
||||
'account_peppol_proxy_state': 'active',
|
||||
})
|
||||
|
||||
edi_identification = cls.env['account_edi_proxy_client.user']._get_proxy_identification(cls.env.company)
|
||||
edi_identification = cls.env['account_edi_proxy_client.user']._get_proxy_identification(cls.env.company, 'peppol')
|
||||
cls.proxy_user = cls.env['account_edi_proxy_client.user'].create({
|
||||
'id_client': ID_CLIENT,
|
||||
'proxy_type': 'peppol',
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo import _, fields, models
|
||||
|
||||
|
||||
class AccountEdiProxyClientUser(models.Model):
|
||||
_inherit = 'account_edi_proxy_client.user'
|
||||
|
||||
proxy_type = fields.Selection(
|
||||
selection_add=[('l10n_it_edi', 'Italian EDI')],
|
||||
)
|
||||
proxy_type = fields.Selection(selection_add=[('l10n_it_edi', 'Italian EDI')], ondelete={'l10n_it_edi': 'cascade'})
|
||||
|
||||
def _get_proxy_urls(self):
|
||||
urls = super()._get_proxy_urls()
|
||||
urls['l10n_it_edi'] = {
|
||||
'demo': False,
|
||||
'prod': 'https://l10n-it-edi.api.odoo.com',
|
||||
'test': 'https://iap-services-test.odoo.com',
|
||||
}
|
||||
@@ -25,3 +24,10 @@ class AccountEdiProxyClientUser(models.Model):
|
||||
for user in self:
|
||||
if user.company_id.country_code == 'IT':
|
||||
user.proxy_type = 'l10n_it_edi'
|
||||
|
||||
def _get_proxy_identification(self, company, proxy_type):
|
||||
if proxy_type == 'l10n_it_edi':
|
||||
if not company.l10n_it_codice_fiscale:
|
||||
raise UserError(_('Please fill your codice fiscale to be able to receive invoices from FatturaPA'))
|
||||
return self.env['res.partner']._l10n_it_edi_normalized_codice_fiscale(company.l10n_it_codice_fiscale)
|
||||
return super()._get_proxy_identification(company, proxy_type)
|
||||
|
||||
@@ -19,9 +19,7 @@ class ResConfigSettings(models.TransientModel):
|
||||
readonly=False)
|
||||
|
||||
def _create_proxy_user(self, company_id, edi_mode):
|
||||
fattura_pa = self.env.ref('l10n_it_edi.edi_fatturaPA')
|
||||
edi_identification = fattura_pa._get_proxy_identification(company_id)
|
||||
self.env['account_edi_proxy_client.user']._register_proxy_user(company_id, 'l10n_it_edi', edi_mode, edi_identification)
|
||||
self.env['account_edi_proxy_client.user']._register_proxy_user(company_id, 'l10n_it_edi', edi_mode)
|
||||
|
||||
@api.depends('company_id.account_edi_proxy_client_ids', 'company_id.account_edi_proxy_client_ids.active')
|
||||
def _compute_l10n_it_edi_sdicoop_demo_mode(self):
|
||||
|
||||
@@ -85,6 +85,7 @@ class TestItEdi(AccountEdiTestCommon):
|
||||
|
||||
# We create this because we are unable to post without a proxy user existing
|
||||
cls.proxy_user = cls.env['account_edi_proxy_client.user'].create({
|
||||
'proxy_type': 'l10n_it_edi',
|
||||
'id_client': 'l10n_it_edi_test',
|
||||
'company_id': cls.company.id,
|
||||
'edi_identification': 'l10n_it_edi_test',
|
||||
|
||||
Reference in New Issue
Block a user