66 lines
3.3 KiB
Python
66 lines
3.3 KiB
Python
from contextlib import contextmanager
|
|
|
|
from app.workflows import preview
|
|
|
|
|
|
class ReadOnlyCursor:
|
|
def __init__(self, agreements=(), cards=(), rules=()):
|
|
self.pools = {'customer_fixed_price_agreements': agreements, 'tticket_prepaid_cards': cards, 'bmc_workflows': rules}
|
|
self.queries = []
|
|
self.rows = []
|
|
|
|
def execute(self, sql, params=None):
|
|
assert sql.startswith('SELECT '), 'Preview must not write'
|
|
self.queries.append((sql, params))
|
|
self.rows = next((rows for table, rows in self.pools.items() if table in sql), [])
|
|
|
|
def fetchall(self):
|
|
return self.rows
|
|
|
|
|
|
def setup_preview(monkeypatch, cursor, active=True):
|
|
@contextmanager
|
|
def transaction():
|
|
yield cursor
|
|
monkeypatch.setattr(preview, 'transaction', transaction)
|
|
monkeypatch.setattr(preview, 'load_case_context', lambda *args: {'id': 10, 'customer_id': '7', 'tag_ids': [3], 'concrete_tag_ids': [3], 'titel': 'Test', 'beskrivelse': 'Case text'})
|
|
monkeypatch.setattr(preview, 'active_for_customer', lambda customer_id: active)
|
|
monkeypatch.setattr(preview, 'enrich_entity_context', lambda cursor, context, entity_type, entity_id: context)
|
|
|
|
|
|
def test_inactive_returns_draft_without_loading_rules_or_resources(monkeypatch):
|
|
cursor = ReadOnlyCursor()
|
|
setup_preview(monkeypatch, cursor, active=False)
|
|
assert preview.preview_case_billing(10)['method'] == 'draft'
|
|
assert cursor.queries == []
|
|
|
|
|
|
def test_coverage_predicts_fast_price_without_saving_or_exposing_trace(monkeypatch):
|
|
cursor = ReadOnlyCursor(agreements=[{'id': 9, 'workflow_coverage': {'tag_ids': [3]}}])
|
|
setup_preview(monkeypatch, cursor)
|
|
assert preview.preview_case_billing(10) == {'status': 'decided', 'method': 'subscription', 'reason': 'resource_coverage', 'agreement_id': 9}
|
|
assert all(params is None or params[0] == 7 for sql, params in cursor.queries)
|
|
assert 'expires_at>now()' in cursor.queries[1][0]
|
|
assert 'cancellation_effective_date' in cursor.queries[0][0]
|
|
|
|
|
|
def test_explicit_rule_takes_precedence_over_coverage(monkeypatch):
|
|
rule = {'id': 1, 'definition': {'trigger': 'time.created', 'branches': [{'condition': {'field': 'description', 'operator': 'contains', 'value': 'intern'}, 'actions': [{'type': 'set_billing', 'method': 'internal'}]}]}}
|
|
cursor = ReadOnlyCursor(agreements=[{'id': 9, 'workflow_coverage': {'tag_ids': [3]}}], rules=[rule])
|
|
setup_preview(monkeypatch, cursor)
|
|
assert preview.preview_case_billing(10, description='intern opgave')['method'] == 'internal'
|
|
|
|
|
|
def test_prepaid_prediction_checks_requested_minutes(monkeypatch):
|
|
cursor = ReadOnlyCursor(cards=[{'id': 4, 'remaining_hours': .5, 'workflow_coverage': {'tag_ids': [3]}}])
|
|
setup_preview(monkeypatch, cursor)
|
|
assert preview.preview_case_billing(10, minutes=30)['method'] == 'prepaid'
|
|
assert preview.preview_case_billing(10, minutes=60)['reason'] == 'insufficient_card_balance'
|
|
|
|
|
|
def test_pending_tag_review_remains_blocking(monkeypatch):
|
|
cursor = ReadOnlyCursor(agreements=[{'id': 9, 'workflow_coverage': {'tag_ids': [3]}}])
|
|
setup_preview(monkeypatch, cursor)
|
|
monkeypatch.setattr(preview, 'enrich_entity_context', lambda cursor, context, entity_type, entity_id: dict(context, pending_billing_tag_suggestions=['case_proposal:1']))
|
|
assert preview.preview_case_billing(10)['reason'] == 'pending_tag_approval'
|