refactor: move capacity_forecast_service from billing to monitoring
Some checks failed
CI / ruff (push) Failing after 8s
CI / pytest (push) Successful in 36m5s
CI / architecture (push) Successful in 11s
CI / dependency-scanning (push) Successful in 27s
CI / docs (push) Has been skipped
CI / audit (push) Successful in 8s

Resolves the billing (core) → monitoring (optional) architecture violation
by moving CapacityForecastService to the monitoring module where it belongs.

- Create BillingMetricsProvider to expose subscription counts via stats_aggregator
- Move CapacitySnapshot model from billing to monitoring
- Replace direct MerchantSubscription queries with stats_aggregator calls
- Fix middleware test mocks to cover StoreDomain/MerchantDomain fallback chains

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 20:58:22 +01:00
parent 7c43d6f4a2
commit 9c27fa02b0
16 changed files with 234 additions and 102 deletions

View File

@@ -312,7 +312,10 @@ class TestPlatformContextManager:
def test_get_platform_from_domain_not_found(self):
"""Test domain lookup when platform not found."""
mock_db = Mock(spec=Session)
mock_db.query.return_value.filter.return_value.filter.return_value.first.return_value = None
# Ensure all query chain variants return None for .first()
query_mock = mock_db.query.return_value
query_mock.filter.return_value.first.return_value = None
query_mock.filter.return_value.filter.return_value.first.return_value = None
context = {"detection_method": "domain", "domain": "unknown.lu"}
@@ -367,8 +370,11 @@ class TestPlatformContextManager:
def test_get_platform_inactive_not_returned(self):
"""Test that inactive platforms are not returned."""
mock_db = Mock(spec=Session)
# First call returns None (is_active filter excludes it)
mock_db.query.return_value.filter.return_value.filter.return_value.first.return_value = None
# Ensure all query chain variants return None for .first()
# (primary Platform lookup and StoreDomain/MerchantDomain fallbacks)
query_mock = mock_db.query.return_value
query_mock.filter.return_value.first.return_value = None
query_mock.filter.return_value.filter.return_value.first.return_value = None
context = {"detection_method": "domain", "domain": "inactive.lu"}

View File

@@ -245,7 +245,13 @@ class TestStoreContextManager:
def test_get_store_from_custom_domain_not_found(self):
"""Test custom domain not found in database."""
mock_db = Mock(spec=Session)
mock_db.query.return_value.filter.return_value.filter.return_value.filter.return_value.first.return_value = None
# Ensure all query chain variants return None for .first()
# (primary StoreDomain lookup and MerchantDomain fallback)
query_mock = mock_db.query.return_value
query_mock.filter.return_value.first.return_value = None
query_mock.filter.return_value.filter.return_value.first.return_value = None
query_mock.filter.return_value.filter.return_value.filter.return_value.first.return_value = None
query_mock.filter.return_value.order_by.return_value.first.return_value = None
context = {"detection_method": "custom_domain", "domain": "nonexistent.com"}