import asyncio import pytest from fastapi import HTTPException from app.core.config import settings from importlib import import_module router = import_module("app.timetracking.backend.router") from app.workflows import integration, settlement @pytest.fixture def active(monkeypatch): monkeypatch.setattr(settings, 'WORKFLOWS_ENABLED', True) monkeypatch.setattr(settings, 'WORKFLOWS_MODE', 'active') monkeypatch.setattr(integration, 'active_for_customer', lambda customer: customer == 24) monkeypatch.setattr(settlement, 'workflow_customer', lambda _: 24) @pytest.mark.parametrize('is_internal', [False, True]) def test_active_internal_registration_cannot_debit_or_preapprove(monkeypatch, active, is_internal): captured = {} monkeypatch.setattr(router, 'execute_query_single', lambda *_: {'customer_id': 24}) def forbidden(*args, **kwargs): pytest.fail('No financial side effect or card lookup allowed at registration') monkeypatch.setattr(router, 'execute_update', forbidden) monkeypatch.setattr(router, '_case_billing_choice', forbidden) def insert(sql, values): captured['values'] = values return [{'id': 1}] monkeypatch.setattr(router, 'execute_query', insert) result = asyncio.run(router.create_internal_time_entry({'sag_id': 9, 'customer_id': 7, 'original_hours': 1, 'prepaid_card_id': 10, 'fixed_price_agreement_id': 11, 'billing_method': 'prepaid', 'approved_hours': 99, 'entry_status': 'godkendt', 'is_internal': is_internal}, current_user={'id': 1, 'username': 'tester'})) assert result['id'] == 1 params = captured['values'] assert params[7] == 'pending' assert params[9] == 'draft' assert params[10:12] == (None, None) assert params[13:15] == (None, None) assert params[21] == 'afventer' @pytest.mark.parametrize('payload', [{'entry_status': 'godkendt'}, {'billable': False}, {'rate_multiplier': 2}, {'fakturerbar_tid_min': 999}, {'round_block_min': 120}]) def test_patch_cannot_bypass_active_workflow_review(monkeypatch, active, payload): monkeypatch.setattr(router, 'execute_query_single', lambda *_: {'id': 1, 'vtiger_id': None, 'billing_method': 'invoice'}) monkeypatch.setattr(router, 'execute_query', lambda *_: pytest.fail('No update allowed')) with pytest.raises(HTTPException) as exc: asyncio.run(router.patch_time_entry_v1(1, payload, current_user={'id': 1, 'is_superadmin': True})) assert exc.value.status_code == 409 def test_wizard_cannot_approve_active_hub_time_even_old_invoice_method(monkeypatch, active): monkeypatch.setattr(router, 'execute_query_single', lambda *_: {'billing_method': 'invoice', 'vtiger_id': None}) monkeypatch.setattr(router, 'execute_query', lambda *_: pytest.fail('No approval update allowed')) with pytest.raises(HTTPException) as exc: asyncio.run(router.approve_time_entry(1, {}, current_user={'id': 1, 'is_superadmin': True})) assert exc.value.status_code == 409