bmc_hub/tests/test_workflow_billing_preview.py

66 lines
3.3 KiB
Python
Raw Normal View History

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'