4 Commits

Author SHA1 Message Date
4410cc919a Merge pull request 'test(Tryton): add catalog sale test and validate build_tryton_comment' (#44) from fix/EnviarComentarioConDetalleDelPedido into main
Reviewed-on: #44
2026-07-11 18:56:05 -05:00
d1c2b4f1bb test(Tryton): add catalog sale test and validate build_tryton_comment
- Added CatalogSale/CatalogSaleLine to setUp
- Added explicit assertion linking TrytonSale.build_tryton_comment()
  to sale.description
- Rewrote test_send_catalog_sales_to_tryton with proper CatalogSale
  data, validating comment format, description, reference and lines
- Added direct assertion of TrytonCatalogSale.build_tryton_comment()
2026-07-11 14:55:44 -05:00
d57b827e4e Merge pull request 'fix(Tryton): restore send sales test and fix TrytonSale.build_tryton_comment' (#43) from fix/EnviarComentarioConDetalleDelPedido into main
Reviewed-on: #43
2026-07-11 14:38:27 -05:00
1e32cfce7f fix(Tryton): restore send sales test and fix TrytonSale.build_tryton_comment
- Restored test_exportar_ventas_para_tryton.py with full parameter
  validation for client.call (method, context, sale fields, lines)
- Fixed TrytonSale.build_tryton_comment referencing self.catalog_sale
  (nonexistent) instead of self.sale.description
2026-07-11 14:32:41 -05:00
2 changed files with 285 additions and 8 deletions

View File

@@ -43,20 +43,28 @@ class TrytonSale:
"shipment_address": self.sale.customer.address_external_id, "shipment_address": self.sale.customer.address_external_id,
"invoice_address": self.sale.customer.address_external_id, "invoice_address": self.sale.customer.address_external_id,
"currency": TRYTON_COP_CURRENCY, "currency": TRYTON_COP_CURRENCY,
"comment": self.sale.description or "", "comment": self.build_tryton_comment(),
"description": "Metodo pago: " + str(self.sale.payment_method or ""), "description": "Metodo pago: "
+ str(self.sale.payment_method or ""),
"party": self.sale.customer.external_id, "party": self.sale.customer.external_id,
"reference": "don_confiao " + str(self.sale.id), "reference": "don_confiao " + str(self.sale.id),
"sale_date": self._format_date(self.sale.date), "sale_date": self._format_date(self.sale.date),
"lines": [ "lines": [
[ [
"create", "create",
[TrytonLineSale(line).to_tryton() for line in self.lines], [
TrytonLineSale(line).to_tryton()
for line in self.lines
],
] ]
], ],
"self_pick_up": True, "self_pick_up": True,
} }
def build_tryton_comment(self):
"""Construye el comentario para la venta en Tryton"""
return self.sale.description or ""
class TrytonLineSale: class TrytonLineSale:
"""Representa una línea de venta para exportación a Tryton""" """Representa una línea de venta para exportación a Tryton"""
@@ -98,20 +106,36 @@ class TrytonCatalogSale:
"shipment_address": self.catalog_sale.customer.address_external_id, "shipment_address": self.catalog_sale.customer.address_external_id,
"invoice_address": self.catalog_sale.customer.address_external_id, "invoice_address": self.catalog_sale.customer.address_external_id,
"currency": TRYTON_COP_CURRENCY, "currency": TRYTON_COP_CURRENCY,
"comment": self.catalog_sale.description or "", "comment": self.build_tryton_comment(),
"description": "Venta de catálogo", "description": "Venta de catálogo",
"party": self.catalog_sale.customer.external_id, "party": self.catalog_sale.customer.external_id,
"reference": "don_confiao_catalog " + str(self.catalog_sale.id), "reference": "don_confiao_catalog "
+ str(self.catalog_sale.id),
"sale_date": self._format_date(self.catalog_sale.date), "sale_date": self._format_date(self.catalog_sale.date),
"lines": [ "lines": [
[ [
"create", "create",
[TrytonCatalogSaleLine(line).to_tryton() for line in self.lines], [
TrytonCatalogSaleLine(line).to_tryton()
for line in self.lines
],
] ]
], ],
"self_pick_up": True, "self_pick_up": True,
} }
def build_tryton_comment(self):
"""Construye el comentario para la venta en Tryton"""
comment = f"Cliente: {self.catalog_sale.customer_name or ''}\n"
comment += f"Teléfono: {self.catalog_sale.customer_phone or ''}\n"
comment += (
f"Dirección: {self.catalog_sale.customer_address or ''}\n"
)
comment += f"Método de recogida: {self.catalog_sale.pickup_method or ''}\n"
return comment
class TrytonCatalogSaleLine: class TrytonCatalogSaleLine:
"""Representa una línea de catalog sale para exportación a Tryton""" """Representa una línea de catalog sale para exportación a Tryton"""
@@ -125,8 +149,12 @@ class TrytonCatalogSaleLine:
def to_tryton(self): def to_tryton(self):
return { return {
"product": self.catalog_sale_line.product.external_id, "product": self.catalog_sale_line.product.external_id,
"quantity": self._format_decimal(self.catalog_sale_line.quantity), "quantity": self._format_decimal(
self.catalog_sale_line.quantity
),
"type": "line", "type": "line",
"unit": self.catalog_sale_line.product.unit_external_id, "unit": self.catalog_sale_line.product.unit_external_id,
"unit_price": self._format_decimal(self.catalog_sale_line.unit_price), "unit_price": self._format_decimal(
self.catalog_sale_line.unit_price
),
} }

