Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adaptive learning: Add learner profile #9673

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from

Conversation

N0W0RK
Copy link
Contributor

@N0W0RK N0W0RK commented Nov 5, 2024

Warning

This PR includes a migration! Do not deploy on testservers

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Motivation and Context

Based on #9448

Description

Added LearnerProfile and CourseLearnerProfile. Each user has a LearnerProfile and each user in an active (current semester and not a test course) course with learning paths has automatically a course learner profile.
The CourseLearnerProfile is also created when a user enrolls in a course with learning paths or learning paths get enabled. The profiles are deleted if the user unenrolls or is deleted.

This PR does not add any UI!

Steps for Testing

🚨 🚨 Local setup to verify database entries 🚨 🚨
Course with enabled learning paths and some students

  1. Log in to Artemis
  2. Check that the migration works and all existing users have a corresponding entry in the learner profile table
  3. Check that the migration works and all existing users in the course with learning paths have a corresponding entry in the course learner profile table
  4. Create a new user and check that they also get a new learner profile in the data base
  5. Delete the course and check that the corresponding course learner profiles are deleted as well
  6. Delete a user and check that the corresponding learner profile course learner profiles are deleted as well

Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Summary by CodeRabbit

  • New Features

    • Introduced CourseLearnerProfile and LearnerProfile classes for enhanced profile management.
    • Added functionality to create and delete course learner profiles associated with users.
    • Updated user management to include learner profile creation during user registration and deletion.
    • Enhanced course management to automatically create learner profiles when users are added to courses.
    • Added methods for retrieving users with their associated learner profiles.
    • Implemented a utility service for creating learner profiles for multiple users in tests.
    • Enhanced test setup to ensure learner profiles are created and validated for users involved in tests.
  • Bug Fixes

    • Corrected method signatures and ensured proper integration of learner profiles in user and course management.
  • Tests

    • Updated integration tests to validate the presence of learner profiles during user and course operations.

@N0W0RK N0W0RK self-assigned this Nov 5, 2024
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) atlas Pull requests that affect the corresponding module labels Nov 5, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 7, 2024
@github-actions github-actions bot added database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. core Pull requests that affect the corresponding module labels Nov 7, 2024
@JohannesStoehr JohannesStoehr self-assigned this Nov 7, 2024
@github-actions github-actions bot added tests programming Pull requests that affect the corresponding module labels Nov 7, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 11, 2024
@N0W0RK N0W0RK changed the title Add LearnerProfile Adaptive learning: Add LearnerProfile Nov 13, 2024
@N0W0RK N0W0RK marked this pull request as ready for review November 19, 2024 01:05
@N0W0RK N0W0RK requested a review from a team as a code owner November 19, 2024 01:05
coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 5, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1)

1060-1064: Consider using the same course instance.

