fix(tariff-worker): match premium bandwidth stats by username, not uuid

This commit is contained in:
3252a8
2026-05-12 11:20:23 +03:00
parent 00a0792c35
commit 8af59750c6
2 changed files with 45 additions and 9 deletions
+29 -3
View File
@@ -78,6 +78,7 @@ class TariffTrafficWorker:
panel_data = await self.panel_service.get_user_by_uuid(sub.panel_user_uuid, log_response=False) or {}
used, limit, panel_strategy = self.subscription_service._extract_panel_traffic_details(panel_data)
panel_status = str(panel_data.get("status") or "").upper()
panel_username = panel_data.get("username") if isinstance(panel_data, dict) else None
if used is not None and used != sub.traffic_used_bytes:
sub.traffic_used_bytes = used
if limit is not None and limit != sub.traffic_limit_bytes:
@@ -96,7 +97,7 @@ class TariffTrafficWorker:
warning_period_start=warning_period_start if tariff.billing_model == "period" else None,
)
await self._sync_premium_squad_limit(session, sub, tariff, now)
await self._sync_premium_squad_limit(session, sub, tariff, now, panel_username=panel_username)
async def _ensure_period_reset_strategy(
self,
@@ -190,6 +191,8 @@ class TariffTrafficWorker:
sub: Subscription,
tariff,
now: datetime,
*,
panel_username: Optional[str] = None,
) -> None:
if not getattr(tariff, "premium_squad_uuids", None):
if any(
@@ -222,7 +225,13 @@ class TariffTrafficWorker:
start_date = now.date().replace(day=1).isoformat()
end_date = now.date().isoformat()
premium_used = await self._premium_usage_for_user(sub.panel_user_uuid, node_uuids, start_date, end_date)
premium_used = await self._premium_usage_for_user(
sub.panel_user_uuid,
node_uuids,
start_date,
end_date,
panel_username=panel_username,
)
if premium_used is None:
return
@@ -379,9 +388,12 @@ class TariffTrafficWorker:
node_uuids: list[str],
start_date: str,
end_date: str,
*,
panel_username: Optional[str] = None,
) -> Optional[int]:
total = 0
found = False
username = (panel_username or "").strip() or None
for node_uuid in node_uuids:
stats = await self.panel_service.get_node_users_bandwidth_stats(
node_uuid,
@@ -403,7 +415,21 @@ class TariffTrafficWorker:
or entry.get("uuid")
or entry.get("user_uuid")
)
if entry_uuid != user_uuid:
entry_username = (
user_obj.get("username")
or entry.get("username")
or entry.get("userUsername")
)
# Remnawave's /bandwidth-stats/nodes/{uuid}/users response
# currently exposes only {color, username, total}; match by
# username first, fall back to UUID if a future version
# adds it back.
matched = False
if entry_uuid and entry_uuid == user_uuid:
matched = True
elif username and entry_username and entry_username == username:
matched = True
if not matched:
continue
value = entry.get("total")
if value is None:
+16 -6
View File
@@ -148,7 +148,7 @@ class TariffWorkerTests(unittest.IsolatedAsyncioTestCase):
return_value={
"topUsers": [
{
"user": {"uuid": "panel-uuid"},
"username": "tg_123",
"total": 2 * (1024**3),
}
]
@@ -176,7 +176,13 @@ class TariffWorkerTests(unittest.IsolatedAsyncioTestCase):
tariff = settings.tariffs_config.require("standard")
with patch("bot.services.tariff_worker.tariff_dal.get_warning", new=AsyncMock(return_value=True)):
await worker._sync_premium_squad_limit(AsyncMock(), sub, tariff, datetime.now(timezone.utc))
await worker._sync_premium_squad_limit(
AsyncMock(),
sub,
tariff,
datetime.now(timezone.utc),
panel_username="tg_123",
)
self.assertTrue(sub.premium_is_limited)
panel_service.update_user_details_on_panel.assert_awaited_once()
@@ -205,7 +211,7 @@ class TariffWorkerTests(unittest.IsolatedAsyncioTestCase):
return_value={
"topUsers": [
{
"user": {"uuid": "panel-uuid"},
"username": "tg_123",
"total": int(1.5 * (1024**3)),
}
]
@@ -233,7 +239,9 @@ class TariffWorkerTests(unittest.IsolatedAsyncioTestCase):
)
tariff = settings.tariffs_config.require("standard")
await worker._sync_premium_squad_limit(AsyncMock(), sub, tariff, now)
await worker._sync_premium_squad_limit(
AsyncMock(), sub, tariff, now, panel_username="tg_123"
)
self.assertEqual(sub.premium_topup_balance_bytes, int(1.5 * (1024**3)))
self.assertEqual(sub.premium_topup_used_bytes, int(0.5 * (1024**3)))
@@ -243,14 +251,16 @@ class TariffWorkerTests(unittest.IsolatedAsyncioTestCase):
return_value={
"topUsers": [
{
"user": {"uuid": "panel-uuid"},
"username": "tg_123",
"total": int(0.1 * (1024**3)),
}
]
}
)
next_month = datetime(2026, 6, 2, tzinfo=timezone.utc)
await worker._sync_premium_squad_limit(AsyncMock(), sub, tariff, next_month)
await worker._sync_premium_squad_limit(
AsyncMock(), sub, tariff, next_month, panel_username="tg_123"
)
self.assertEqual(sub.premium_topup_balance_bytes, int(1.5 * (1024**3)))
self.assertEqual(sub.premium_topup_used_bytes, 0)