Files
plantillas-proyectos/backend/tests/unit/invoices/test_balance_algorithm.py
AlexeerCT b750c35522 Add backend test job to CI workflow
- Introduced a new job in the CI workflow to run backend tests before the build process.
- Configured Python environment and installed dependencies from the backend requirements.
- Added a check for the TEST_DATABASE_URL secret to ensure it is defined before running tests.
- The test job must pass for the build job to execute, enhancing the reliability of the CI pipeline.
2026-03-24 12:33:21 -05:00

122 lines
4.0 KiB
Python

from datetime import date
from decimal import Decimal
from api.v1.modules.a24.balance_movements.models import BalanceMovement, MovementType
from api.v1.modules.a76.invoices.exports.process.sub_process.compare_balances import compare_balances
from api.v1.modules.a76.invoices.exports.process.sub_process.discharge_types import (
AvailableLot,
DownloadEntry,
)
from api.v1.modules.a76.invoices.exports.process.sub_process.fill_available_balances import (
_net_balance_for_lot,
)
from core.exceptions import ErrorCollector
from tests.fixtures.builders import (
create_business_catalogs,
create_import_invoice_with_line,
ensure_reference_data,
ensure_tenant_company,
)
def test_net_balance_accounts_for_returns_and_entry_void(db_session):
"""
Balance neto esperado:
entry 10 - consumption 4 + return 1 - entry_void 2 = 5
"""
ensure_reference_data(db_session)
ensure_tenant_company(db_session, tenant_id=1, company_id=1)
catalogs = create_business_catalogs(db_session, tenant_id=1, company_id=1)
import_invoice, import_line = create_import_invoice_with_line(
db_session,
1,
1,
catalogs,
invoice_type="TEM",
invoice_number="IMP-UNIT-01",
qty=Decimal("10"),
)
line_id = import_line.id
tenant_id = import_invoice.tenant_id
company_id = import_invoice.company_id
import_invoice_id = import_invoice.id
for idx, (mtype, qty) in enumerate(
[
(MovementType.ENTRY, Decimal("10")),
(MovementType.CONSUMPTION, Decimal("4")),
(MovementType.RETURN, Decimal("1")),
(MovementType.ENTRY_VOID, Decimal("2")),
],
start=1,
):
db_session.add(
BalanceMovement(
id=10000 + idx,
tenant_id=tenant_id,
company_id=company_id,
import_invoice_id=import_invoice_id,
import_item_line_id=line_id,
movement_type=mtype,
quantity=qty,
order_peps=10000 + idx,
operation_date=date(2026, 3, 20),
)
)
db_session.flush()
balance = _net_balance_for_lot(db_session, line_id, date(2026, 3, 21))
assert balance == Decimal("5")
def test_fifo_consumption_algorithm_uses_oldest_lots_first(db_session, monkeypatch):
"""
Verifica distribución FIFO (PEPS):
- lote1 (order=1, qty=3), lote2 (order=2, qty=5), demanda=6
- resultado: lote1 consume 3, lote2 consume 3, faltante 0
"""
monkeypatch.setattr(
"api.v1.modules.a76.invoices.exports.process.sub_process.compare_balances._resolve_import_uom",
lambda db, import_item_line_id: "PZA",
)
entry = DownloadEntry(
origin_procedure="TEM",
export_line=1,
part_number="PN-1",
class_code="CLS",
quantity=Decimal("6"),
quantity_used=Decimal("0"),
unit_of_measure="PZA",
import_invoice="IMP-1",
import_line=1,
line_item_id=1,
available_lots=[
AvailableLot(
import_item_line_id=11,
import_invoice_id=101,
part_number_id=None,
available_qty=Decimal("3"),
value_me=Decimal("0"),
value_mn=Decimal("0"),
order_peps=1,
),
AvailableLot(
import_item_line_id=12,
import_invoice_id=101,
part_number_id=None,
available_qty=Decimal("5"),
value_me=Decimal("0"),
value_mn=Decimal("0"),
order_peps=2,
),
],
)
errors = ErrorCollector()
compare_balances(db_session, export_invoice=None, to_discharge=[entry], errors=errors) # type: ignore[arg-type]
assert not errors.has_errors()
assert entry.quantity_used == Decimal("6")
assert entry.available_lots[0].consumed_qty == Decimal("3")
assert entry.available_lots[1].consumed_qty == Decimal("3")