]> git.openstreetmap.org Git - osqa.git/commitdiff
better handling of the accepting answers workflow
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Fri, 16 Apr 2010 12:47:02 +0000 (12:47 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Fri, 16 Apr 2010 12:47:02 +0000 (12:47 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@38 0cfe37f9-358a-4d5e-be75-b63607b5c754

forum/activity.py
forum/models/answer.py
forum/models/question.py
forum/models/tag.py
forum/reputation.py
forum/views/commands.py
forum/views/decorators.py
forum/views/readers.py

index 1f2d7f081b3afb415108cc64aab5a3e30f743fa7..a58307ba0123faea2eeb119f8cef51321b42751f 100644 (file)
@@ -3,6 +3,7 @@ from django.db.models.signals import post_save
 from forum.models import *\r
 from forum.models.base import marked_deleted\r
 from forum.models.meta import vote_canceled\r
+from forum.models.answer import answer_accepted\r
 from forum.authentication import user_updated\r
 from forum.const import *\r
 \r
@@ -33,7 +34,7 @@ post_save.connect(record_comment_event, sender=Comment)
 \r
 def record_revision_event(instance, created, **kwargs):\r
     if created and instance.revision <> 1 and instance.node.node_type in ('question', 'answer',):\r
-        activity_type = instance.node == 'question' and TYPE_ACTIVITY_UPDATE_QUESTION or TYPE_ACTIVITY_UPDATE_ANSWER\r
+        activity_type = instance.node.node_type == 'question' and TYPE_ACTIVITY_UPDATE_QUESTION or TYPE_ACTIVITY_UPDATE_ANSWER\r
         activity = Activity(user=instance.author, active_at=instance.revised_at, content_object=instance, activity_type=activity_type)\r
         activity.save()\r
 \r
@@ -49,13 +50,11 @@ def record_award_event(instance, created, **kwargs):
 post_save.connect(record_award_event, sender=Award)\r
 \r
 \r
-def record_answer_accepted(instance, created, **kwargs):\r
-    if not created and 'accepted' in instance.get_dirty_fields() and instance.accepted:\r
-        activity = Activity(user=instance.question.author, active_at=datetime.datetime.now(), \\r
-            content_object=instance, activity_type=TYPE_ACTIVITY_MARK_ANSWER)\r
-        activity.save()\r
+def record_answer_accepted(answer, user, **kwargs):\r
+    activity = Activity(user=user, active_at=datetime.datetime.now(), content_object=answer, activity_type=TYPE_ACTIVITY_MARK_ANSWER)\r
+    activity.save()\r
 \r
-post_save.connect(record_answer_accepted, sender=Answer)\r
+answer_accepted.connect(record_answer_accepted)\r
 \r
 \r
 def update_last_seen(instance, **kwargs):\r
index bac79af3894863d5e7dc0cd3cf6b9bc0c7c6258d..01e0aae734e28f15c88df5e4c0c2d070593f9dc3 100644 (file)
@@ -20,18 +20,20 @@ class Answer(QandA):
             self.accepted_at = datetime.datetime.now()
             self.accepted_by = user
             self.save()
-            self.question.answer_accepted = True
+            self.question.accepted_answer = self
             self.question.save()
+            answer_accepted.send(sender=Answer, answer=self, user=user)
             return True
 
         return False
 
-    def unmark_accepted(self):
+    def unmark_accepted(self, user):
         if self.accepted:
             self.accepted = False
             self.save()
-            self.question.answer_accepted = False
+            self.question.accepted_answer = None
             self.question.save()
+            answer_accepted_canceled.send(sender=Answer, answer=self, user=user)
             return True
 
         return False
@@ -70,6 +72,8 @@ class Answer(QandA):
     def __unicode__(self):
         return self.html
         
+answer_accepted = django.dispatch.Signal(providing_args=['answer', 'user'])
+answer_accepted_canceled = django.dispatch.Signal(providing_args=['answer', 'user'])
 
 class AnswerRevision(NodeRevision):
     class Meta:
index 3bf517c6bedbd09903d76660166d4aa054e38710..485576d5522af30a4d3935ba51f3016ff283802d 100644 (file)
@@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _
 question_view = django.dispatch.Signal(providing_args=['instance', 'user'])
 
 class Question(QandA):
-    answer_accepted = models.BooleanField(default=False)
+    accepted_answer = models.OneToOneField('Answer', null=True, related_name="question_accepting")
     closed          = models.BooleanField(default=False)
     closed_by       = models.ForeignKey(User, null=True, blank=True, related_name='closed_questions')
     closed_at       = models.DateTimeField(null=True, blank=True)
@@ -34,6 +34,10 @@ class Question(QandA):
 
         return self.title
 
+    @property
+    def answer_accepted(self):
+        return self.accepted_answer is not None
+
     def delete(self):
         super(Question, self).delete()
         try:
index cda27796e60b3fd34d0179ef1441ec0c3c60ce53..895dac03b925de1f3103fe2d81a5452d461c5973 100644 (file)
@@ -8,7 +8,7 @@ class ActiveTagManager(UndeletedObjectManager):
         return super(UndeletedObjectManager, self).get_query_set().exclude(used_count=0)
 
 
-class Tag(DeletableContent):
+class Tag(BaseModel, DeletableContent):
     name            = models.CharField(max_length=255, unique=True)
     created_by      = models.ForeignKey(User, related_name='created_tags')
     marked_by       = models.ManyToManyField(User, related_name="marked_tags", through="MarkedTag")
index fd5ce633363ffc269b0b676cb31fc7f706dcd525..4a0fe7ea92754b37b4a473250328963ec48577fe 100644 (file)
@@ -1,5 +1,6 @@
 from django.db.models.signals import post_save\r
 from forum.models.meta import vote_canceled\r
+from forum.models.answer import answer_accepted, answer_accepted_canceled\r
 \r
 from forum.models import *\r
 from forum.const import *\r
@@ -28,24 +29,32 @@ def on_flagged_item(instance, created, **kwargs):
 \r
 post_save.connect(on_flagged_item, sender=FlaggedItem)\r
 \r
+def on_answer_accepted(answer, user, **kwargs):\r
+    if user == answer.question.author and not user == answer.author:\r
+        user.reputes.create(\r
+            value=int(settings.REP_GAIN_BY_ACCEPTING), question=answer.question,\r
+            reputation_type=TYPE_REPUTATION_GAIN_BY_ACCEPTING_ANSWER)\r
 \r
-def on_answer_accepted_switch(instance, created, **kwargs):\r
-    if not created and 'accepted' in instance.get_dirty_fields() and (\r
-            not instance.accepted_by == instance.question.author):\r
-        repute_type, repute_value = instance.accepted and (\r
-            TYPE_REPUTATION_GAIN_BY_ANSWER_ACCEPTED, int(settings.REP_GAIN_BY_ACCEPTED)) or (\r
-            TYPE_REPUTATION_LOST_BY_ACCEPTED_ANSWER_CANCELED, -int(settings.REP_LOST_BY_ACCEPTED_CANCELED))\r
+    if not user == answer.author:\r
+        answer.author.reputes.create(\r
+            value=int(settings.REP_GAIN_BY_ACCEPTED), question=answer.question,\r
+            reputation_type=TYPE_REPUTATION_GAIN_BY_ANSWER_ACCEPTED)\r
 \r
-        instance.author.reputes.create(value=repute_value, question=instance.question, reputation_type=repute_type)\r
-        \r
-        if instance.accepted_by == instance.question.author:\r
-            repute_type, repute_value = instance.accepted and (\r
-            TYPE_REPUTATION_GAIN_BY_ACCEPTING_ANSWER, int(settings.REP_GAIN_BY_ACCEPTING)) or (\r
-            TYPE_REPUTATION_LOST_BY_CANCELLING_ACCEPTED_ANSWER, -int(settings.REP_LOST_BY_CANCELING_ACCEPTED))\r
+answer_accepted.connect(on_answer_accepted)\r
 \r
-            instance.question.author.reputes.create(value=repute_value, question=instance.question, reputation_type=repute_type)\r
 \r
-post_save.connect(on_answer_accepted_switch, sender=Answer)\r
+def on_answer_accepted_canceled(answer, user, **kwargs):\r
+    if user == answer.accepted_by:\r
+        user.reputes.create(\r
+            value=-int(settings.REP_LOST_BY_CANCELING_ACCEPTED), question=answer.question,\r
+            reputation_type=TYPE_REPUTATION_LOST_BY_CANCELLING_ACCEPTED_ANSWER)\r
+\r
+    if not user == answer.author:\r
+        answer.author.reputes.create(\r
+            value=-int(settings.REP_LOST_BY_ACCEPTED_CANCELED), question=answer.question,\r
+            reputation_type=TYPE_REPUTATION_LOST_BY_ACCEPTED_ANSWER_CANCELED)\r
+\r
+answer_accepted_canceled.connect(on_answer_accepted)\r
 \r
 \r
 def on_vote(instance, created, **kwargs):\r
index 794ed49786fadbc63aeb8b1385e04b5a7039d79f..89f3fb8aaaf78137897e2b4fe72b7895a039b0cf 100644 (file)
@@ -274,17 +274,13 @@ def accept_answer(request, id):
     commands = {}
 
     if answer.accepted:
-        answer.unmark_accepted()
+        answer.unmark_accepted(user)
         commands['unmark_accepted'] = [answer.id]
     else:
-        try:
-            accepted = question.answers.get(accepted=True)
-            accepted.unmark_accepted()
+        if question.accepted_answer is not None:
+            accepted = question.accepted_answer
+            accepted.unmark_accepted(user)
             commands['unmark_accepted'] = [accepted.id]
-        except:
-            #import sys, traceback
-            #traceback.print_exc(file=sys.stdout)
-            pass
 
         answer.mark_accepted(user)
         commands['mark_accepted'] = [answer.id]
index da51e1a5b9247a8ab4ff3a9e14871fdfdb9b5b74..cf5f90373288f5b5a7e45dca546a1bb88e0b4e67 100644 (file)
@@ -61,8 +61,8 @@ def command(func):
             response = func(request, *args, **kwargs)\r
             response['success'] = True\r
         except Exception, e:\r
-            import sys, traceback\r
-            traceback.print_exc(file=sys.stdout)\r
+            #import sys, traceback\r
+            #traceback.print_exc(file=sys.stdout)\r
 \r
             response = {\r
                 'success': False,\r
index 819384f9e05e31b628bb0816619efc467c872859..15ac86b8995a242c16bf59018ff3a30fe90fb649 100644 (file)
@@ -60,7 +60,7 @@ def index(request):
 
 @decorators.render('questions.html', 'unanswered')
 def unanswered(request):
-    return question_list(request, Question.objects.filter(answer_accepted=False),
+    return question_list(request, Question.objects.filter(accepted_answer=None),
                          _('Open questions without an accepted answer'))
 
 @decorators.render('questions.html', 'questions')
@@ -186,16 +186,16 @@ def get_answer_sort_order(request):
     return (view_id, view_dic[view_id])
 
 def update_question_view_times(request, question):
-    if not 'question_view_times' in request.session:
-        request.session['question_view_times'] = {}
+    if not 'last_seen_in_question' in request.session:
+        request.session['last_seen_in_question'] = {}
 
-    last_seen = request.session['question_view_times'].get(question.id,None)
+    last_seen = request.session['last_seen_in_question'].get(question.id,None)
 
-    if not last_seen or last_seen < question.last_activity_at:
+    if (not last_seen) or last_seen < question.last_activity_at:
         question_view.send(sender=update_question_view_times, instance=question, user=request.user)
-        request.session['question_view_times'][question.id] = datetime.datetime.now()
+        request.session['last_seen_in_question'][question.id] = datetime.datetime.now()
 
-    request.session['question_view_times'][question.id] = datetime.datetime.now()
+    request.session['last_seen_in_question'][question.id] = datetime.datetime.now()
 
 def question(request, id, slug):
     question = get_object_or_404(Question, id=id)