- Introduced a new fixture, `test_tenant`, to allocate ephemeral tenant and company IDs for tests, reducing conflicts with real data. - Updated various test functions to use the new `test_tenant` fixture, ensuring consistent tenant ID usage across tests. - Enhanced the `ensure_tenant_company` function to accept dynamic tenant and company IDs, improving flexibility in test scenarios. - Adjusted database interaction in tests to utilize the ephemeral IDs, streamlining the setup process and enhancing isolation.
112 lines
4.7 KiB
Python
112 lines
4.7 KiB
Python
from decimal import Decimal
|
|
|
|
from api.v1.modules.a24.balance_movements.models import BalanceMovement, MovementType
|
|
from api.v1.modules.a24.discharges.models import DischargeDetail, DischargeHeader
|
|
from api.v1.modules.a76.invoices.imports.process import main_process as import_main
|
|
from api.v1.modules.a76.invoices.exports.process import main_process as export_main
|
|
from tests.fixtures.builders import (
|
|
create_business_catalogs,
|
|
create_export_invoice_with_line,
|
|
create_import_invoice_with_line,
|
|
ensure_reference_data,
|
|
)
|
|
|
|
|
|
def _patch_import_pipeline(monkeypatch, import_line):
|
|
monkeypatch.setattr(import_main, "pre_validators", lambda *args, **kwargs: [import_line])
|
|
monkeypatch.setattr(import_main, "review_classes", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(import_main, "review_exchange_rate", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(import_main, "review_weights_kgs", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(import_main, "review_weights_lbs", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(import_main, "_validate_sisimp_limits", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(import_main, "_validate_lines", lambda *args, **kwargs: ([], {}))
|
|
|
|
|
|
def _patch_export_pipeline(monkeypatch, export_line):
|
|
monkeypatch.setattr(export_main, "pre_validators", lambda *args, **kwargs: [export_line])
|
|
monkeypatch.setattr(export_main, "review_class", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(export_main, "review_exchange_rate", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(export_main, "assign_values", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(export_main, "review_qty_vs_weight", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(export_main, "review_unit_cost", lambda *args, **kwargs: None)
|
|
monkeypatch.setattr(export_main, "review_qty_series", lambda *args, **kwargs: None)
|
|
|
|
|
|
def test_e2e_inventory_flow_import_then_export(client, db_session, monkeypatch, test_tenant):
|
|
"""
|
|
E2E principal:
|
|
- Alta catálogos/base
|
|
- Procesa factura IMP -> genera entry
|
|
- Procesa factura EXP -> genera consumo/descarga
|
|
- Valida decremento de saldo sin negativos
|
|
"""
|
|
tid, cid = test_tenant.tenant_id, test_tenant.company_id
|
|
ensure_reference_data(db_session)
|
|
catalogs = create_business_catalogs(db_session, tenant_id=tid, company_id=cid)
|
|
|
|
import_invoice, import_line = create_import_invoice_with_line(
|
|
db_session, tid, cid, catalogs, invoice_type="TEM", invoice_number="IMP-E2E-01", qty=Decimal("10")
|
|
)
|
|
_patch_import_pipeline(monkeypatch, import_line)
|
|
|
|
response = client.post(f"/api/v1/a76/invoices/{import_invoice.id}/process?company_id={cid}")
|
|
assert response.status_code == 200
|
|
|
|
entry_movements = (
|
|
db_session.query(BalanceMovement)
|
|
.filter(
|
|
BalanceMovement.import_invoice_id == import_invoice.id,
|
|
BalanceMovement.import_item_line_id == import_line.id,
|
|
BalanceMovement.movement_type == MovementType.ENTRY,
|
|
)
|
|
.all()
|
|
)
|
|
assert entry_movements
|
|
assert sum(Decimal(str(m.quantity or 0)) for m in entry_movements) > 0
|
|
|
|
export_invoice, export_line = create_export_invoice_with_line(
|
|
db_session, tid, cid, catalogs, import_invoice, import_line, qty=Decimal("4")
|
|
)
|
|
_patch_export_pipeline(monkeypatch, export_line)
|
|
|
|
response = client.post(f"/api/v1/a76/invoices/{export_invoice.id}/process?company_id={cid}")
|
|
assert response.status_code == 200
|
|
|
|
consumptions = (
|
|
db_session.query(BalanceMovement)
|
|
.filter(
|
|
BalanceMovement.source_invoice_id == export_invoice.id,
|
|
BalanceMovement.movement_type == MovementType.CONSUMPTION,
|
|
)
|
|
.all()
|
|
)
|
|
assert consumptions, "El proceso de exportación debe generar consumos"
|
|
|
|
discharge_headers = (
|
|
db_session.query(DischargeHeader)
|
|
.filter(DischargeHeader.source_invoice_id == export_invoice.id)
|
|
.all()
|
|
)
|
|
assert discharge_headers
|
|
|
|
discharge_details = (
|
|
db_session.query(DischargeDetail)
|
|
.filter(DischargeDetail.export_item_line_id == export_line.id)
|
|
.all()
|
|
)
|
|
assert discharge_details
|
|
assert all(detail.movement_id is not None for detail in discharge_details)
|
|
|
|
net_balance = db_session.query(BalanceMovement).filter(
|
|
BalanceMovement.import_item_line_id == import_line.id
|
|
).all()
|
|
signed = Decimal("0")
|
|
for mov in net_balance:
|
|
qty = Decimal(str(mov.quantity or 0))
|
|
if mov.movement_type in {MovementType.CONSUMPTION, MovementType.WASTE, MovementType.SCRAP, MovementType.DESTRUCTION}:
|
|
signed -= qty
|
|
else:
|
|
signed += qty
|
|
assert signed >= 0
|
|
assert signed < Decimal("10")
|