bmc_hub/tests/test_invoice_error_finder.py
2026-07-11 11:48:42 +02:00

238 lines
7.3 KiB
Python

import asyncio
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
def test_simply_import_service_persists_multi_line_orders_without_overwrite(monkeypatch):
from app.modules.invoice_error_finder.services.simply_import_service import SimplyImportService
captured = []
def fake_execute_query(query, params=None):
if "INSERT INTO invoice_error_finder_simply_sales_orders" in query:
captured.append(params)
return []
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.simply_import_service.execute_query",
fake_execute_query,
)
service = SimplyImportService()
service._persist_order(
7,
{
"id": "SO-14",
"salesorder_no": "SO-14",
"account_id": "A-1",
"accountname": "Testkunde",
"sostatus": "Approved",
"LineItems": [
{"productnumber": "P1", "productname": "Linje 1", "quantity": 1, "listprice": 10, "netprice": 10},
{"productnumber": "P2", "productname": "Linje 2", "quantity": 2, "listprice": 20, "netprice": 40},
],
},
)
assert len(captured) == 2
assert captured[0][1] != captured[1][1]
assert captured[0][1].startswith("SO-14:")
assert captured[1][1].startswith("SO-14:")
def test_economic_import_service_persists_valid_json(monkeypatch):
from app.modules.invoice_error_finder.services.economic_import_service import EconomicImportService
captured = {}
def fake_execute_query_single(query, params=None):
if "INSERT INTO invoice_error_finder_economic_invoices" in query:
captured["invoice_raw"] = params[-1]
return {"id": 11}
return {"id": 11}
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.economic_import_service.execute_query_single",
fake_execute_query_single,
)
service = EconomicImportService()
invoice_id = service._persist_invoice(
3,
{
"bookedInvoiceNumber": 123,
"customer": {"customerNumber": 10, "name": "ACME"},
"date": "2026-07-01",
"grossAmount": 100,
},
)
assert invoice_id == 11
assert json.loads(captured["invoice_raw"])["bookedInvoiceNumber"] == 123
def test_economic_import_service_defaults_missing_line_amounts(monkeypatch):
from app.modules.invoice_error_finder.services.economic_import_service import EconomicImportService
captured = []
def fake_execute_query(query, params=None):
if "INSERT INTO invoice_error_finder_economic_invoice_lines" in query:
captured.append(params)
return []
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.economic_import_service.execute_query",
fake_execute_query,
)
service = EconomicImportService()
service._persist_lines(
99,
[
{
"lineNumber": 1,
"description": "Mobilnummer",
"quantity": None,
"unitNetPrice": None,
"totalNetAmount": None,
"discountPercentage": None,
}
],
)
assert len(captured) == 1
assert captured[0][5] == 0.0
assert captured[0][6] == 0.0
assert captured[0][7] == 0.0
assert captured[0][8] == 0.0
def test_detection_service_keeps_customers_without_subscriptions(monkeypatch):
from app.modules.invoice_error_finder.services.detection_service import DetectionService
def fake_execute_query_single(query, params=None):
if "SELECT deleted_at FROM customers" in query:
return {"deleted_at": None}
return None
def fake_execute_query(query, params=None):
if "FROM sag_subscriptions" in query:
return []
return []
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.detection_service.execute_query_single",
fake_execute_query_single,
)
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.detection_service.execute_query",
fake_execute_query,
)
service = DetectionService()
assert service._is_customer_closed_or_cancelled(55, __import__("datetime").date(2026, 7, 1)) is False
def test_detection_service_reopens_expired_ignored_issue(monkeypatch):
from datetime import date
from app.modules.invoice_error_finder.services.detection_service import DetectionService
updates = []
def fake_execute_query_single(query, params=None):
if "FROM invoice_error_finder_issues" in query and "SELECT id, status" in query:
return {"id": 9, "status": "ignored"}
if "SELECT ignored_until FROM invoice_error_finder_issues" in query:
return {"ignored_until": date(2026, 7, 1)}
return None
def fake_execute_query(query, params=None):
if "UPDATE invoice_error_finder_issues" in query:
updates.append((query, params))
return []
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.detection_service.execute_query_single",
fake_execute_query_single,
)
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.detection_service.execute_query",
fake_execute_query,
)
service = DetectionService()
issue_id = service._upsert_issue(
issue_type="missing_line",
customer_id=77,
product_number="P-1",
reference_period_start=date(2026, 7, 1),
reference_period_end=date(2026, 7, 31),
expected_quantity=2,
)
assert issue_id == 9
assert updates
assert "ignored_until = NULL" in updates[0][0]
def test_detection_service_ignores_non_hub_customer_keys(monkeypatch):
from app.modules.invoice_error_finder.services.detection_service import DetectionService
def fake_execute_query_single(query, params=None):
if "SELECT id FROM customers" in query:
return None
return None
monkeypatch.setattr(
"app.modules.invoice_error_finder.services.detection_service.execute_query_single",
fake_execute_query_single,
)
service = DetectionService()
customer_id = service._resolve_hub_customer_id(
{
"customer_key": 56283338,
"hub_customer_id": None,
}
)
assert customer_id is None
def test_list_issues_supports_unassigned_filter(monkeypatch):
from app.modules.invoice_error_finder.backend.router import list_issues
captured = {}
def fake_execute_query_single(query, params=None):
captured["count_query"] = query
return {"c": 0}
def fake_execute_query(query, params=None):
captured["list_query"] = query
return []
monkeypatch.setattr(
"app.modules.invoice_error_finder.backend.router.execute_query_single",
fake_execute_query_single,
)
monkeypatch.setattr(
"app.modules.invoice_error_finder.backend.router.execute_query",
fake_execute_query,
)
payload = asyncio.run(
list_issues(
assigned_user_id="null",
current_user={},
)
)
assert payload["total"] == 0
assert "assigned_user_id IS NULL" in captured["count_query"]
assert "assigned_user_id IS NULL" in captured["list_query"]