import unittest from datetime import datetime, timezone from types import SimpleNamespace from unittest.mock import AsyncMock, patch from bot.services.tariff_worker import TariffTrafficWorker class _Service: def _base_hwid_limit_for_tariff(self, tariff): return tariff.hwid_device_limit @staticmethod def _effective_hwid_limit(base_limit, extra_devices=0): if base_limit is None: return None base_int = max(0, int(base_limit)) if base_int == 0: return 0 return base_int + max(0, int(extra_devices or 0)) @staticmethod def _build_panel_update_payload( *, panel_user_uuid=None, expire_at=None, hwid_device_limit=None, include_default_squads=True, **_kwargs, ): payload = {} if panel_user_uuid: payload["uuid"] = panel_user_uuid if expire_at: payload["expireAt"] = expire_at.isoformat(timespec="milliseconds").replace( "+00:00", "Z" ) if hwid_device_limit is not None: payload["hwidDeviceLimit"] = int(hwid_device_limit) return payload class HwidDeviceWorkerTests(unittest.IsolatedAsyncioTestCase): async def test_worker_resets_expired_hwid_entitlement_on_panel(self): panel = SimpleNamespace(update_user_details_on_panel=AsyncMock(return_value={"ok": True})) worker = TariffTrafficWorker( settings=SimpleNamespace(), session_factory=None, panel_service=panel, subscription_service=_Service(), ) sub = SimpleNamespace( subscription_id=11, panel_user_uuid="panel-user", end_date=datetime(2099, 1, 1, tzinfo=timezone.utc), hwid_device_limit=3, extra_hwid_devices=2, ) tariff = SimpleNamespace(hwid_device_limit=3) with patch( "bot.services.tariff_worker.tariff_dal.sum_active_hwid_devices", AsyncMock(return_value=0), ): await worker._sync_hwid_device_limit( session=AsyncMock(), sub=sub, tariff=tariff, panel_data={"hwidDeviceLimit": 5}, ) self.assertEqual(sub.extra_hwid_devices, 0) panel_payload = panel.update_user_details_on_panel.await_args.args[1] self.assertEqual(panel_payload["hwidDeviceLimit"], 3) if __name__ == "__main__": # pragma: no cover unittest.main()