2026-09-11 15:45:46 +02:00
|
|
|
def test_order_export_inherits_global_safety_flags_when_order_flags_are_unset(monkeypatch):
|
|
|
|
|
from app.modules.orders.backend import economic_export
|
|
|
|
|
|
|
|
|
|
settings = economic_export.settings
|
|
|
|
|
monkeypatch.setattr(settings, "ECONOMIC_READ_ONLY", False)
|
|
|
|
|
monkeypatch.setattr(settings, "ECONOMIC_DRY_RUN", False)
|
|
|
|
|
monkeypatch.setattr(settings, "ORDRE_ECONOMIC_READ_ONLY", True)
|
|
|
|
|
monkeypatch.setattr(settings, "ORDRE_ECONOMIC_DRY_RUN", True)
|
|
|
|
|
fields_set = set(settings.model_fields_set)
|
|
|
|
|
fields_set.discard("ORDRE_ECONOMIC_READ_ONLY")
|
|
|
|
|
fields_set.discard("ORDRE_ECONOMIC_DRY_RUN")
|
|
|
|
|
monkeypatch.setattr(settings, "__pydantic_fields_set__", fields_set)
|
|
|
|
|
|
|
|
|
|
service = economic_export.OrdreEconomicExportService()
|
|
|
|
|
|
|
|
|
|
assert service.read_only is False
|
|
|
|
|
assert service.dry_run is False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_order_export_respects_explicit_order_safety_flags(monkeypatch):
|
|
|
|
|
from app.modules.orders.backend import economic_export
|
|
|
|
|
|
|
|
|
|
settings = economic_export.settings
|
|
|
|
|
monkeypatch.setattr(settings, "ECONOMIC_READ_ONLY", False)
|
|
|
|
|
monkeypatch.setattr(settings, "ECONOMIC_DRY_RUN", False)
|
|
|
|
|
monkeypatch.setattr(settings, "ORDRE_ECONOMIC_READ_ONLY", True)
|
|
|
|
|
monkeypatch.setattr(settings, "ORDRE_ECONOMIC_DRY_RUN", True)
|
|
|
|
|
fields_set = set(settings.model_fields_set)
|
|
|
|
|
fields_set.update({"ORDRE_ECONOMIC_READ_ONLY", "ORDRE_ECONOMIC_DRY_RUN"})
|
|
|
|
|
monkeypatch.setattr(settings, "__pydantic_fields_set__", fields_set)
|
|
|
|
|
|
|
|
|
|
service = economic_export.OrdreEconomicExportService()
|
|
|
|
|
|
|
|
|
|
assert service.read_only is True
|
|
|
|
|
assert service.dry_run is True
|
2026-09-11 16:46:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_economic_validation_error_is_exposed_without_developer_metadata():
|
|
|
|
|
from app.modules.orders.backend.economic_export import _economic_error_message
|
|
|
|
|
|
|
|
|
|
message = _economic_error_message(
|
|
|
|
|
400,
|
|
|
|
|
'{"message":"Validation failed","errors":{"paymentTerms":"Required"},"developerHint":"internal"}',
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert "Validation failed" in message
|
|
|
|
|
assert "paymentTerms" in message
|
|
|
|
|
assert "Required" in message
|
|
|
|
|
assert "internal" not in message
|
2026-09-13 09:33:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_order_export_blocks_priced_line_when_product_does_not_exist():
|
|
|
|
|
from fastapi import HTTPException
|
|
|
|
|
from app.modules.orders.backend.economic_export import _require_valid_product_numbers
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
_require_valid_product_numbers({"1000", "UKENDT"}, {"1000"})
|
|
|
|
|
assert False, "missing product must block the export before POST"
|
|
|
|
|
except HTTPException as exc:
|
|
|
|
|
assert exc.status_code == 409
|
|
|
|
|
assert "UKENDT" in exc.detail
|
|
|
|
|
assert "Ordren blev ikke sendt" in exc.detail
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_order_export_accepts_only_verified_products():
|
|
|
|
|
from app.modules.orders.backend.economic_export import _require_valid_product_numbers
|
|
|
|
|
|
|
|
|
|
assert _require_valid_product_numbers({"1000"}, {"1000"}) == []
|
2026-09-13 09:56:24 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_product_creation_preview_values_become_economic_payload():
|
|
|
|
|
from app.modules.orders.backend.economic_export import _product_creation_payload
|
|
|
|
|
|
|
|
|
|
payload = _product_creation_payload({
|
|
|
|
|
"product_number": "W2211X",
|
|
|
|
|
"name": "HP 207X Cyan",
|
|
|
|
|
"description": "Original toner",
|
|
|
|
|
"ean": "0194850012345",
|
|
|
|
|
"sales_price": 899.95,
|
|
|
|
|
}, 2)
|
|
|
|
|
|
|
|
|
|
assert payload == {
|
|
|
|
|
"productNumber": "W2211X",
|
|
|
|
|
"name": "HP 207X Cyan",
|
|
|
|
|
"description": "Original toner",
|
|
|
|
|
"salesPrice": 899.95,
|
|
|
|
|
"barCode": "0194850012345",
|
|
|
|
|
"barred": False,
|
|
|
|
|
"productGroup": {"productGroupNumber": 2},
|
|
|
|
|
}
|
2026-09-13 11:24:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_legacy_draft_id_is_saved_as_order_number():
|
|
|
|
|
from app.modules.orders.backend.router import _economic_order_number
|
|
|
|
|
|
|
|
|
|
assert _economic_order_number({"economic_draft_id": 4711}) == 4711
|
2026-09-13 11:41:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_exported_status_requires_economic_order_number():
|
|
|
|
|
from fastapi import HTTPException
|
|
|
|
|
from app.modules.orders.backend.router import _validate_sync_status_number
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
_validate_sync_status_number("exported", None, None)
|
|
|
|
|
assert False, "exported status without an external order number must be rejected"
|
|
|
|
|
except HTTPException as exc:
|
|
|
|
|
assert exc.status_code == 409
|
|
|
|
|
_validate_sync_status_number("exported", None, "4711")
|