Like/dislike + report under every question and lesson, lesson reports and vote columns in admin; practice islands refresh from file; audit fixes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -398,3 +398,50 @@ class SeedRecord(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return f'seed-{self.kind}-{self.key[:8]}'
|
||||
|
||||
|
||||
class LessonReport(models.Model):
|
||||
"""گزارشِ ایراد روی متنِ یک درس (توضیح، مثال، قدمها)؛ همتای `QuestionReport`."""
|
||||
|
||||
REASON_CHOICES = [
|
||||
('wrong_content', 'مطلبِ درس اشتباه است'),
|
||||
('unclear', 'توضیح گنگ است'),
|
||||
('typo', 'غلطِ املایی/نگارشی'),
|
||||
('bad_figure', 'شکل اشکال دارد'),
|
||||
('other', 'موردِ دیگر'),
|
||||
]
|
||||
STATUS_CHOICES = [('open', 'باز'), ('resolved', 'بررسیشده'), ('rejected', 'رد شد')]
|
||||
|
||||
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, related_name='reports')
|
||||
user_id = models.IntegerField(db_index=True) # ارجاع سبک به accounts.User
|
||||
reason = models.CharField(max_length=20, choices=REASON_CHOICES, default='other')
|
||||
note = models.TextField(blank=True)
|
||||
status = models.CharField(max_length=15, choices=STATUS_CHOICES, default='open', db_index=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
resolved_at = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
indexes = [models.Index(fields=['lesson', 'status'])]
|
||||
|
||||
def __str__(self):
|
||||
return f'report on lesson {self.lesson_id} ({self.get_reason_display()})'
|
||||
|
||||
|
||||
class ContentVote(models.Model):
|
||||
"""
|
||||
لایک/دیسلایکِ دانشآموز روی یک سوال یا یک درس. هر کاربر روی هر هدف یک رأی دارد (تغییرپذیر).
|
||||
ارجاعِ سبک (kind + target_id) تا یک جدول هر دو را بپوشاند؛ شمارش در ادمین با Subquery است.
|
||||
"""
|
||||
|
||||
KIND_CHOICES = [('question', 'سوال'), ('lesson', 'درس')]
|
||||
|
||||
kind = models.CharField(max_length=10, choices=KIND_CHOICES)
|
||||
target_id = models.IntegerField()
|
||||
user_id = models.IntegerField()
|
||||
value = models.SmallIntegerField() # ۱ = لایک، −۱ = دیسلایک
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [models.UniqueConstraint(fields=['kind', 'target_id', 'user_id'], name='one_vote_per_user_target')]
|
||||
indexes = [models.Index(fields=['kind', 'target_id'])]
|
||||
|
||||
Reference in New Issue
Block a user