Files
enterprise-addons/l10n_co_edi_pos/tests/test_dian_pos.py
T

284 lines
13 KiB
Python

from unittest.mock import patch
import requests
from markupsafe import Markup
from .common import TestL10nCoEdiPosCommon
from odoo.exceptions import UserError
from odoo.tests import tagged
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestDianPos(TestL10nCoEdiPosCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.default_pos_order_ui_data = {
'pos_order_lines_ui_args': [(cls.product_a, 2)],
'payments': [(cls.default_pos_payment_method, 2380.0)]
}
def _mock_get_status_zip_pos_order(self, order, response_file, response_code=200):
with patch.object(requests, 'post', return_value=self._mocked_request(response_file, response_code)):
order.l10n_co_edi_pos_document_ids._get_status_zip()
def _send_test_set_async(self):
self.config.company_id.write({
'l10n_co_dian_test_environment': True,
'l10n_co_dian_certification_process': True,
})
order = self._create_and_send_order(pos_order_ui_data=self.default_pos_order_ui_data, response_file_name='SendTestSetAsync.xml')
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_pending',
'message': Markup("<p>Invoice is being processed by the DIAN.</p>"),
}])
self.assertEqual(order.l10n_co_edi_pos_dian_state, 'invoice_pending')
return order
def test_get_status_zip_warnings(self):
""" SendTestSetAsync then GetStatusZip which returns warnings but the document is valid. """
# Step 1: SendTestSetAsync
order = self._send_test_set_async()
# Step 2: GetStatusZip
self._mock_get_status_zip_pos_order(order=order, response_file='GetStatusZip_warnings.xml')
# checks on the document
self.assertEqual(len(order.l10n_co_edi_pos_document_ids), 1)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_accepted',
'message': Markup(
"<p>Procesado Correctamente.</p>"
"<ul><li>Regla: FAJ44b, Notificación: Nit o Documento de Identificación BlaBlaBla.</li>"
"<li>Regla: FAJ43b, Notificación: Nombre informado No corresponde al BlaBlaBla.</li></ul>"
),
}])
# checks on the invoice
self.assertTrue(order.l10n_co_edi_pos_attachment_id)
self.assertEqual(order.l10n_co_edi_pos_dian_state, 'invoice_accepted')
def test_get_status_zip_habilitation(self):
""" SendTestSetAsync then GetStatusZip which inform that they passed the habitation process. """
# Step 1: SendTestSetAsync
order = self._send_test_set_async()
# Step 2: GetStatusZip
self._mock_get_status_zip_pos_order(order, response_file='GetStatusZip_habilitation.xml')
# checks on the document
self.assertEqual(len(order.l10n_co_edi_pos_document_ids), 1)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_rejected',
'message': Markup("<p>Set de prueba con identificador 123456 se encuentra Aceptado.</p>"),
}])
# checks on the invoice
self.assertFalse(order.l10n_co_edi_pos_attachment_id)
self.assertEqual(order.l10n_co_edi_pos_dian_state, 'invoice_rejected')
def test_get_status_zip_pending(self):
""" SendTestSetAsync then GetStatusZip which responds 'Batch is being processed' (need to check again later)"""
# Step 1: SendTestSetAsync
order = self._send_test_set_async()
# Step 2: GetStatusZip
self._mock_get_status_zip_pos_order(order, response_file='GetStatusZip_pending.xml')
# checks on the document
self.assertEqual(len(order.l10n_co_edi_pos_document_ids), 1)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_pending',
'message': Markup("<p>Batch en proceso de validación.</p>"),
'show_button_get_status': True,
}])
# checks on the invoice
self.assertFalse(order.l10n_co_edi_pos_attachment_id)
self.assertEqual(order.l10n_co_edi_pos_dian_state, 'invoice_pending')
# Step 3: GetStatusZip again (this time the document is processed)
self._mock_get_status_zip_pos_order(order, response_file='GetStatusZip_warnings.xml')
# checks on the document
self.assertEqual(len(order.l10n_co_edi_pos_document_ids), 1)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_accepted',
'message': Markup(
"<p>Procesado Correctamente.</p>"
"<ul><li>Regla: FAJ44b, Notificación: Nit o Documento de Identificación BlaBlaBla.</li>"
"<li>Regla: FAJ43b, Notificación: Nombre informado No corresponde al BlaBlaBla.</li></ul>"
),
}])
# checks on the invoice
self.assertTrue(order.l10n_co_edi_pos_attachment_id)
self.assertEqual(order.l10n_co_edi_pos_dian_state, 'invoice_accepted')
def test_send_bill_sync_warnings(self):
""" SendBillSync returning warnings but the document is valid. """
order = self._create_and_send_order(pos_order_ui_data=self.default_pos_order_ui_data, response_file_name='SendBillSync_warnings.xml')
self.assertTrue(order.l10n_co_edi_pos_attachment_id)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_accepted',
'message': Markup(
"<p>Procesado Correctamente.</p>"
"<ul><li>Regla: FAJ44b, Notificación: Nit o Documento de Identificación informado No BlaBlaBla.</li>"
"<li>Regla: FAJ43b, Notificación: Nombre informado No corresponde al registrado en el BlaBlaBla.</li></ul>"
),
}])
def test_send_bill_sync_errors(self):
""" SendBillSync returning errors blocking the Send & Print flow. """
error_raised = False
try:
self._create_and_send_order(pos_order_ui_data=self.default_pos_order_ui_data, response_file_name='SendBillSync_errors.xml')
except UserError as e:
error_raised = True
self.assertEqual(e.args[0], "Error(s) when sending the document to the DIAN:\n"
"- Regla: ZB01, Rechazo: Fallo en el esquema XML del archivo")
self.assertTrue(error_raised)
order = self.config.session_ids.order_ids[0]
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_rejected',
'message': Markup(
"<p>Documento con errores en campos mandatorios.</p>"
"<ul><li>Regla: ZB01, Rechazo: Fallo en el esquema XML del archivo</li></ul>"
),
}])
return order
def test_send_bill_sync_errors_nsmap(self):
""" SendBillSync returning errors due to a missing namespace, blocking the Send & Print flow. """
error_raised = False
try:
self._create_and_send_order(pos_order_ui_data=self.default_pos_order_ui_data, response_file_name='SendBillSync_errors_nsmap.xml')
except UserError as e:
error_raised = True
self.assertEqual(e.args[0], "Error(s) when sending the document to the DIAN:\n- Error al parsear xml. Namespace prefix 'sts' is not defined.")
self.assertTrue(error_raised)
order = self.config.session_ids.order_ids[0]
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_rejected',
'message': Markup("<p>Error al parsear xml. Namespace prefix 'sts' is not defined.</p>"),
}])
def test_send_bill_sync_duplicated(self):
""" SendBillSync returning 'Regla: 90, Rechazo: Documento procesado anteriormente.'
This means an invoice with the same CUFE has already been accepted by the DIAN.
"""
error_raised = False
try:
self._create_and_send_order(pos_order_ui_data=self.default_pos_order_ui_data, response_file_name='SendBillSync_duplicated.xml')
except UserError as e:
error_raised = True
self.assertEqual(e.args[0], "Error(s) when sending the document to the DIAN:\n"
"- Regla: 90, Rechazo: Documento procesado anteriormente.")
self.assertTrue(error_raised)
order = self.config.session_ids.order_ids[0]
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_rejected',
'message': Markup(
"<p>Validación contiene errores en campos mandatorios.</p>"
"<ul><li>Regla: 90, Rechazo: Documento procesado anteriormente.</li></ul>"
),
}])
def test_send_bill_sync_second_attempt(self):
""" First attempt SendBillSync returns errors, second attempt is successful. """
# 1st attempt (fail)
order = self.test_send_bill_sync_errors()
self.assertFalse(order.l10n_co_edi_pos_attachment_id)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_rejected',
'message': Markup(
"<p>Documento con errores en campos mandatorios.</p>"
"<ul><li>Regla: ZB01, Rechazo: Fallo en el esquema XML del archivo</li></ul>"
),
}])
# 2nd attempt (success without errors or warnings)
with (
self.patched_document('_parse_errors', []),
self._mock_get_status(),
patch(f'{self.utils_path}._build_and_send_request', return_value=self._mocked_response('SendBillSync_warnings.xml', 200)),
):
order.l10n_co_edi_pos_action_send_document()
self.assertEqual(len(order.l10n_co_edi_pos_document_ids), 1) # no need to keep the rejected documents
self.assertTrue(order.l10n_co_edi_pos_attachment_id)
self.assertRecordValues(order.l10n_co_edi_pos_document_ids, [{
'zip_key': False,
'state': 'invoice_accepted',
'message': Markup("<p>Procesado Correctamente.</p>"),
}])
def test_invoiced_pos_order(self):
self.config.company_id.write({
'l10n_co_dian_test_environment': True,
'l10n_co_dian_certification_process': True,
})
with (
self._pos_session(),
self._mock_get_status(),
self._disable_get_acquirer_call(),
patch(f'{self.utils_path}._build_and_send_request', return_value=self._mocked_response('SendTestSetAsync.xml', 200)),
):
order = self._create_order({
**self.default_pos_order_ui_data,
'is_invoiced': True,
'customer': self.partner_co,
})
self.assertRecordValues(order, [{
'to_invoice': True,
'l10n_co_edi_pos_document_ids': self.env['l10n_co_dian.document'],
}])
self.assertTrue(order.account_move)
move = order.account_move
self._mock_send_and_print(move=move, response_file='SendTestSetAsync.xml')
self.assertRecordValues(move.l10n_co_dian_document_ids, [{
'zip_key': '42424242',
'state': 'invoice_pending',
'message': Markup("<p>Invoice is being processed by the DIAN.</p>"),
}])
self.assertEqual(move.l10n_co_dian_state, 'invoice_pending')
def test_session_report(self):
self.config.company_id.write({
'l10n_co_dian_test_environment': True,
'l10n_co_dian_certification_process': True,
})
self.config.l10n_co_edi_pos_serial_number = "Test CO SN"
with (
self._pos_session(),
self._mock_get_status(),
self._disable_get_acquirer_call(),
patch(f'{self.utils_path}._build_and_send_request', return_value=self._mocked_response('SendTestSetAsync.xml', 200)),
):
order = self._create_order({
**self.default_pos_order_ui_data,
'is_invoiced': True,
'customer': self.partner_co,
})
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details(
config_ids=order.session_id.config_id.ids,
session_ids=order.session_id.ids
)
self.assertIn("Test CO SN", report['l10n_co_edi_pos_serial_number'])