fix: separate HWID device renewal flows
Keep one-off device top-ups scoped to the active subscription term and move device renewal into subscription checkout. Carry HWID renewal metadata through provider callbacks and webhooks, including YooKassa saved-card flows. Add admin extension controls, docs, demo data, and regression coverage.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import unittest
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from db.dal import tariff_dal
|
||||
|
||||
|
||||
class _ScalarResult:
|
||||
def __init__(self, records):
|
||||
self._records = records
|
||||
|
||||
def scalars(self):
|
||||
return self
|
||||
|
||||
def all(self):
|
||||
return self._records
|
||||
|
||||
|
||||
class HwidDeviceBonusExtensionTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_extends_tail_purchase_when_it_covers_subscription_end(self):
|
||||
subscription_end = datetime(2099, 2, 1, tzinfo=timezone.utc)
|
||||
future_purchase = SimpleNamespace(
|
||||
valid_until=subscription_end,
|
||||
)
|
||||
session = SimpleNamespace(
|
||||
execute=AsyncMock(return_value=_ScalarResult([future_purchase])),
|
||||
flush=AsyncMock(),
|
||||
)
|
||||
|
||||
updated = await tariff_dal.extend_hwid_device_purchases_for_subscription_bonus(
|
||||
session,
|
||||
subscription_id=10,
|
||||
at=datetime(2099, 1, 1, tzinfo=timezone.utc),
|
||||
subscription_end_before=subscription_end,
|
||||
delta=timedelta(days=7),
|
||||
)
|
||||
|
||||
self.assertEqual(updated, 1)
|
||||
self.assertEqual(future_purchase.valid_until, subscription_end + timedelta(days=7))
|
||||
session.flush.assert_awaited_once()
|
||||
self.assertEqual(session.execute.await_count, 1)
|
||||
|
||||
async def test_extends_active_purchase_when_no_tail_purchase_exists(self):
|
||||
active_until = datetime(2099, 1, 16, tzinfo=timezone.utc)
|
||||
active_purchase = SimpleNamespace(valid_until=active_until)
|
||||
session = SimpleNamespace(
|
||||
execute=AsyncMock(
|
||||
side_effect=[
|
||||
_ScalarResult([]),
|
||||
_ScalarResult([active_purchase]),
|
||||
]
|
||||
),
|
||||
flush=AsyncMock(),
|
||||
)
|
||||
|
||||
updated = await tariff_dal.extend_hwid_device_purchases_for_subscription_bonus(
|
||||
session,
|
||||
subscription_id=10,
|
||||
at=datetime(2099, 1, 1, tzinfo=timezone.utc),
|
||||
subscription_end_before=datetime(2099, 2, 1, tzinfo=timezone.utc),
|
||||
delta=timedelta(days=7),
|
||||
)
|
||||
|
||||
self.assertEqual(updated, 1)
|
||||
self.assertEqual(active_purchase.valid_until, active_until + timedelta(days=7))
|
||||
session.flush.assert_awaited_once()
|
||||
self.assertEqual(session.execute.await_count, 2)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user