Harden auth, AI tutor, payments, and subscriptions
This commit is contained in:
@@ -5,21 +5,13 @@ class FamilyLink(models.Model):
|
||||
"""
|
||||
اتصال حساب والد به یک فرزند. طبق سند معماری، این اپ فقط به accounts.User
|
||||
ارجاع سبک (parent_user_id / child_user_id) میده، نه FK واقعی.
|
||||
|
||||
⚠️ افزوده نسبت به سند اولیه: سند models فقط parent_user_id/child_user_id
|
||||
را مشخص کرده بود، ولی برای پیادهسازی واقعی جریان «دعوت با کد» (طبق سند
|
||||
Endpointها: POST /api/family/link/invite و /api/family/link/accept) باید
|
||||
خود کد دعوت و شمارهی فرزندی که هنوز ثبتنام نکرده جایی نگه داشته بشه؛
|
||||
دقیقاً همون الگویی که accounts.OTPCode برای نگهداشتن کد یکبارمصرف
|
||||
استفاده میکنه. اگه این دو فیلد قرار بود جای دیگهای (مثلاً یک مدل
|
||||
Invite جدا) نگه داشته بشن، میشه بعداً جابهجا کرد.
|
||||
"""
|
||||
STATUS_CHOICES = [('pending', 'در انتظار'), ('accepted', 'پذیرفتهشده')]
|
||||
|
||||
parent_user_id = models.IntegerField(db_index=True) # ارجاع سبک به accounts.User
|
||||
child_user_id = models.IntegerField(null=True, blank=True, db_index=True) # ارجاع سبک به accounts.User
|
||||
child_phone = models.CharField(max_length=15, blank=True) # <-- افزوده شده
|
||||
invite_code = models.CharField(max_length=10, unique=True) # <-- افزوده شده
|
||||
child_phone = models.CharField(max_length=15, blank=True)
|
||||
invite_code = models.CharField(max_length=10, unique=True)
|
||||
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='pending')
|
||||
invited_at = models.DateTimeField(auto_now_add=True)
|
||||
accepted_at = models.DateTimeField(null=True, blank=True)
|
||||
@@ -27,15 +19,7 @@ class FamilyLink(models.Model):
|
||||
class Meta:
|
||||
ordering = ['-invited_at']
|
||||
constraints = [
|
||||
# 🔒 اصلاح race condition: قبلاً فقط با یک چکِ application-level
|
||||
# (filter().first() قبل از create) جلوی دعوتِ تکراری برای یک
|
||||
# parent/child_phone گرفته میشد که در برابر دو درخواستِ همزمان
|
||||
# کافی نبود (هر دو میتونستن ببینن که pending وجود نداره و هر دو
|
||||
# create کنن). این UniqueConstraint سطح DB تضمین میکنه که برای
|
||||
# هر (parent_user_id, child_phone) فقط یک دعوتِ pending همزمان
|
||||
# میتونه وجود داشته باشه؛ FamilyLinkInviteView حالا
|
||||
# IntegrityError ناشی از این قید رو میگیره و رکورد pending
|
||||
# موجود رو برمیگردونه (idempotent).
|
||||
# حداکثر یک دعوت pending همزمان برای هر (parent_user_id, child_phone).
|
||||
models.UniqueConstraint(
|
||||
fields=['parent_user_id', 'child_phone'],
|
||||
condition=models.Q(status='pending'),
|
||||
|
||||
Reference in New Issue
Block a user