diff --git a/app/cabinet/routes/admin_users.py b/app/cabinet/routes/admin_users.py index 86d76033..3d049884 100644 --- a/app/cabinet/routes/admin_users.py +++ b/app/cabinet/routes/admin_users.py @@ -318,11 +318,10 @@ async def _sync_subscription_to_panel( if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if ext_squad_uuid is not None: update_kwargs['external_squad_uuid'] = ext_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None try: updated_panel_user = await api.update_user(**update_kwargs) @@ -2777,11 +2776,10 @@ async def sync_user_to_panel( update_kwargs['hwid_device_limit'] = hwid_limit changes['device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if ext_squad_uuid is not None: update_kwargs['external_squad_uuid'] = ext_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None try: await api.update_user(**update_kwargs) diff --git a/app/cabinet/routes/subscription.py b/app/cabinet/routes/subscription.py index c04238ea..951a0d97 100644 --- a/app/cabinet/routes/subscription.py +++ b/app/cabinet/routes/subscription.py @@ -3762,17 +3762,27 @@ async def reduce_devices( old_device_limit = current_device_limit - # Update subscription + # Update subscription in memory (will be committed by update_remnawave_user on success) subscription.device_limit = new_device_limit subscription.updated_at = datetime.now(UTC) - await db.commit() - # Update RemnaWave - try: - subscription_service = SubscriptionService() - await subscription_service.update_remnawave_user(db, subscription) - except Exception as e: - logger.error('Error updating RemnaWave user', error=e) + # Update RemnaWave — commits on success, returns None on failure + subscription_service = SubscriptionService() + result = await subscription_service.update_remnawave_user(db, subscription) + + if result is None: + # RemnaWave update failed — rollback local changes + await db.rollback() + logger.error( + 'Failed to update RemnaWave after device limit reduction', + user_id=user.id, + old_device_limit=old_device_limit, + new_device_limit=new_device_limit, + ) + raise HTTPException( + status_code=status.HTTP_502_BAD_GATEWAY, + detail='Не удалось обновить VPN-панель. Попробуйте позже.', + ) logger.info( f'User {user.id} reduced device limit from {old_device_limit} to {new_device_limit}' diff --git a/app/handlers/admin/users.py b/app/handlers/admin/users.py index d8ea5e22..5c8a8552 100644 --- a/app/handlers/admin/users.py +++ b/app/handlers/admin/users.py @@ -4590,11 +4590,10 @@ async def admin_buy_subscription_execute(callback: types.CallbackQuery, db_user: if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if ext_squad_uuid is not None: update_kwargs['external_squad_uuid'] = ext_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None remnawave_user = await api.update_user(**update_kwargs) else: diff --git a/app/services/monitoring_service.py b/app/services/monitoring_service.py index 0ba7b0c8..444ea13a 100644 --- a/app/services/monitoring_service.py +++ b/app/services/monitoring_service.py @@ -390,11 +390,10 @@ class MonitoringService: if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if subscription.tariff and subscription.tariff.external_squad_uuid: update_kwargs['external_squad_uuid'] = subscription.tariff.external_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None updated_user = await api.update_user(**update_kwargs) diff --git a/app/services/remnawave_service.py b/app/services/remnawave_service.py index 73106a4d..a13a3918 100644 --- a/app/services/remnawave_service.py +++ b/app/services/remnawave_service.py @@ -1961,11 +1961,10 @@ class RemnaWaveService: if hwid_limit is not None: create_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if sub.tariff and sub.tariff.external_squad_uuid: create_kwargs['external_squad_uuid'] = sub.tariff.external_squad_uuid - else: - create_kwargs['external_squad_uuid'] = None # Определяем UUID для обновления panel_uuid = user.remnawave_uuid @@ -2007,11 +2006,10 @@ class RemnaWaveService: if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: синхронизируем из тарифа или сбрасываем + # Внешний сквад: синхронизируем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if sub.tariff and sub.tariff.external_squad_uuid: update_kwargs['external_squad_uuid'] = sub.tariff.external_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None try: await api.update_user(**update_kwargs) diff --git a/app/services/subscription_service.py b/app/services/subscription_service.py index 40709174..340aa40b 100644 --- a/app/services/subscription_service.py +++ b/app/services/subscription_service.py @@ -238,11 +238,10 @@ class SubscriptionService: if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit - # Внешний сквад: назначаем из тарифа или сбрасываем + # Внешний сквад: назначаем из тарифа (если задан) + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if ext_squad_uuid is not None: update_kwargs['external_squad_uuid'] = ext_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None updated_user = await api.update_user(**update_kwargs) @@ -872,10 +871,9 @@ class SubscriptionService: if hwid_limit is not None: update_kwargs['hwid_device_limit'] = hwid_limit + # Не отправляем null — RemnaWave API не принимает null для externalSquadUuid (A039) if ext_squad_uuid is not None: update_kwargs['external_squad_uuid'] = ext_squad_uuid - else: - update_kwargs['external_squad_uuid'] = None updated_user = await api.update_user(**update_kwargs)