@programisto/edrm-exams 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -871,6 +871,8 @@ class ExamsRouter extends EnduranceRouter {
871
871
  const skip = (page - 1) * limit;
872
872
  const search = req.query.search || '';
873
873
  const state = req.query.state || 'all';
874
+ const sortBy = req.query.sortBy || 'invitationDate';
875
+ const sortOrder = req.query.sortOrder || 'desc';
874
876
  try {
875
877
  const test = await Test.findById(testId);
876
878
  if (!test) {
@@ -881,30 +883,84 @@ class ExamsRouter extends EnduranceRouter {
881
883
  if (state !== 'all') {
882
884
  query.state = state;
883
885
  }
884
- // Recherche sur les candidats
886
+ // Recherche sur les candidats via leurs contacts
885
887
  if (search) {
886
- const candidates = await Candidate.find({
888
+ // D'abord, rechercher dans les contacts
889
+ const contacts = await ContactModel.find({
887
890
  $or: [
888
- { firstName: { $regex: search, $options: 'i' } },
889
- { lastName: { $regex: search, $options: 'i' } },
891
+ { firstname: { $regex: search, $options: 'i' } },
892
+ { lastname: { $regex: search, $options: 'i' } },
890
893
  { email: { $regex: search, $options: 'i' } }
891
894
  ]
892
895
  });
896
+ // Ensuite, récupérer les candidats qui ont ces contacts
897
+ const contactIds = contacts.map(c => c._id);
898
+ const candidates = await Candidate.find({
899
+ contact: { $in: contactIds }
900
+ });
893
901
  const candidateIds = candidates.map(c => c._id);
894
902
  query.candidateId = { $in: candidateIds };
895
903
  }
896
- const [results, total] = await Promise.all([
897
- TestResult.find(query)
898
- .sort({ invitationDate: -1 })
899
- .skip(skip)
900
- .limit(limit)
901
- .exec(),
902
- TestResult.countDocuments(query)
903
- ]);
904
- // Récupérer les données des candidats
905
- const candidateIds = results.map(result => result.candidateId);
906
- const candidates = await Candidate.find({ _id: { $in: candidateIds } });
907
- const candidatesMap = new Map(candidates.map(c => [c._id.toString(), c]));
904
+ // Déterminer l'ordre de tri
905
+ const sortDirection = sortOrder === 'asc' ? 1 : -1;
906
+ // Si on trie par lastName, on récupère tous les résultats puis on trie après
907
+ // Sinon on peut trier directement dans la requête MongoDB
908
+ let results, total;
909
+ if (sortBy === 'lastName') {
910
+ // Récupérer tous les résultats sans pagination pour pouvoir trier par lastName
911
+ const allResults = await TestResult.find(query).exec();
912
+ total = allResults.length;
913
+ // Récupérer les données des candidats pour le tri
914
+ const candidateIds = allResults.map(result => result.candidateId);
915
+ const candidates = await Candidate.find({ _id: { $in: candidateIds } });
916
+ const candidatesMap = new Map(candidates.map(c => [c._id.toString(), c]));
917
+ // Combiner les résultats avec les données des candidats et trier
918
+ const resultsWithCandidates = await Promise.all(allResults.map(async (result) => {
919
+ const candidate = candidatesMap.get(result.candidateId.toString());
920
+ if (!candidate) {
921
+ return {
922
+ ...result.toObject(),
923
+ candidate: null,
924
+ lastName: ''
925
+ };
926
+ }
927
+ const contact = await ContactModel.findById(candidate.contact);
928
+ return {
929
+ ...result.toObject(),
930
+ candidate: contact
931
+ ? {
932
+ firstName: contact.firstname,
933
+ lastName: contact.lastname,
934
+ email: contact.email
935
+ }
936
+ : null,
937
+ lastName: contact ? contact.lastname : ''
938
+ };
939
+ }));
940
+ // Trier par lastName
941
+ resultsWithCandidates.sort((a, b) => {
942
+ const lastNameA = (a.lastName || '').toLowerCase();
943
+ const lastNameB = (b.lastName || '').toLowerCase();
944
+ return sortDirection === 1
945
+ ? lastNameA.localeCompare(lastNameB)
946
+ : lastNameB.localeCompare(lastNameA);
947
+ });
948
+ // Appliquer la pagination
949
+ results = resultsWithCandidates.slice(skip, skip + limit);
950
+ }
951
+ else {
952
+ // Tri direct dans MongoDB pour invitationDate
953
+ const sortObject = {};
954
+ sortObject[sortBy] = sortDirection;
955
+ [results, total] = await Promise.all([
956
+ TestResult.find(query)
957
+ .sort(sortObject)
958
+ .skip(skip)
959
+ .limit(limit)
960
+ .exec(),
961
+ TestResult.countDocuments(query)
962
+ ]);
963
+ }
908
964
  // Calculer le maxScore du test
909
965
  let maxScore = 0;
910
966
  if (test.questions && test.questions.length > 0) {
@@ -912,30 +968,45 @@ class ExamsRouter extends EnduranceRouter {
912
968
  const questions = await TestQuestion.find({ _id: { $in: questionIds } }).lean();
913
969
  maxScore = questions.reduce((sum, q) => sum + (q.maxScore || 0), 0);
914
970
  }
915
- // Combiner les résultats avec les données des candidats
916
- const resultsWithCandidates = await Promise.all(results.map(async (result) => {
917
- const candidate = candidatesMap.get(result.candidateId.toString());
918
- if (!candidate) {
971
+ // Si on a déjà traité les candidats pour le tri par lastName, on utilise directement les résultats
972
+ let resultsWithCandidates;
973
+ if (sortBy === 'lastName') {
974
+ // Les résultats sont déjà traités avec les données des candidats
975
+ resultsWithCandidates = results.map(result => ({
976
+ ...result,
977
+ maxScore
978
+ }));
979
+ }
980
+ else {
981
+ // Récupérer les données des candidats
982
+ const candidateIds = results.map(result => result.candidateId);
983
+ const candidates = await Candidate.find({ _id: { $in: candidateIds } });
984
+ const candidatesMap = new Map(candidates.map(c => [c._id.toString(), c]));
985
+ // Combiner les résultats avec les données des candidats
986
+ resultsWithCandidates = await Promise.all(results.map(async (result) => {
987
+ const candidate = candidatesMap.get(result.candidateId.toString());
988
+ if (!candidate) {
989
+ return {
990
+ ...result.toObject(),
991
+ candidate: null,
992
+ maxScore
993
+ };
994
+ }
995
+ // Récupérer le contact pour obtenir les informations personnelles
996
+ const contact = await ContactModel.findById(candidate.contact);
919
997
  return {
920
998
  ...result.toObject(),
921
- candidate: null,
999
+ candidate: contact
1000
+ ? {
1001
+ firstName: contact.firstname,
1002
+ lastName: contact.lastname,
1003
+ email: contact.email
1004
+ }
1005
+ : null,
922
1006
  maxScore
923
1007
  };
924
- }
925
- // Récupérer le contact pour obtenir les informations personnelles
926
- const contact = await ContactModel.findById(candidate.contact);
927
- return {
928
- ...result.toObject(),
929
- candidate: contact
930
- ? {
931
- firstName: contact.firstname,
932
- lastName: contact.lastname,
933
- email: contact.email
934
- }
935
- : null,
936
- maxScore
937
- };
938
- }));
1008
+ }));
1009
+ }
939
1010
  const totalPages = Math.ceil(total / limit);
940
1011
  return res.json({
941
1012
  data: resultsWithCandidates,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@programisto/edrm-exams",
4
- "version": "0.2.5",
4
+ "version": "0.2.6",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },