feat(test unitario): se desarrollo el test del escenario account_invoice

Se realizo el test unitario del escenario account_invoice donde se timbra una factura en moneda MXN
parent 027f32f8
Pipeline #24268 failed with stages
in 12 minutes and 40 seconds
......@@ -41,8 +41,10 @@ test:
- cd bench
- source bin/activate
- createdb $DB_NAME
- start_openerp -d $DB_NAME --stop-after-init -i $NAME_PRO
- green -d $DB_NAME -- local_modules/$NAME_PRO
- start_openerp -d $DB_NAME -i $NAME_PRO --stop-after-init
- start_openerp -d $DB_NAME -i l10n_generic_coa --stop-after-init
- start_openerp -d $DB_NAME -i account_payment --stop-after-init
- start_openerp -d $DB_NAME -i $NAME_PRO --test-enable --stop-after-init
dependencies:
- make
......
[buildout]
extends =
local.cfg
config/account.cfg
config/mexico.cfg
# The project name, base for paths
......
......@@ -301,7 +301,7 @@ class AccountPayment(models.Model):
precision_digits=6
)
return "{:.6f}".format(value)
return value
def impuestos_dr(self, invoice, tax_type="traslados"):
"""Computes move lines for on payment taxes related to given invoice"""
......
......@@ -99,9 +99,8 @@
t-attf-Impuesto="{{ tax.xml_name }}"
t-attf-Importe="{{ tax.xml_amount }}" />
</cfdi:Retenciones>
<cfdi:Traslados t-if="line.impuestos['traslados']">
<t t-set="impuestos" t-value="line.impuestos"/>
<cfdi:Traslado t-foreach="impuestos['traslados']" t-as="tax"
<cfdi:Traslados t-if="taxes['traslados']">
<cfdi:Traslado t-foreach="taxes['traslados']" t-as="tax"
t-att-Base="format_float(tax.base, o.currency_id.decimal_places)"
t-attf-Impuesto="{{ tax.xml_name }}"
t-attf-TipoFactor="{{ tax.type }}"
......
from . import test_account_invoice
# from . import test_account_voucher
# from . import test_cancel_invoice
\ No newline at end of file
# -*- coding: utf-8 -*-
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo import fields
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestCancelInvoice(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
# Setup for required fields and configurations
super().setUpClass(chart_template_ref=chart_template_ref)
main_company = cls.env.ref('l10n_mx.demo_company_mx')
"""Add a company to the user's allowed & set to current."""
cls.env.user.write(
{
"company_ids": [(6, 0, (main_company + cls.env.user.company_ids).ids)],
"company_id": main_company.id,
}
)
cls.tax_group = cls.env.ref('l10n_mx.tax_group_iva_16')
cls.customer = cls.env.ref('l10n_mx_facturae.res_partner_2023')
cls.cfdi_use = cls.env['cfdi.use'].sudo().search([], limit=1)
cls.fiscal_regime = cls.env['cfdi.fiscal.regime'].sudo().search([], limit=1)
cls.product = cls.env.ref('product.product_product_7')
cls.uom = cls.env['uom.uom'].search([], limit=1)
cls.journal = cls.env['account.journal'].sudo().search([('type', '=', 'sale'),
('company_id', '=', main_company.id)], limit=1)
cls.payment_type_id = cls.env['payment.type'].sudo().search([], limit=1)
if not cls.payment_type_id:
raise ValueError("No payment method was found in the database.")
# Configure tax group and tax for the test
cls.taxes_ids = cls.env['account.tax'].search([
('company_id', '=', main_company.id),
('type_tax_use', '=', 'sale'),
('tax_group_id', '=', cls.tax_group.id)
], limit=1)
if not cls.taxes_ids:
raise ValueError("The tax 'IVA 16% VENTAS' was not found in the database")
cfdi_product_service = cls.env['cfdi.product.service'].sudo().search([], limit=1).id
# Set up product with the tax and cfdi_product_service
cls.product.write({
'taxes_id': [(6, 0, [cls.taxes_ids.id])],
'cfdi_product_service_id': cfdi_product_service,
'company_id': main_company.id,
'uom_id': cls.uom.id,
})
receivable_account = cls.env['account.account'].sudo().search([
('company_id', '=', main_company.id),
('internal_type', '=', 'receivable')
], limit=1)
income_account = cls.env['account.account'].sudo().search([
('company_id', '=', main_company.id),
('internal_type', '=', 'income')
], limit=1)
cls.customer.sudo().write({
'company_id': main_company.id,
'cfdi_fiscal_regime_id': cls.fiscal_regime.id,
'zip': '20928',
'property_account_receivable_id': receivable_account.id,
})
# Create invoice with line items
cls.invoice = cls.env['account.move'].sudo().create({
'date': fields.Date.context_today(cls.customer),
'partner_id': cls.customer.id,
'journal_id': cls.journal.id,
'move_type': 'out_invoice',
'cfdi_periodicity': '04',
'invoice_line_ids': [
(0, 0, {
'product_id': cls.product.id,
'account_id': income_account.id,
'price_unit': 130.00,
'quantity': 1.0,
'tax_ids': [(6, 0, [cls.taxes_ids.id])],
'uom_id': cls.uom.id,
}),
],
'company_id': main_company.id,
})
# Configure journal for invoicing with SAT signature enabled
cls.journal.sudo().write({'sign_sat': True})
cls.customer.sudo().write({'vat': 'MXXAXX010101000'})
def test_cancel_invoice_with_out_cfdi(self):
"""
This scenario cancels the invoice, CFDI and verifies that:
- There is 1 CfdiRelacion node
- The TipoRelacion for the node is '04' (Substitution of the previous CFDI)
- The UUID for the node corresponds to the UUID of the cancelled CFDI
"""
self.journal.sign_sat = True
self.invoice.action_post()
self.assertEqual(self.invoice.state, 'posted')
self.assertEqual(self.invoice.cfdi_state, 'done')
self.invoice.action_cancel()
# self.assertEqual(self.invoice.state, "cancel")
# uuid_cancelado = self.invoice.cfdi_uuid_cancelled
# self.assertTrue(uuid_cancelado, "Debe existir un UUID para el CFDI cancelado")
# cfdi_xml = self.invoice.get_cfdi_xml_cancelled()
# self.assertTrue(cfdi_xml, "Debe existir un XML del CFDI cancelado")
# tree = etree.fromstring(cfdi_xml.encode('utf-8'))
# namespaces = {
# 'cfdi': 'http://www.sat.gob.mx/cfd/4',
# 'tfd': 'http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd',
# }
# cfdi_relacionados = tree.find('.//cfdi:CfdiRelacionados', namespaces=namespaces)
# self.assertIsNotNone(cfdi_relacionados)
# cfdi_relacionados_list = cfdi_relacionados.findall('cfdi:CfdiRelacionado', namespaces=namespaces)
# self.assertEqual(len(cfdi_relacionados_list), 1)
# tipo_relacion = cfdi_relacionados.get('TipoRelacion')
# self.assertEqual(tipo_relacion, '04')
# uuid_relacionado = cfdi_relacionados_list[0].get('UUID')
# self.assertEqual(uuid_relacionado, uuid_cancelado)
# -*- coding: utf-8 -*-
from odoo import fields, Command
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestPaymentReceipt(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
""" Configuración inicial para los datos requeridos. """
super().setUpClass()
cls.cfdi_use = cls.env["cfdi.use"].search([], limit=1)
cls.fiscal_regime = cls.env["cfdi.fiscal.regime"].search([], limit=1)
cls.payment_method_id = cls.env["payment.method"].search([], limit=1)
cls.customer.write(
{
"cfdi_fiscal_regime_id": cls.fiscal_regime.id,
"payment_method_customer": cls.payment_method_id.id,
"cfdi_use": cls.cfdi_use.id,
"zip": "20928",
}
)
# Crear cuenta contable y configuración de IVA
cls.account_iva_pendiente = cls.env['account.account.template'].create({
'code': '1151004000',
'name': 'IVA pendiente de acreditar',
'user_type_id': cls.env.ref('account.data_account_type_current_liabilities').id,
})
cls.account_iva_pagado = cls.env['account.account.template'].create({
'code': '1151003000',
'name': 'IVA efectivamente pagado',
'user_type_id': cls.env.ref('account.data_account_type_current_liabilities').id,
})
cls.account_banco = cls.env['account.account.template'].create({
'code': '1113020000',
'name': 'Banco',
'user_type_id': cls.env.ref('account.data_account_type_liquidity').id,
})
# Configurar diario para pagos
cls.bank_journal = cls.env['account.journal'].create({
'name': 'Banco',
'type': 'bank',
'code': 'BNK',
'bank_account_id': cls.account_banco.id,
})
cls.invoice = cls.env["account.move"].create(
{
"date": fields.Date.context_today(cls.customer),
"partner_id": cls.customer.id,
"journal_id": cls.sale_journal.id,
"type": "out_invoice",
"account_id": cls.customer.property_account_payable.id,
"cfdi_periodicity": "04",
"cfdi_use": cls.customer.cfdi_use.id,
"fiscal_regime": cls.customer.cfdi_fiscal_regime_id.id,
"payment_method_ids": [(4, cls.customer.payment_method_customer.id)],
"invoice_line": [
(
0,
0,
{
"name": 'ProductoA',
"account_id": cls.product.property_account_income.id,
"price_unit": 100.00,
"quantity": 1.0,
"product_id": cls.product.id,
"uos_id": cls.product.uom_id.id,
"invoice_line_tax_id": [(4, cls.product.taxes_id.id)],
},
),
],
}
)
cls.invoice.action_post()
def test_payment_receipt_with_higher_amount(self):
""" Escenario: Recibo de pago con monto mayor al de la factura """
# Registrar un pago por 116.01 MXN
payment_register = self.env['account.payment'].with_context(
active_model='account.move',
active_ids=self.invoice.ids
).create({
'amount': 116.01,
'payment_date': fields.Date.context_today(self),
'journal_id': self.bank_journal.id,
'payment_method_id': self.env.ref('account.account_payment_method_manual_out').id,
})
payment = payment_register._create_payments()
# Validar que la factura se haya pagado
self.assertEqual(self.invoice.state, 'posted')
self.assertEqual(self.invoice.payment_state, 'paid')
# Generar el recibo electrónico de pagos (CFDI de pago)
payment_move = payment.move_id
payment_move.l10n_mx_edi_is_required()
payment_move._post()
# Obtener el XML generado
xml_str = payment_move._l10n_mx_edi_create_cfdi()
xml_tree = self.env['account.move'].l10n_mx_edi_get_xml_etree(xml_str)
# Validar nodo DoctoRelacionado
docto_relacionado_node = xml_tree.find('.//pago10:DoctoRelacionado',
namespaces=self.env['account.move']._l10n_mx_edi_get_namespaces())
self.assertIsNotNone(docto_relacionado_node, "El XML debería contener el nodo DoctoRelacionado")
# Validar que el ImpSaldoAnt sea 116.00 MXN
self.assertEqual(docto_relacionado_node.get('ImpSaldoAnt'), '116.00',
"El ImpSaldoAnt debería ser 116.00 MXN")
# Validar que el ImportePagado sea 116.00 MXN
self.assertEqual(docto_relacionado_node.get('ImportePagado'), '116.00',
"El ImportePagado debería ser 116.00 MXN")
# Validar que el ImpoSaldoInsoluto sea 0.00 MXN
self.assertEqual(docto_relacionado_node.get('ImpSaldoInsoluto'), '0.00',
"El ImpSaldoInsoluto debería ser 0.00 MXN")
# -*- coding: utf-8 -*-
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from openerp import fields
from openerp.addons.account.tests.common import AccountTestInvoicingCommon
from odoo import fields
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestCancelInvoice(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super(TestCancelInvoice, cls).setUpClass()
super().setUpClass()
# Create required fields and assign to customer
cls.cfdi_use = cls.env["cfdi.use"].search([], limit=1)
cls.fiscal_regime = cls.env["cfdi.fiscal.regime"].search([], limit=1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment