Repository: oppia/oppia

Issue:
Incorrect Open thread count at Feedback Tab
<!--
  - Thanks for taking the time to report a bug in the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->

**Describe the bug**
The count for number of open threads at feedback tab while creating an exploration seems incorrect

**To Reproduce**
Steps to reproduce the behavior:
 1. Go to https://www.oppiatestserver.org/create/37bETBn801Se#/feedback
 2. Observe the count

The code for specific `span` tag on feedback tab icon is
https://github.com/oppia/oppia/blob/741cc401ec375d4bd148dd547a718db7bcdb7499/core/templates/pages/exploration-editor-page/exploration-editor-page.component.html#L84-L88


**Screenshots**
![image](https://user-images.githubusercontent.com/60519303/155834795-ea538c31-0be0-483b-a551-3a071cf4c529.png)
![image](https://user-images.githubusercontent.com/60519303/155834811-9dd2e458-d1a7-45f8-96b7-60bb2ddb19c4.png)

**Expected Behaviour**
The number of open threads clearly seem to be more than 1. The correct count should be displayed instead


Highlighted icons look weird in the exploration editor page
<!--
  - Thanks for taking the time to report a bug in the Oppia project.
  - Before filing a new issue, please do a quick search to check that it hasn't
  - already been filed on the [issue tracker](https://github.com/oppia/oppia/issues)._
  -->

**Describe the bug**
Highlighted icons look weird in the exploration editor page.

**To Reproduce**
Steps to reproduce the behavior:
 1. Go to 'the exploration editor.
 2. Click on icons in the nav bar.
 3. See error.

https://user-images.githubusercontent.com/11008603/159848532-ea1a96a5-d7df-4d1c-903f-5de028d69bd7.mp4






Discussion:
Seems like the correct count is only visible to author of respective exploration -- not sure if this is expected behaviour?
For instance the count here seems correct
![image](https://user-images.githubusercontent.com/60519303/155835834-3bd9ee8a-6090-426b-b678-95c37a663660.png)

@mridul-netizen I'd like to work on it, if possible so assign it to me
@krishita30j @Rijuta-s Can you take a look into the issue and assign accordingly. Thanks.
@sahiljoster32  any updates on this?
@Rijuta-s @sahiljoster32 Any update here?
Hi @vojtechjelinek,
The scenario mentioned in the second screenshot is working fine on both local and test server. But for the first screenshot, things work fine until there is some "suggestions from learner". So i'm still currently tracing the cause of the error. Maybe i'm able to raise PR by Thursday morning. Is that fine?

@sahiljoster32 Any update here?
@vojtechjelinek , things are working fine on develop branch. Also, as we discontinued the 'suggestions from learner' I'm not able to reproduce it on develop branch. 

on testserver, If we check exploration which only contain 'exploration feedback' then this count is correct.

As I'm not able to reproduce this issue, i removed assignment of myself from this.
@mridul-netizen Can you verify whether this works?
> Seems like the correct count is only visible to author of respective exploration -- not sure if this is expected behaviour? For instance the count here seems correct ![image](https://user-images.githubusercontent.com/60519303/155835834-3bd9ee8a-6090-426b-b678-95c37a663660.png)

Only working fine for author of respective exploration for `exploration feedback` part as mentioned here, I'm not sure how to provide `suggestions from learners`.
Per offline discussion with @seanlip, we think the fix would be to not show the "suggestion from learners" section and only show the count of "open" exploration feedback. I'm working on a fix.
Thank you so much @kevintab95 !!
@kevintab95 Will you also be fixing this?
Yup will be fixing this

Resolving patch:
diff --git a/core/controllers/feedback.py b/core/controllers/feedback.py
--- a/core/controllers/feedback.py
+++ b/core/controllers/feedback.py
@@ -86,12 +86,6 @@ def get(self, exploration_id):
                feconf.ENTITY_TYPE_EXPLORATION, exploration_id, False
             )
         ]
-        suggestion_thread_dicts = [
-            thread.to_dict() for thread in feedback_services.get_all_threads(
-                feconf.ENTITY_TYPE_EXPLORATION, exploration_id, True
-            )
-        ]
-
         self.values.update({
             'feedback_thread_dicts': replace_user_id_with_username_in_dict(
                 feedback_thread_dicts, [
@@ -101,10 +95,6 @@ def get(self, exploration_id):
                         'last_nonempty_message_author'
                     )
                 ]
-            ),
-            'suggestion_thread_dicts': replace_user_id_with_username_in_dict(
-                suggestion_thread_dicts,
-                [('original_author_id', 'original_author_username')]
             )
         })
         self.render_json(self.values)
diff --git a/core/domain/opportunity_services.py b/core/domain/opportunity_services.py
--- a/core/domain/opportunity_services.py
+++ b/core/domain/opportunity_services.py
@@ -850,7 +850,11 @@ def _get_skill_opportunities_with_updated_question_counts(skill_ids, delta):
         if skill_opportunity_model is not None:
             skill_opportunity = get_skill_opportunity_from_model(
                 skill_opportunity_model)
-            skill_opportunity.question_count += delta
+            # The question count should never be negative. We default to 0
+            # if some operation tries to reduce question count down to a
+            # negative value.
+            skill_opportunity.question_count = max(
+                skill_opportunity.question_count + delta, 0)
             updated_skill_opportunities.append(skill_opportunity)
     return updated_skill_opportunities
 


Test patch:
diff --git a/core/controllers/feedback_test.py b/core/controllers/feedback_test.py
--- a/core/controllers/feedback_test.py
+++ b/core/controllers/feedback_test.py
@@ -496,49 +496,6 @@ def test_feedback_threads(self):
 
         self.logout()
 
-    def test_feedback_threads_with_suggestions(self):
-        new_content = state_domain.SubtitledHtml(
-            'content', '<p>new content html</p>').to_dict()
-        change_cmd = {
-            'cmd': exp_domain.CMD_EDIT_STATE_PROPERTY,
-            'property_name': exp_domain.STATE_PROPERTY_CONTENT,
-            'state_name': 'State 1',
-            'new_value': new_content
-        }
-        suggestion_services.create_suggestion(
-            feconf.SUGGESTION_TYPE_EDIT_STATE_CONTENT,
-            feconf.ENTITY_TYPE_EXPLORATION, self.EXP_ID, 1,
-            self.user_id, change_cmd, 'sample description')
-
-        response = self.get_json(
-            '%s/%s' % (
-                feconf.FEEDBACK_THREADLIST_URL_PREFIX, self.EXP_ID))
-        self.assertEqual(response['feedback_thread_dicts'], [])
-        expected_thread_dict = {
-            'original_author_username': self.USER_USERNAME,
-            'status': feedback_models.STATUS_CHOICES_OPEN,
-            'subject': 'sample description'
-        }
-        self.assertDictContainsSubset(
-            expected_thread_dict,
-            response['suggestion_thread_dicts'][0])
-
-        thread_id = (
-            response['suggestion_thread_dicts'][0]['thread_id'])
-
-        response = self.get_json(
-            '%s/%s' % (feconf.FEEDBACK_THREAD_URL_PREFIX, thread_id))
-        expected_suggestion_dict = {
-            'suggestion_type': (
-                feconf.SUGGESTION_TYPE_EDIT_STATE_CONTENT),
-            'target_type': feconf.ENTITY_TYPE_EXPLORATION,
-            'target_id': self.EXP_ID,
-            'status': suggestion_models.STATUS_IN_REVIEW,
-            'author_name': self.USER_USERNAME
-        }
-        self.assertDictContainsSubset(
-            expected_suggestion_dict, response['suggestion'])
-
     def test_post_feedback_threads_with_no_text_and_no_updated_status_raise_400(
             self):
         self.login(self.OWNER_EMAIL_1)