feat: grant signup bonus points

This commit is contained in:
QiuSW
2026-07-08 15:13:23 +08:00
parent 02aa12e8b9
commit ac8bec7b9c
29 changed files with 399 additions and 61 deletions
+34 -6
View File
@@ -2,6 +2,7 @@ import uuid
from decimal import Decimal
from allauth.account.models import EmailAddress
from django.conf import settings
from django.contrib.auth import get_user, get_user_model
from django.contrib.staticfiles import finders
from django.core import mail
@@ -17,6 +18,7 @@ from apps.billing.models import (
PointsLedger,
PricingRule,
RechargeOrder,
SignupBonusGrant,
)
from apps.portal.models import DownloadRelease
from apps.users.models import ApiKey, UserWallet
@@ -144,7 +146,10 @@ class PortalAccountFlowTests(TestCase):
html,
)
def test_signup_creates_user_wallet_with_zero_points_no_ledger_and_can_login(self):
def test_signup_rate_limit_is_configured(self):
self.assertEqual(settings.ACCOUNT_RATE_LIMITS["signup"], "20/m/ip")
def test_signup_grants_100_points_writes_signup_bonus_ledger_and_can_login(self):
suffix = uuid.uuid4().hex[:8]
email = f"signup-{suffix}@example.com"
@@ -164,11 +169,23 @@ class PortalAccountFlowTests(TestCase):
wallet = UserWallet.objects.get(user=user)
self.assertFalse(email_address.verified)
self.assertTrue(email_address.primary)
self.assertEqual(wallet.points_balance, 0)
self.assertFalse(PointsLedger.objects.filter(user=user).exists())
self.assertEqual(wallet.points_balance, 100)
self.assertEqual(SignupBonusGrant.objects.filter(user=user).count(), 1)
ledger = PointsLedger.objects.get(
user=user,
change_type=PointsLedger.ChangeType.SIGNUP_BONUS,
)
self.assertEqual(ledger.points_delta, 100)
self.assertEqual(ledger.balance_after, 100)
self.assertEqual(len(mail.outbox), 0)
self.assertTrue(get_user(self.client).is_authenticated)
dashboard_response = self.client.get("/dashboard")
self.assertEqual(dashboard_response.status_code, 200)
self.assertEqual(dashboard_response.context["balance"].points_balance, 100)
self.assertEqual(dashboard_response.context["balance"].ledger_balance, 100)
self.assertContains(dashboard_response, "100")
def test_user_can_login_without_verified_email(self):
suffix = uuid.uuid4().hex[:8]
user = get_user_model().objects.create_user(
@@ -237,7 +254,8 @@ class PortalAccountFlowTests(TestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.resolver_match.url_name, "portal-home")
self.assertContains(response, "cmhub AI 电商生成台")
self.assertContains(response, "免费注册")
self.assertContains(response, "注册领 100 点")
self.assertContains(response, "注册送 100 点")
self.assertContains(response, "登录")
self.assertContains(response, "客户端暂未发布")
self.assertContains(response, "暂未发布")
@@ -269,7 +287,7 @@ class PortalAccountFlowTests(TestCase):
self.assertEqual(response.status_code, 200)
self.assertContains(response, "进入控制台")
self.assertNotContains(response, "免费注册")
self.assertNotContains(response, "注册领 100 点")
def test_download_release_only_keeps_one_current_per_platform(self):
old_release = self.create_download_release(version="1.0.0", sha256="c" * 64)
@@ -349,7 +367,7 @@ class PortalAccountFlowTests(TestCase):
("/apikeys", "/apikeys", "API Key"),
("/models", "/models", "可用模型"),
("/records/recharge", "/records/recharge", "充值记录"),
("/records/usage", "/records/usage", "消费记录"),
("/records/usage", "/records/usage", "点数记录"),
)
for path, href, label in cases:
@@ -526,6 +544,7 @@ class PortalAccountFlowTests(TestCase):
self.assertEqual(response.context["balance"].ledger_balance, 160)
self.assertEqual(response.context["recharge_total_amount"], Decimal("20.00"))
self.assertEqual(response.context["recharge_points_total"], 200)
self.assertEqual(response.context["credited_points_total"], 200)
self.assertEqual(response.context["consumed_points_total"], 50)
self.assertEqual(response.context["refunded_points_total"], 10)
self.assertEqual(response.context["net_used_points"], 40)
@@ -634,6 +653,13 @@ class PortalAccountFlowTests(TestCase):
alias="other-alias",
points_cost=90,
)
PointsLedger.objects.create(
user=user,
change_type=PointsLedger.ChangeType.SIGNUP_BONUS,
points_delta=100,
balance_after=100,
reason="new_user_registration",
)
PointsLedger.objects.create(
user=user,
change_type=PointsLedger.ChangeType.CONSUME,
@@ -667,6 +693,8 @@ class PortalAccountFlowTests(TestCase):
self.assertEqual(response.context["consumed_points_total"], 40)
self.assertEqual(response.context["refunded_points_total"], 15)
self.assertEqual(response.context["net_used_points"], 25)
self.assertContains(response, "注册赠点")
self.assertContains(response, "100")
self.assertContains(response, "title-standard")
self.assertContains(response, api_key.key_prefix)
self.assertContains(response, "-40")