From ba2a8a2dc993d9c9eddfd59d1913d3b71255cf1e Mon Sep 17 00:00:00 2001
From: Alexandre COIN <alexandre.pc.coin@gmail.com>
Date: Fri, 6 Dec 2024 17:22:09 +0100
Subject: [PATCH] fix(api): remove non unique answers in sql request

---
 .../repositories/answer-repository.js         | 14 +++++---
 .../repositories/answer-repository_test.js    | 35 +++++++++++++++++++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/api/src/shared/infrastructure/repositories/answer-repository.js b/api/src/shared/infrastructure/repositories/answer-repository.js
index 59eb4abe783..be553bfa004 100644
--- a/api/src/shared/infrastructure/repositories/answer-repository.js
+++ b/api/src/shared/infrastructure/repositories/answer-repository.js
@@ -83,10 +83,16 @@ const findByAssessment = async function (assessmentId) {
 
 const findByAssessmentExcludingChallengeIds = async function ({ assessmentId, excludedChallengeIds = [] }) {
   const answerDTOs = await knex
-    .select(COLUMNS)
-    .from('answers')
-    .where({ assessmentId })
-    .whereNotIn('challengeId', excludedChallengeIds);
+    .with('all-first-answers', (qb) => {
+      qb.select('*')
+        .distinctOn('challengeId', 'assessmentId')
+        .from('answers')
+        .where({ assessmentId })
+        .whereNotIn('challengeId', excludedChallengeIds)
+        .orderBy(['challengeId', 'assessmentId', 'createdAt']);
+    })
+    .from('all-first-answers')
+    .orderBy('all-first-answers.createdAt');
 
   return _toDomainArray(answerDTOs);
 };
diff --git a/api/tests/shared/integration/infrastructure/repositories/answer-repository_test.js b/api/tests/shared/integration/infrastructure/repositories/answer-repository_test.js
index 5a6d86b84b1..b2224791d3d 100644
--- a/api/tests/shared/integration/infrastructure/repositories/answer-repository_test.js
+++ b/api/tests/shared/integration/infrastructure/repositories/answer-repository_test.js
@@ -268,6 +268,7 @@ describe('Integration | Repository | answerRepository', function () {
         expect(foundAnswers).to.be.empty;
       });
     });
+
     context('when assessment exists', function () {
       context('when excludingChallengeIds is not provided', function () {
         it('should return all answers', async function () {
@@ -310,6 +311,40 @@ describe('Integration | Repository | answerRepository', function () {
         });
       });
     });
+
+    context('when there are doubled answers', function () {
+      it('should return unique answers', async function () {
+        // given
+        databaseBuilder.factory.buildAssessment({ id: 123 });
+        const firstAnswer = domainBuilder.buildAnswer({ id: 1, assessmentId: 123, challengeId: 'recChallenge123' });
+        const secondAnswer = domainBuilder.buildAnswer({ id: 3, assessmentId: 123, challengeId: 'recChallenge456' });
+        databaseBuilder.factory.buildAnswer({
+          ...firstAnswer,
+          id: 1,
+          result: firstAnswer.result.status,
+        });
+        databaseBuilder.factory.buildAnswer({
+          ...firstAnswer,
+          id: 2,
+          result: firstAnswer.result.status,
+        });
+        databaseBuilder.factory.buildAnswer({
+          ...secondAnswer,
+          id: 3,
+          result: secondAnswer.result.status,
+        });
+        await databaseBuilder.commit();
+
+        // when
+        const foundAnswers = await answerRepository.findByAssessmentExcludingChallengeIds({
+          assessmentId: 123,
+          excludedChallengeIds: [],
+        });
+
+        // then
+        expect(foundAnswers).to.deep.equal([firstAnswer, secondAnswer]);
+      });
+    });
   });
 
   describe('#findChallengeIdsFromAnswerIds', function () {