Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions l10n_uy_ux/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,25 @@ def _compute_l10n_latam_document_number(self):
name = name.split(" ")[-1]
rec.l10n_latam_document_number = name

def _l10n_uy_edi_get_line_nom_and_desc(self, aml):
"""
Sobrescribimos este método que devuelve el valor de NomItem y DscItem para cada línea del comprobante,
para utilizar siempre la descripción de la línea (aml.name) como está en Odoo nativo, ya que a veces se quiere
modificar el valor a mostrar en la factura manteniendo el producto en la línea.
"""
Comment thread
jue-adhoc marked this conversation as resolved.
# B7 NomItem, B8 DscItem
nom_item = aml.name and aml.name[:80] or "-"
description = aml.name and aml.name[80:] or ""

if aml.l10n_uy_edi_addenda_ids:
adenda = [
" {%s}" % addenda.content if addenda.is_legend else " " + addenda.content
for addenda in aml.l10n_uy_edi_addenda_ids
]
description += "".join(adenda)

return nom_item, description

# Nuevos metodos

def action_l10n_uy_get_pdf(self):
Expand Down
100 changes: 99 additions & 1 deletion l10n_uy_ux/tests/test_l10n_uy_ux.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from odoo import Command
from odoo.addons.l10n_uy_edi.tests.common import TestUyEdi
from odoo.exceptions import UserError
from odoo.tests import Form
from odoo.tests.common import tagged


@tagged("-at_install", "post_install", "post_install_l10n", "ux")
@tagged("-at_install", "post_install", "post_install_l10n", "l10n_uy_ux")
class TestUx(TestUyEdi):
@classmethod
def setUpClass(self):
Expand Down Expand Up @@ -120,3 +121,100 @@ def test_with_automatic_report_params(self):
},
),
)

def test_110_account_move_line_nom_and_desc(self):
"""Test account move with varied products and descriptions"""
long_name = "Product name for testing purposes that intentionally contains more than eighty chars"

products = [
self.env["product.product"].create({"name": "Product Without Description"}),
self.env["product.product"].create({"name": "Product With Description"}),
self.env["product.product"].create({"name": long_name}),
]

addenda = self.env["l10n_uy_edi.addenda"].create(
{
"content": "Addenda Content",
"is_legend": False,
}
)

# Define invoice lines data to create
invoice_line_data = [
{"product_id": products[0], "name": None, "addenda_ids": []}, # Without description
{"product_id": products[1], "name": "Custom Description", "addenda_ids": []}, # With description
{"product_id": products[2], "name": None, "addenda_ids": []}, # +80 chars without description
{"product_id": products[2], "name": "Custom Description", "addenda_ids": []}, # +80 chars with description
{"product_id": products[2], "name": None, "addenda_ids": [addenda]}, # +80 chars with addenda
{
"product_id": products[2],
"name": "Custom Description",
"addenda_ids": [addenda],
}, # +80 chars with desc and addenda
{"product_id": products[0], "name": False, "addenda_ids": []}, # With description deleted by user
{"product_id": products[0], "name": "", "addenda_ids": []}, # With a empty string as description
]

# Create invoice using Form to simulate UI interaction
with Form(self.env["account.move"].with_context(default_move_type="out_invoice")) as invoice_form:
invoice_form.partner_id = self.partner_local
for line_data in invoice_line_data:
with invoice_form.invoice_line_ids.new() as line_form:
line_form.product_id = line_data["product_id"]
# Only override name if explicitly provided (not None)
if line_data["name"] is not None:
line_form.name = line_data["name"]
# Add addenda if provided
if line_data["addenda_ids"]:
line_form.l10n_uy_edi_addenda_ids.clear()
for addenda_rec in line_data["addenda_ids"]:
line_form.l10n_uy_edi_addenda_ids.add(addenda_rec)

invoice = invoice_form.save()

for idx, line in enumerate(invoice.invoice_line_ids):
nom_item, description = invoice._l10n_uy_edi_get_line_nom_and_desc(line)
if idx == 0: # Without description
self.assertEqual(
nom_item, "Product Without Description"[:80], "NomItem mismatch for line without description"
)
self.assertEqual(description, "", "Description mismatch for line without description")
elif idx == 1: # With custom description (aml.name is the custom description)
self.assertEqual(nom_item, "Custom Description"[:80], "NomItem mismatch for line with description")
self.assertEqual(description, "", "Description mismatch for line with description")
elif idx == 2: # +80 chars without description
self.assertEqual(
nom_item, long_name[:80], "NomItem mismatch for line with long name without description"
)
self.assertEqual(
description, long_name[80:], "Description mismatch for line with long name without description"
)
elif idx == 3: # +80 chars with custom description (aml.name is the custom description)
self.assertEqual(
nom_item, "Custom Description"[:80], "NomItem mismatch for line with long name and description"
)
self.assertEqual(
description,
"",
"Description mismatch for line with long name and description",
)
elif idx == 4: # +80 chars with addenda
self.assertEqual(nom_item, long_name[:80], "NomItem mismatch for line with long name and addenda")
self.assertIn(
"Addenda Content", description, "Addenda content missing in description for line with addenda"
)
elif idx == 5: # +80 chars with custom description and addenda (aml.name is the custom description)
self.assertEqual(
nom_item,
"Custom Description"[:80],
"NomItem mismatch for line with long name, description, and addenda",
)
# When custom description is set, description should contain the addenda
self.assertIn(
"Addenda Content",
description,
"Addenda content missing in description for line with desc and addenda",
)
elif idx == 6 or idx == 7: # With description deleted by user or "" (aml.name is False or empty)
self.assertEqual(nom_item, "-", "NomItem mismatch for line with deleted description")
self.assertEqual(description, "", "Description mismatch for line with deleted description")
10 changes: 10 additions & 0 deletions l10n_uy_ux/tests/test_patch_l10n_uy_edi.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ def test_default_doc_type_by_id_patch(self):
original_method = getattr(TestManual, "test_default_doc_type_by_id").origin
original_method(self)

def test_110_account_move_line_nom_and_desc_patch(self):
"""Test skipped: l10n_uy_ux intentionally modifies the line name logic for DGI submission.

The core l10n_uy_edi test expects that line.name is used to send data to DGI, but l10n_uy_ux
modifies this behavior to use the product name instead. This is an intentional change,
so we skip this test in l10n_uy_ux.
"""
self.skipTest("l10n_uy_ux changes the line name logic for DGI submission")

def propagate(method1, method2):
if method1:
for attr in ("_returns",):
Expand All @@ -76,6 +85,7 @@ def _skip_method(cls, name, method):
test_120_e_ticket_final_consumer_patch,
)
_patch_method(TestManual, "test_default_doc_type_by_id", test_default_doc_type_by_id_patch)
_patch_method(TestManual, "test_110_account_move_line_nom_and_desc", test_110_account_move_line_nom_and_desc_patch)
_skip_method(
TestAccountMoveSend,
"test_download_with_existing_cfe",
Expand Down