View File

@@ -0,0 +1,249 @@
import json
from unittest.mock import patch, MagicMock
from django.test import TestCase
from ..models.sales import Sale, SaleLine, CatalogSale, CatalogSaleLine
from ..models.customers import Customer
from ..models.products import Product
from ..services.tryton.client import TrytonSale, TrytonCatalogSale
from .Mixins import LoginMixin
class TestSendSalesToTryton(TestCase, LoginMixin):
def setUp(self):
self.login()
self.product = Product.objects.create(
name="Panela",
price=5000,
measuring_unit="UNIT",
unit_external_id="1",
external_id="1",
)
self.customer = Customer.objects.create(
name="Camilo",
external_id="1",
address_external_id="307",
)
self.sale = Sale.objects.create(
customer=self.customer,
date="2024-09-02",
payment_method="CASH",
description="un comentario",
)
SaleLine.objects.create(
product=self.product,
quantity=2,
unit_price=3000,
sale=self.sale,
)
SaleLine.objects.create(
product=self.product,
quantity=3,
unit_price=5000,
sale=self.sale,
)
self.catalog_sale = CatalogSale.objects.create(
customer=self.customer,
date="2024-09-02",
customer_name="Camilo",
customer_phone="3001234567",
customer_address="Calle 123",
pickup_method="Recogida en tienda",
)
CatalogSaleLine.objects.create(
catalog_sale=self.catalog_sale,
product=self.product,
quantity=2,
unit_price=3000,
)
CatalogSaleLine.objects.create(
catalog_sale=self.catalog_sale,
product=self.product,
quantity=3,
unit_price=5000,
)
@patch("don_confiao.api.sales.get_tryton_client")
def test_send_sales_to_tryton(self, mock_get_tryton_client):
external_id = "23423"
mock_client = MagicMock()
mock_client.call.return_value = [external_id]
mock_get_tryton_client.return_value = mock_client
url = "/don_confiao/api/enviar_ventas_a_tryton"
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
content = json.loads(response.content.decode("utf-8"))
self.assertEqual(
content, {"successful": [self.sale.id], "failed": []}
)
updated_sale = Sale.objects.get(id=self.sale.id)
self.assertEqual(updated_sale.external_id, external_id)
mock_get_tryton_client.assert_called_once()
mock_client.call.assert_called_once()
call_args = mock_client.call.call_args
method, params = call_args[0]
self.assertEqual(method, "model.sale.sale.create")
tryton_context = params[1]
self.assertEqual(tryton_context, {"company": 1, "shops": [1]})
sale_params = params[0][0]
self.assertEqual(sale_params["company"], 1)
self.assertEqual(sale_params["shipment_address"], "307")
self.assertEqual(sale_params["invoice_address"], "307")
self.assertEqual(sale_params["currency"], 31)
self.assertEqual(sale_params["comment"], "un comentario")
self.assertEqual(sale_params["description"], "Metodo pago: CASH")
self.assertEqual(sale_params["party"], "1")
self.assertEqual(
sale_params["reference"], f"don_confiao {self.sale.id}"
)
self.assertEqual(
sale_params["sale_date"],
{"__class__": "date", "year": 2024, "month": 9, "day": 2},
)
self.assertTrue(sale_params["self_pick_up"])
sale_tryton = TrytonSale(
self.sale, SaleLine.objects.filter(sale=self.sale)
)
self.assertEqual(
sale_tryton.build_tryton_comment(), self.sale.description
)
lines_block = sale_params["lines"]
self.assertEqual(len(lines_block), 1)
self.assertEqual(lines_block[0][0], "create")
lines = lines_block[0][1]
self.assertEqual(len(lines), 2)
self.assertEqual(lines[0]["product"], "1")
self.assertEqual(
lines[0]["quantity"],
{"__class__": "Decimal", "decimal": "2.00"},
)
self.assertEqual(lines[0]["type"], "line")
self.assertEqual(lines[0]["unit"], "1")
self.assertEqual(
lines[0]["unit_price"],
{"__class__": "Decimal", "decimal": "3000.00"},
)
self.assertEqual(lines[1]["product"], "1")
self.assertEqual(
lines[1]["quantity"],
{"__class__": "Decimal", "decimal": "3.00"},
)
self.assertEqual(lines[1]["type"], "line")
self.assertEqual(lines[1]["unit"], "1")
self.assertEqual(
lines[1]["unit_price"],
{"__class__": "Decimal", "decimal": "5000.00"},
)
@patch("don_confiao.api.sales.get_tryton_client")
def test_send_catalog_sales_to_tryton(self, mock_get_tryton_client):
external_id = "23423"
mock_client = MagicMock()
mock_client.call.return_value = [external_id]
mock_get_tryton_client.return_value = mock_client
url = "/don_confiao/api/enviar_catalog_sales_a_tryton"
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
content = json.loads(response.content.decode("utf-8"))
self.assertEqual(
content,
{"successful": [self.catalog_sale.id], "failed": []},
)
updated = CatalogSale.objects.get(id=self.catalog_sale.id)
self.assertEqual(updated.external_id, external_id)
mock_get_tryton_client.assert_called_once()
mock_client.call.assert_called_once()
call_args = mock_client.call.call_args
method, params = call_args[0]
self.assertEqual(method, "model.sale.sale.create")
tryton_context = params[1]
self.assertEqual(tryton_context, {"company": 1, "shops": [1]})
sale_params = params[0][0]
self.assertEqual(sale_params["company"], 1)
self.assertEqual(sale_params["shipment_address"], "307")
self.assertEqual(sale_params["invoice_address"], "307")
self.assertEqual(sale_params["currency"], 31)
self.assertEqual(sale_params["description"], "Venta de catálogo")
self.assertEqual(sale_params["party"], "1")
self.assertEqual(
sale_params["reference"],
f"don_confiao_catalog {self.catalog_sale.id}",
)
self.assertEqual(
sale_params["sale_date"],
{"__class__": "date", "year": 2024, "month": 9, "day": 2},
)
self.assertTrue(sale_params["self_pick_up"])
expected_comment = (
"Cliente: Camilo\n"
"Teléfono: 3001234567\n"
"Dirección: Calle 123\n"
"Método de recogida: Recogida en tienda\n"
)
self.assertEqual(sale_params["comment"], expected_comment)
catalog_tryton = TrytonCatalogSale(
self.catalog_sale,
CatalogSaleLine.objects.filter(
catalog_sale=self.catalog_sale
),
)
self.assertEqual(
catalog_tryton.build_tryton_comment(), expected_comment
)
lines_block = sale_params["lines"]
self.assertEqual(len(lines_block), 1)
self.assertEqual(lines_block[0][0], "create")
lines = lines_block[0][1]
self.assertEqual(len(lines), 2)
self.assertEqual(lines[0]["product"], "1")
self.assertEqual(
lines[0]["quantity"],
{"__class__": "Decimal", "decimal": "2.00"},
)
self.assertEqual(lines[0]["type"], "line")
self.assertEqual(lines[0]["unit"], "1")
self.assertEqual(
lines[0]["unit_price"],
{"__class__": "Decimal", "decimal": "3000.00"},
)
self.assertEqual(lines[1]["product"], "1")
self.assertEqual(
lines[1]["quantity"],
{"__class__": "Decimal", "decimal": "3.00"},
)
self.assertEqual(lines[1]["type"], "line")
self.assertEqual(lines[1]["unit"], "1")
self.assertEqual(
lines[1]["unit_price"],
{"__class__": "Decimal", "decimal": "5000.00"},
)