The method fetches a new course instance with competencies but uses the original course instance for creating the learner profile. This could lead to inconsistencies.

 if (group.equals(course.getStudentGroupName()) && course.getLearningPathsEnabled()) {
     Course courseWithCompetencies = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(course.getId());
-    courseLearnerProfileService.createCourseLearnerProfile(course, user);
-    learningPathApi.generateLearningPathForUser(courseWithCompetencies, user);
+    courseLearnerProfileService.createCourseLearnerProfile(courseWithCompetencies, user);
+    learningPathApi.generateLearningPathForUser(courseWithCompetencies, user);
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 90e061b and c25e76e.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (10 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (7)
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (4)

218-218: LGTM: Clean dependency injection.

The CourseLearnerProfileService is properly injected following constructor injection best practices.

Also applies to: 233-233, 277-277


515-515: LGTM: Proper cleanup of learner profiles.

The deletion of learner profiles is correctly placed in the course deletion sequence, ensuring proper cleanup of all related data.


677-677: LGTM: Proper cleanup on unenrollment.

The deletion of learner profiles on user unenrollment ensures proper cleanup of user data.


216-216: 🛠️ Refactor suggestion

Remove redundant field.

The faqRepository field appears to be redundant and should be removed.

-    private final FaqRepository faqRepository;

Likely invalid or redundant comment.

src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (3)

70-70: LGTM: Clean dependency injection implementation

The addition of CourseLearnerProfileService follows best practices with constructor injection and immutable field declaration.

Also applies to: 181-182, 201-201, 225-225


1184-1184: LGTM: Simplified method signatures

The removal of redundant role parameters simplifies the API while maintaining functionality. The implementation now directly uses group names, following the KISS principle.

Also applies to: 1199-1199, 1215-1215, 1230-1230


342-343: ⚠️ Potential issue

Add transaction boundary for data consistency

The creation of learner profiles and generation of learning paths involves multiple database operations. Without proper transaction boundaries, this could lead to inconsistent state if one operation fails.

Add @Transactional annotation to ensure atomic operations:

+ @Transactional
  public ResponseEntity<Course> updateCourse(@PathVariable Long courseId, @RequestPart("course") Course courseUpdate, @RequestPart(required = false) MultipartFile file)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/atlas/api/LearnerProfileApi.java (1)

1-51: Add API documentation using OpenAPI/Swagger annotations.

The API endpoints lack documentation. Consider adding OpenAPI annotations to document the API endpoints, parameters, and responses.

Add OpenAPI annotations, for example:

+@Operation(summary = "Delete all learner profiles for a course")
+@ApiResponse(responseCode = "200", description = "Learner profiles deleted successfully")
+@ApiResponse(responseCode = "403", description = "Forbidden")
+@ApiResponse(responseCode = "500", description = "Internal server error")
 public void deleteAllForCourse(Course course) {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c25e76e and c4e9df8.

📒 Files selected for processing (6)
  • src/main/java/de/tum/cit/aet/artemis/atlas/api/LearnerProfileApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/UserScheduleService.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/user/UserCreationService.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/core/service/UserScheduleService.java
  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java
🧰 Additional context used
📓 Path-based instructions (4)
src/main/java/de/tum/cit/aet/artemis/core/service/user/UserCreationService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/atlas/api/LearnerProfileApi.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

🔇 Additional comments (6)
src/main/java/de/tum/cit/aet/artemis/core/service/user/UserCreationService.java (3)

26-26: LGTM: Dependency injection is properly implemented

The new dependency follows best practices with constructor injection and immutability.

Also applies to: 78-78


82-82: LGTM: Constructor properly initialized

The constructor correctly initializes all dependencies including the new LearnerProfileApi.

Also applies to: 91-91


149-150: ⚠️ Potential issue

Add transaction boundary and error handling for profile creation

The profile creation should be part of the same transaction as user creation to maintain data consistency. If profile creation fails, we might end up with users without profiles.

Consider wrapping the operations in a transaction and adding proper error handling:

-    newUser = saveUser(newUser);
-    learnerProfileApi.createProfile(newUser);
+    @Transactional
+    protected User createUserWithProfile(User newUser) {
+        try {
+            newUser = saveUser(newUser);
+            learnerProfileApi.createProfile(newUser);
+            return newUser;
+        } catch (Exception e) {
+            log.error("Failed to create user profile for user {}: {}", newUser.getLogin(), e.getMessage());
+            throw new UserProfileCreationException("Failed to create user profile", e);
+        }
+    }

Similar changes should be applied to both createUser methods.

Also applies to: 204-205

src/main/java/de/tum/cit/aet/artemis/core/service/user/UserService.java (1)

476-478: Add error handling for profile deletion.

The profile deletion operation should include error handling to ensure the user deletion process continues even if profile deletion fails.

src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (2)

626-628: Extract duplicated learner profile creation logic.

The logic for creating a learner profile and generating a learning path is duplicated in multiple methods. Consider extracting it into a private helper method.

Also applies to: 660-664, 1060-1064


677-677: Add learner profile cleanup for student group removal.

When removing a user from the student group, consider cleaning up their learner profile if learning paths are enabled.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 6, 2024
florian-glombik
florian-glombik previously approved these changes Dec 6, 2024
Copy link
Contributor

@florian-glombik florian-glombik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approve code

az108
az108 previously approved these changes Dec 6, 2024
Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reapprove code 👍

@N0W0RK N0W0RK requested review from EneaGore and AjayvirS December 9, 2024 16:25
AjayvirS
AjayvirS previously approved these changes Dec 10, 2024
Copy link
Contributor

@AjayvirS AjayvirS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reapprove

EneaGore
EneaGore previously approved these changes Dec 10, 2024
Copy link
Contributor

@EneaGore EneaGore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reapprove

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
atlas Pull requests that affect the corresponding module core Pull requests that affect the corresponding module database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. programming Pull requests that affect the corresponding module ready to merge server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Status: In review
Development

Successfully merging this pull request may close these issues.

8 participants