Release v4928.1.4.2 stable
This commit is contained in:
109
tests/test_v4913_apply_reconstructed_process.py
Normal file
109
tests/test_v4913_apply_reconstructed_process.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""v4.9.13 regression tests for applying reconstructed processes.
|
||||
|
||||
The reconstruction is useful only if confirming a process updates the
|
||||
opportunity pipeline, Odoo links and commercial lines instead of leaving a loose
|
||||
reconciliation reference.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import types
|
||||
|
||||
if "sqlalchemy" not in sys.modules:
|
||||
sqlalchemy = types.ModuleType("sqlalchemy")
|
||||
sqlalchemy.text = lambda sql: sql
|
||||
sys.modules["sqlalchemy"] = sqlalchemy
|
||||
|
||||
if "app.db" not in sys.modules:
|
||||
app_db = types.ModuleType("app.db")
|
||||
app_db.engine = object()
|
||||
sys.modules["app.db"] = app_db
|
||||
|
||||
if "app.action_catalog" not in sys.modules:
|
||||
action_catalog = types.ModuleType("app.action_catalog")
|
||||
action_catalog.get_action_config = lambda code: {
|
||||
"route": "financeiro" if code == "SEND_INVOICE" else "rever",
|
||||
"action": "Enviar fatura ao cliente" if code == "SEND_INVOICE" else code,
|
||||
"action_required": True,
|
||||
"safe_to_post": False,
|
||||
}
|
||||
sys.modules["app.action_catalog"] = action_catalog
|
||||
|
||||
from app import reconciliation_service as svc
|
||||
|
||||
|
||||
def _odoo_item_with_delivery():
|
||||
return {
|
||||
"id": "odoo-sale-274",
|
||||
"source_system": "odoo",
|
||||
"external_type": "odoo_sale_order",
|
||||
"external_id": "274",
|
||||
"document_number": "S00274",
|
||||
"document_date": "2026-06-02",
|
||||
"amount": "537.00",
|
||||
"currency": "EUR",
|
||||
"payload": {
|
||||
"record": {
|
||||
"id": 274,
|
||||
"name": "S00274",
|
||||
"partner_external_id": 288,
|
||||
"partner_name": "ELEGANTLEGACY, LDA",
|
||||
"invoice_status": "to invoice",
|
||||
"fulfilment": {
|
||||
"physical_status": "shipped",
|
||||
"delivery_done": True,
|
||||
"invoice_pending": True,
|
||||
"lines": [
|
||||
{"id": 643, "product_name": "Wallbox 7.4KW", "qty_ordered": 1.0, "qty_delivered": 1.0, "qty_invoiced": 0.0, "price_unit": 160.0, "price_total": 160.0},
|
||||
{"id": 644, "product_name": "Wallbox 11KW", "qty_ordered": 1.0, "qty_delivered": 1.0, "qty_invoiced": 0.0, "price_unit": 178.0, "price_total": 178.0},
|
||||
{"id": 645, "product_name": "Wallbox 22KW", "qty_ordered": 1.0, "qty_delivered": 1.0, "qty_invoiced": 0.0, "price_unit": 199.0, "price_total": 199.0},
|
||||
{"id": 646, "product_name": "[Delivery_007] Standard delivery", "qty_ordered": 1.0, "qty_delivered": 0.0, "qty_invoiced": 0.0, "price_unit": 0.0, "price_total": 0.0},
|
||||
],
|
||||
"outgoing_pickings": [{"name": "WH/OUT/00295", "state": "done", "date_done": "2026-06-02 12:12:10"}],
|
||||
"productions": [{"name": "WH/MO/00477", "state": "done", "product_name": "Wallbox 7.4KW"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_odoo_importable_lines_skip_zero_delivery_carrier_line():
|
||||
lines = svc._odoo_importable_lines(_odoo_item_with_delivery())
|
||||
|
||||
assert [line["product_name"] for line in lines] == [
|
||||
"Wallbox 7.4KW",
|
||||
"Wallbox 11KW",
|
||||
"Wallbox 22KW",
|
||||
]
|
||||
assert sum(float(line["price_total"]) for line in lines) == 537.0
|
||||
|
||||
|
||||
def test_process_state_for_delivered_odoo_sale_points_to_invoice():
|
||||
state = svc.infer_reconciliation_process_state([_odoo_item_with_delivery()])
|
||||
|
||||
assert state["stage"] == "SHIPMENT_CREATED"
|
||||
assert state["action_code"] == "SEND_INVOICE"
|
||||
assert [step["external_type"] for step in state["steps"]] == [
|
||||
"odoo_sale_order",
|
||||
"odoo_sale_lines",
|
||||
"odoo_delivery",
|
||||
"odoo_invoice_pending",
|
||||
]
|
||||
|
||||
|
||||
def test_apply_reconstructed_process_hooks_are_present():
|
||||
source = open("app/reconciliation_service.py", encoding="utf-8").read()
|
||||
|
||||
assert "def _apply_reconstructed_process_to_opportunity" in source
|
||||
assert "_apply_reconstructed_process_to_opportunity(conn, items, opportunity_id" in source
|
||||
assert "def _upsert_opportunity_items_from_odoo_item" in source
|
||||
assert "metadata->>'source_line_id'" in source
|
||||
assert "system, external_type)" in source and "physical_validation" in source
|
||||
assert "Venda Odoo" not in source or "odoo_invoice_pending" in source
|
||||
|
||||
|
||||
def test_reconciliation_ui_supports_active_days_window():
|
||||
ui = open("app/admin_ui/pages/reconciliation.py", encoding="utf-8").read()
|
||||
|
||||
assert "days: Optional[int] = 3" in ui
|
||||
assert "Hoje" in ui and "7 dias" in ui and "30 dias" in ui
|
||||
assert "sync_odoo_reconciliation_candidates(limit=50, days=days)" in ui
|
||||
Reference in New Issue
Block a user