diff --git a/src/main/java/org/sunbird/core/config/SunbirdConfig.java b/src/main/java/org/sunbird/core/config/SunbirdConfig.java index c2878102e..d03d3861f 100644 --- a/src/main/java/org/sunbird/core/config/SunbirdConfig.java +++ b/src/main/java/org/sunbird/core/config/SunbirdConfig.java @@ -17,7 +17,8 @@ @Configuration @ConfigurationProperties("spring.data.cassandra.sb") -@EnableCassandraRepositories(basePackages = { "org.sunbird.assessment.repo" }, cassandraTemplateRef = "sunbirdTemplate") +@EnableCassandraRepositories(basePackages = { "org.sunbird.assessment.repo", + "org.sunbird.learnerPath.repository" }, cassandraTemplateRef = "sunbirdTemplate") public class SunbirdConfig extends CassandraConfig { private Logger logger = LoggerFactory.getLogger(SunbirdConfig.class); diff --git a/src/main/java/org/sunbird/learnerPath/repository/LearnerPathRepository.java b/src/main/java/org/sunbird/learnerPath/repository/LearnerPathRepository.java new file mode 100644 index 000000000..cb3d78544 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/LearnerPathRepository.java @@ -0,0 +1,14 @@ +package org.sunbird.learnerPath.repository; + +import java.util.List; + +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.stereotype.Repository; +import org.sunbird.learnerPath.repository.model.LearnerPath; + + +@Repository +public interface LearnerPathRepository extends CassandraRepository { + List findByUserid(String userid); + List findByUseridAndCourseid(String userId, String courseId); +} diff --git a/src/main/java/org/sunbird/learnerPath/repository/UserPassbookRepository.java b/src/main/java/org/sunbird/learnerPath/repository/UserPassbookRepository.java new file mode 100644 index 000000000..5db469345 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/UserPassbookRepository.java @@ -0,0 +1,14 @@ +package org.sunbird.learnerPath.repository; + +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.stereotype.Repository; +import org.sunbird.learnerPath.repository.model.UserPassbook; + +import java.util.List; + +@Repository +public interface UserPassbookRepository extends CassandraRepository { + + List findByUserid(String userid); + +} diff --git a/src/main/java/org/sunbird/learnerPath/repository/controller/LearnerPathController.java b/src/main/java/org/sunbird/learnerPath/repository/controller/LearnerPathController.java new file mode 100644 index 000000000..99d085e83 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/controller/LearnerPathController.java @@ -0,0 +1,57 @@ +package org.sunbird.learnerPath.repository.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.sunbird.learnerPath.repository.model.LearnerPath; +import org.sunbird.learnerPath.repository.service.LearnerPathService; +import org.sunbird.learnerPath.repository.service.UserPassbookService; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@RestController +public class LearnerPathController { + + @Autowired + private LearnerPathService learnerpathservice; + @Autowired + private UserPassbookService userPassbookService; + + @PostMapping(value = "/learnerpath") + public ResponseEntity createOrUpdateLearnerPath(@RequestBody LearnerPath learnerPath) { + return ResponseEntity.ok(learnerpathservice.insertOrUpdate(learnerPath)); + } + + + @GetMapping("/learnerpath") + public ResponseEntity> getLearnerPath(@RequestParam(value = "userId", required = true) String userId, + @RequestParam(value = "courseId", required = false) String courseId) { + + List learnerPaths; + List userPassbooks; + if (courseId != null) { + + userPassbooks= userPassbookService.getUserPassbookByUseridAndCourseId(userId, courseId); + learnerPaths = learnerpathservice.findByUserIdAndCourseId(userId, courseId); + + } else { + userPassbooks = userPassbookService.getUserPassbookByUserid(userId); + learnerPaths = learnerpathservice.findByUserId(userId); + } +// Set learnerPathSet = new HashSet<>(learnerPaths); // Convert to set to eliminate duplicates +// learnerPathSet.removeAll(userPassbooks); // Remove userPassbooks from learnerPaths set + Set mergedSet = new HashSet<>(learnerPaths); + mergedSet.addAll(userPassbooks); + + List mergedList = new ArrayList<>(mergedSet); + + if (mergedList.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + return ResponseEntity.ok(mergedList); + } +} diff --git a/src/main/java/org/sunbird/learnerPath/repository/model/LearnerPath.java b/src/main/java/org/sunbird/learnerPath/repository/model/LearnerPath.java new file mode 100644 index 000000000..e2606426f --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/model/LearnerPath.java @@ -0,0 +1,145 @@ +package org.sunbird.learnerPath.repository.model; + +import java.time.LocalDateTime; + +import org.springframework.data.cassandra.core.mapping.PrimaryKey; +import org.springframework.data.cassandra.core.mapping.Table; + +@Table(value = "asha_learnerpath") +public class LearnerPath { + @PrimaryKey("userid") + private String userid; // Unique user identifier + private String courseid; // Identifier for the course + private String batchid; // Identifier for the batch + private String contentid; // Identifier for the content + private String competencyid; + private int competencylevel; // competency level + private double completionpercentage; // Percentage of completion + private LocalDateTime datetime; // Date and time of enrollment + private LocalDateTime last_access_time; // Last access time of the learner + private LocalDateTime last_completed_time; // Last completion time of the learner + private String content_type; // Progress status (e.g., "In Progress", "Completed") + private String pass_fail_status = "Fail"; // Default value set to "Fail" + private int attemptcount = 0; // Default value set to 0 + + + // Getters and Setters + + public String getUserid() { + return userid; + } + + public void setUserid(String userid) { + this.userid = userid; + } + + public String getCourseid() { + return courseid; + } + + public void setCourseid(String courseid) { + this.courseid = courseid; + } + + public String getBatchid() { + return batchid; + } + + public void setBatchid(String batchid) { + this.batchid = batchid; + } + + public String getContentid() { + return contentid; + } + + public void setContentid(String contentid) { + this.contentid = contentid; + } + + public String getCompetencyid() { + return competencyid; + } + + public void setCompetencyid(String competencyid) { + this.competencyid = competencyid; + } + + public int getcompetencylevel() { + return competencylevel; + } + + public void setcompetencylevel(int competencylevel) { + this.competencylevel = competencylevel; + } + + public double getCompletionpercentage() { + return completionpercentage; + } + + public void setCompletionpercentage(double completionpercentage) { + this.completionpercentage = completionpercentage; + // Update passFailStatus if completionpercentage is 100 + if (completionpercentage == 100) { + this.pass_fail_status = "Pass"; + updateLastCompletedTime(); + } + } + + public LocalDateTime getDatetime() { + return datetime; + } + + // Only set this once when the user enrolls + public void setDatetime(LocalDateTime datetime) { + if (this.datetime == null) { + this.datetime = datetime; + } + } + + public LocalDateTime getLastAccessTime() { + return last_access_time; + } + + public void setLastAccessTime(LocalDateTime lastAccessTime) { + this.last_access_time = lastAccessTime; + } + + public LocalDateTime getLastCompletedTime() { + return last_completed_time; + } + + private void updateLastCompletedTime() { + this.last_completed_time = LocalDateTime.now(); // Update to current time + } + + public String getContentType() { + return content_type; + } + + public void setContentType(String content_type) { + this.content_type = content_type; + } + + + public String getPassFailStatus() { + return pass_fail_status; + } + + public void setPassFailStatus(String passFailStatus) { + this.pass_fail_status = passFailStatus; + } + + public int getAttemptcount() { + return attemptcount; + } + + // Method to increment attempt count + public void incrementAttemptCount() { + this.attemptcount++; + } + + public void setAttemptcount(int attemptcount) { + this.attemptcount = attemptcount; + } +} diff --git a/src/main/java/org/sunbird/learnerPath/repository/model/UserPassbook.java b/src/main/java/org/sunbird/learnerPath/repository/model/UserPassbook.java new file mode 100644 index 000000000..9a8d21061 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/model/UserPassbook.java @@ -0,0 +1,133 @@ +package org.sunbird.learnerPath.repository.model; + +import org.springframework.data.cassandra.core.mapping.Column; +import org.springframework.data.cassandra.core.mapping.PrimaryKey; +import org.springframework.data.cassandra.core.mapping.Table; +import java.time.Instant; +import java.util.Map; + +@Table(value="user_passbook_v2") // table name in Cassandra +public class UserPassbook { + + @PrimaryKey("userid") + @Column("userid") + private String userid; + + @Column("typename") + private String typename; + + @Column("acquiredchannel") + private String acquiredChannel; + + @Column("typeid") + private String typeId; + + @Column("contextid") + private String contextId; + + @Column("effectivedate") + private Instant effectiveDate; + + @Column("acquireddetails") + private Map acquiredDetails; + + @Column("additionalparams") + private Map additionalParams; + + // Top-level fields for final response + private String resourceId; + private String courseId; + private String competencyName; + + // Getters and setters for all fields + + public String getUserid() { + return userid; + } + + public void setUserid(String userid) { + this.userid = userid; + } + + public String getTypename() { + return typename; + } + + public void setTypename(String typename) { + this.typename = typename; + } + + public String getAcquiredChannel() { + return acquiredChannel; + } + + public void setAcquiredChannel(String acquiredChannel) { + this.acquiredChannel = acquiredChannel; + } + + public String getTypeId() { + return typeId; + } + + public void setTypeId(String typeId) { + this.typeId = typeId; + } + + public String getContextId() { + return contextId; + } + + public void setContextId(String contextId) { + this.contextId = contextId; + } + + public Instant getEffectiveDate() { + return effectiveDate; + } + + public void setEffectiveDate(Instant effectiveDate) { + this.effectiveDate = effectiveDate; + } + + public Map getAcquiredDetails() { + return acquiredDetails; + } + + public void setAcquiredDetails(Map acquiredDetails) { + this.acquiredDetails = acquiredDetails; + } + + public Map getAdditionalParams() { + return additionalParams; + } + + public void setAdditionalParams(Map additionalParams) { + this.additionalParams = additionalParams; + } + + // Getters and setters for new top-level fields + public String getResourceId() { + return resourceId; + } + + public void setResourceId(String resourceId) { + this.resourceId = resourceId; + } + + public String getCourseId() { + return courseId; + } + + public void setCourseId(String courseId) { + this.courseId = courseId; + } + + public String getCompetencyName() { + return competencyName; + } + + public void setCompetencyName(String competencyName) { + this.competencyName = competencyName; + } +} + diff --git a/src/main/java/org/sunbird/learnerPath/repository/service/LearnerPathService.java b/src/main/java/org/sunbird/learnerPath/repository/service/LearnerPathService.java new file mode 100644 index 000000000..fcef03ee7 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/service/LearnerPathService.java @@ -0,0 +1,53 @@ +package org.sunbird.learnerPath.repository.service; + + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.sunbird.learnerPath.repository.LearnerPathRepository; +import org.sunbird.learnerPath.repository.model.LearnerPath; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +public class LearnerPathService { + + private final LearnerPathRepository repository; + + @Autowired + public LearnerPathService(LearnerPathRepository repository) { + this.repository = repository; + } + + public LearnerPath insertOrUpdate(LearnerPath learnerPath) { + // If it's a new enrollment, set the enrollment datetime + if (learnerPath.getDatetime() == null) { + learnerPath.setDatetime(LocalDateTime.now()); + } + + // Update last access time every time the user accesses the course + learnerPath.setLastAccessTime(LocalDateTime.now()); + + // Increment attempt count for each update + learnerPath.incrementAttemptCount(); + + // Save the learnerPath object to the repository + return repository.save(learnerPath); + } + + // public Optional findById(String userId) { +// return repository.findById(userId); +// } + public List findByUserId(String userId) { + return repository.findByUserid(userId); + } + + public List findByUserIdAndCourseId(String userId, String courseId) { + return repository.findByUseridAndCourseid(userId, courseId); + } + + public void deleteById(String userId) { + repository.deleteById(userId); + } +} + diff --git a/src/main/java/org/sunbird/learnerPath/repository/service/UserPassbookService.java b/src/main/java/org/sunbird/learnerPath/repository/service/UserPassbookService.java new file mode 100644 index 000000000..4eaa06385 --- /dev/null +++ b/src/main/java/org/sunbird/learnerPath/repository/service/UserPassbookService.java @@ -0,0 +1,112 @@ +package org.sunbird.learnerPath.repository.service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.sunbird.learnerPath.repository.UserPassbookRepository; +import org.sunbird.learnerPath.repository.model.LearnerPath; +import org.sunbird.learnerPath.repository.model.UserPassbook; + +@Service +public class UserPassbookService { + + @Autowired + private UserPassbookRepository userPassbookRepository; + @Autowired + public UserPassbookService(UserPassbookRepository repository) { + this.userPassbookRepository = repository; + } + + + public List getUserPassbookByUserid(String userid) { + // Fetch all UserPassbook records for the given userId + List userPassbooks = userPassbookRepository.findByUserid(userid); + + // Process each UserPassbook in the list + return userPassbooks.stream().map(passbook -> { + // Get the acquiredDetails map + Map acquiredDetails = passbook.getAcquiredDetails(); + LearnerPath learnerPath = new LearnerPath(); + learnerPath.setUserid(passbook.getUserid()); + learnerPath.setContentType(passbook.getAcquiredChannel()); + learnerPath.setCompetencyid(passbook.getTypeId()); + int contextId = Integer.parseInt(passbook.getContextId()); + learnerPath.setcompetencylevel(contextId); + learnerPath.setCompletionpercentage(100); + learnerPath.setPassFailStatus("Pass"); + + if (acquiredDetails != null) { + // Extract the ResourceId, courseId, and competencyName + String resourceId = acquiredDetails.getOrDefault("ResourseId",""); + String courseId = acquiredDetails.get("courseId"); + String competencyName = acquiredDetails.get("competencyName"); + + // Set these values as top-level fields in the UserPassbook object +// passbook.setResourceId(resourceId); +// passbook.setCourseId(courseId); +// passbook.setCompetencyName(competencyName); + learnerPath.setCourseid(courseId); + learnerPath.setContentid(resourceId); + + // Optionally, remove acquiredDetails if you don't want to include it in the final response + passbook.setAcquiredDetails(null); // Nullify or reset the map + } + + return learnerPath; + }).collect(Collectors.toList()); // Collect the modified list of UserPassbook objects + } + + public List getUserPassbookByUseridAndCourseId(String userid, String courseId) { + // Fetch all UserPassbook records for the given userId + List userPassbooks = userPassbookRepository.findByUserid(userid); + + // Process each UserPassbook in the list + return userPassbooks.stream() + // Apply filter for the desired courseId + .filter(passbook -> { + // Check if acquiredDetails is not null and contains the courseId key + Map acquiredDetails = passbook.getAcquiredDetails(); + return acquiredDetails != null && acquiredDetails.containsKey("courseId") && + acquiredDetails.get("courseId").equals(courseId); // courseId is the value you are filtering by + }) + .map(passbook -> { + // Get the acquiredDetails map + Map acquiredDetails = passbook.getAcquiredDetails(); + LearnerPath learnerPath = new LearnerPath(); + learnerPath.setUserid(passbook.getUserid()); + learnerPath.setContentType(passbook.getAcquiredChannel()); + learnerPath.setCompetencyid(passbook.getTypeId()); + int contextId = Integer.parseInt(passbook.getContextId()); + learnerPath.setcompetencylevel(contextId); + learnerPath.setCompletionpercentage(100); + learnerPath.setPassFailStatus("Pass"); + // learnerPath.setDatetime(passbook.getEffectiveDate()); + + if (acquiredDetails != null) { + // Extract the ResourceId, courseId, and competencyName + String resourceId = acquiredDetails.getOrDefault("ResourseId", ""); + String courseIdFromDetails = acquiredDetails.get("courseId"); + String competencyName = acquiredDetails.get("competencyName"); + + learnerPath.setCourseid(courseIdFromDetails); + learnerPath.setContentid(resourceId); + + // Set these values as top-level fields in the UserPassbook object +// passbook.setResourceId(resourceId); +// passbook.setCourseId(courseIdFromDetails); // you may need to use the actual `courseIdFromDetails` +// passbook.setCompetencyName(competencyName); + + // Optionally, remove acquiredDetails if you don't want to include it in the final response + passbook.setAcquiredDetails(null); // Nullify or reset the map + } + + return learnerPath; + }) + .collect(Collectors.toList()); + + } +} +