Odoo18-Base/addons/account_peppol/tests/test_peppol_participant.py
2025-01-06 10:57:38 +07:00

241 lines
11 KiB
Python

import json
from contextlib import contextmanager
from requests import Session, PreparedRequest, Response
from psycopg2 import IntegrityError
from odoo.exceptions import ValidationError, UserError
from odoo.tests.common import tagged, TransactionCase, freeze_time
from odoo.tools import mute_logger
ID_CLIENT = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
FAKE_UUID = 'yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy'
PDF_FILE_PATH = 'account_peppol/tests/assets/peppol_identification_test.pdf'
@freeze_time('2023-01-01')
@tagged('-at_install', 'post_install')
class TestPeppolParticipant(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env['ir.config_parameter'].sudo().set_param('account_peppol.edi.mode', 'test')
@classmethod
def _get_mock_responses(cls):
participant_state = cls.env.context.get('participant_state', 'receiver')
return {
'/api/peppol/2/participant_status': {
'result': {
'peppol_state': participant_state,
}
},
'/api/peppol/1/activate_participant': {'result': {}},
'/api/peppol/2/register_participant': {'result': {}},
'/iap/account_edi/2/create_user': {
'result': {
'id_client': ID_CLIENT,
'refresh_token': FAKE_UUID,
}
},
'/api/peppol/1/send_verification_code': {'result': {}},
'/api/peppol/1/update_user': {'result': {}},
'/api/peppol/2/verify_phone_number': {'result': {}},
'/api/peppol/1/migrate_peppol_registration': {
'result': {
'migration_key': 'test_key',
}
},
'/api/peppol/1/register_sender': {'result': {}},
'/api/peppol/1/register_sender_as_receiver': {'result': {}},
}
@classmethod
def _request_handler(cls, s: Session, r: PreparedRequest, /, **kw):
response = Response()
response.status_code = 200
if r.url.endswith('/iso6523-actorid-upis%3A%3A9925%3A0000000000'):
response.status_code = 404
return response
if r.url.endswith('/iso6523-actorid-upis%3A%3A0208%3A0000000000'):
response._content = b'<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<smp:ServiceGroup xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:id="http://busdox.org/transport/identifiers/1.0/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:smp="http://busdox.org/serviceMetadata/publishing/1.0/"><id:ParticipantIdentifier scheme="iso6523-actorid-upis">0208:0000000000</id:ParticipantIdentifier></smp:ServiceGroup>'
return response
url = r.path_url
body = json.loads(r.body)
responses = cls._get_mock_responses()
if (
url == '/api/peppol/2/register_participant'
and cls.env.context.get('migrate_to')
and not body['params'].get('migration_key')
):
raise UserError('No migration key was provided')
if cls.env.context.get('migrated_away'):
response.json = lambda: {
'result': {
'proxy_error': {
'code': 'no_such_user',
'message': 'The user does not exist on the proxy',
}
}
}
return response
if url not in responses:
return super()._request_handler(s, r, **kw)
response.json = lambda: responses[url]
return response
def _get_participant_vals(self):
return {
'peppol_eas': '9925',
'peppol_endpoint': '0000000000',
'phone_number': '+32483123456',
'contact_email': 'yourcompany@test.example.com',
}
@contextmanager
def _set_context(self, other_context):
previous_context = self.env.context
self.env.context = dict(previous_context, **other_context)
yield self
self.env.context = previous_context
def test_create_participant_missing_data(self):
# creating a participant without eas/endpoint/document should not be possible
wizard = self.env['peppol.registration'].create({
'peppol_eas': False,
'peppol_endpoint': False,
})
with self.assertRaises(ValidationError), self.cr.savepoint():
wizard.button_peppol_sender_registration()
def test_create_participant_already_exists(self):
# creating a receiver participant that already exists on Peppol network should not be possible
vals = self._get_participant_vals()
vals['peppol_eas'] = '0208'
wizard = self.env['peppol.registration'].create(vals)
with self.assertRaises(UserError), self.cr.savepoint():
wizard.button_peppol_sender_registration()
wizard.verification_code = '123456'
wizard.button_check_peppol_verification_code()
def test_create_success_sender(self):
# should be possible to apply with all data
# the account_peppol_proxy_state should correctly change to sender
# then the account_peppol_proxy_state should not change
# after running the cron checking participant status
company = self.env.company
wizard = self.env['peppol.registration'].create({'smp_registration': False, **self._get_participant_vals()})
wizard.button_peppol_sender_registration()
# since we did not select receiver registration, we're now just a sender
self.assertEqual(company.account_peppol_proxy_state, 'sender')
# running the cron should not do anything for the company
with self._set_context({'participant_state': 'sender'}):
self.env['account_edi_proxy_client.user']._cron_peppol_get_participant_status()
self.assertEqual(company.account_peppol_proxy_state, 'sender')
def test_create_success_receiver(self):
# should be possible to apply with all data
# the account_peppol_proxy_state should correctly change to smp_registration
# then the account_peppol_proxy_state should change successfully
# after checking participant status
company = self.env.company
wizard = self.env['peppol.registration'].create(self._get_participant_vals())
wizard.smp_registration = True # choose to register as a receiver right away
wizard.button_peppol_sender_registration()
self.assertEqual(company.account_peppol_proxy_state, 'smp_registration')
with self._set_context({'participant_state': 'receiver'}):
self.env['account_edi_proxy_client.user']._cron_peppol_get_participant_status()
self.assertEqual(company.account_peppol_proxy_state, 'receiver')
def test_create_success_receiver_two_steps(self):
# it should be possible to first register as a sender in the wizard
# and then come back to settings and register as a receiver
# first step: use the peppol wizard to register only as a sender
company = self.env.company
wizard = self.env['peppol.registration'].create({'smp_registration': False, **self._get_participant_vals()})
wizard.button_peppol_sender_registration()
wizard.verification_code = '123456'
wizard.button_check_peppol_verification_code()
self.assertEqual(company.account_peppol_proxy_state, 'sender')
# second step: open settings and register as a receiver
settings = self.env['res.config.settings'].create({})
settings.button_peppol_smp_registration()
self.assertEqual(company.account_peppol_proxy_state, 'smp_registration')
self.env['account_edi_proxy_client.user']._cron_peppol_get_participant_status()
self.assertEqual(company.account_peppol_proxy_state, 'receiver')
def test_create_reject_participant(self):
# the account_peppol_proxy_state should change to rejected
# if we reject the participant
company = self.env.company
wizard = self.env['peppol.registration'].create(self._get_participant_vals())
with self._set_context({'participant_state': 'rejected'}):
wizard.button_peppol_sender_registration()
company.account_peppol_proxy_state = 'smp_registration'
self.env['account_edi_proxy_client.user']._cron_peppol_get_participant_status()
self.assertEqual(company.account_peppol_proxy_state, 'rejected')
@mute_logger('odoo.sql_db')
def test_create_duplicate_participant(self):
# should not be possible to create a duplicate participant
wizard = self.env['peppol.registration'].create(self._get_participant_vals())
wizard.button_peppol_sender_registration()
with self.assertRaises(IntegrityError), self.cr.savepoint():
wizard.account_peppol_proxy_state = 'not_registered'
wizard.button_peppol_sender_registration()
def test_save_migration_key(self):
# migration key should be saved
wizard = self.env['peppol.registration']\
.create({
**self._get_participant_vals(),
'smp_registration': True,
'account_peppol_migration_key': 'helloo',
})
with self._set_context({'migrate_to': True}):
self.assertEqual(self.env.company.account_peppol_migration_key, 'helloo')
wizard.button_peppol_sender_registration()
wizard.verification_code = '123456'
wizard.button_check_peppol_verification_code()
self.assertEqual(self.env.company.account_peppol_proxy_state, 'smp_registration')
self.assertFalse(self.env.company.account_peppol_migration_key) # the key should be reset once we've used it
def test_migrate_away_participant(self):
# a participant should be able to request a migration key
wizard = self.env['peppol.registration'].create(self._get_participant_vals())
self.assertFalse(wizard.account_peppol_migration_key)
wizard.button_peppol_sender_registration()
wizard.account_peppol_proxy_state = 'receiver'
# migrating away is only possible in the settings
settings = self.env['res.config.settings'].create({})
settings.button_migrate_peppol_registration()
self.assertEqual(settings.company_id.account_peppol_proxy_state, 'receiver')
self.assertEqual(settings.account_peppol_migration_key, 'test_key')
def test_reset_participant(self):
# once a participant has migrated away, they should be reset
wizard = self.env['peppol.registration'].create(self._get_participant_vals())
wizard.button_peppol_sender_registration()
wizard.account_peppol_proxy_state = 'receiver'
settings = self.env['res.config.settings'].create({})
settings.button_migrate_peppol_registration()
with self._set_context({'migrated_away': True}):
try:
settings.button_update_peppol_user_data()
except UserError:
settings = self.env['res.config.settings'].create({})
self.assertRecordValues(settings, [{
'account_peppol_migration_key': False,
'account_peppol_proxy_state': 'not_registered',
}],
)
self.assertFalse(self.env.company.account_edi_proxy_client_ids.filtered(lambda u: u.proxy_type == 'peppol'))
else:
raise ValidationError('A UserError should be raised.')