Skip to content

Commit 2f348d9

Browse files
KB-12111 : added learning pathway retire api (#223) (#224)
Co-authored-by: shankaragoudab <140387294+shankaragoudab@users.noreply.github.com>
1 parent 771555a commit 2f348d9

File tree

5 files changed

+546
-0
lines changed

5 files changed

+546
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.igot.cb.controller;
2+
3+
import com.igot.cb.model.ApiResponse;
4+
import com.igot.cb.service.ContentStateServiceImpl;
5+
import com.igot.cb.service.LearningPathwayRetireService;
6+
import com.igot.cb.util.Constants;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.*;
9+
10+
@RestController
11+
@RequestMapping("/learningpathway")
12+
public class LearningPathwayRetireController {
13+
14+
private final LearningPathwayRetireService learningPathwayRetireService;
15+
16+
public LearningPathwayRetireController(LearningPathwayRetireService learningPathwayRetireService ) {
17+
this.learningPathwayRetireService=learningPathwayRetireService;
18+
}
19+
20+
@GetMapping("/v1/retire/{contentId}")
21+
public ResponseEntity<ApiResponse> retireLearningPathway(@PathVariable("contentId") String contentId,
22+
@RequestHeader(Constants.X_AUTH_TOKEN) String authToken) {
23+
ApiResponse response = learningPathwayRetireService.retireLearningPathway(authToken,contentId);
24+
return new ResponseEntity<>(response, response.getResponseCode());
25+
}
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.igot.cb.service;
2+
3+
import com.igot.cb.model.ApiResponse;
4+
import org.springframework.stereotype.Service;
5+
6+
@Service
7+
public interface LearningPathwayRetireService {
8+
9+
public ApiResponse retireLearningPathway(String userToken, String contentId);
10+
11+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package com.igot.cb.service.impl;
2+
3+
import com.igot.cb.cassandra.CassandraOperation;
4+
import com.igot.cb.model.ApiResponse;
5+
import com.igot.cb.service.ContentInfoServiceImpl;
6+
import com.igot.cb.service.LearningPathwayRetireService;
7+
import com.igot.cb.util.AccessTokenValidator;
8+
import com.igot.cb.util.Constants;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.apache.commons.collections4.MapUtils;
11+
import org.springframework.http.HttpStatus;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.util.CollectionUtils;
14+
import org.apache.commons.lang3.StringUtils;
15+
16+
import java.util.*;
17+
18+
@Service
19+
@Slf4j
20+
public class LearningPathwayRetireServiceImpl implements LearningPathwayRetireService {
21+
22+
private final AccessTokenValidator accessTokenValidator;
23+
private final CassandraOperation cassandraOperation;
24+
private final ContentInfoServiceImpl contentService;
25+
26+
public LearningPathwayRetireServiceImpl(AccessTokenValidator accessTokenValidator,
27+
CassandraOperation cassandraOperation,
28+
ContentInfoServiceImpl contentService) {
29+
this.accessTokenValidator = accessTokenValidator;
30+
this.cassandraOperation = cassandraOperation;
31+
this.contentService = contentService;
32+
}
33+
34+
@Override
35+
public ApiResponse retireLearningPathway(String userToken, String contentId) {
36+
ApiResponse response = new ApiResponse();
37+
38+
try {
39+
log.info("LearningPathwayRetireServiceImpl::retireLearningPathway: starting validation for contentId: {}", contentId);
40+
String userId = accessTokenValidator.fetchUserIdFromAccessToken(userToken, response);
41+
42+
if (StringUtils.isBlank(userId)) {
43+
response.getParams().setStatus(Constants.FAILED);
44+
response.getParams().setErr(Constants.USER_ID_DOESNT_EXIST);
45+
response.setResponseCode(HttpStatus.BAD_REQUEST);
46+
return response;
47+
}
48+
49+
// Validate user has SPV_PUBLISHER role
50+
if (!hasSPVPublisherRole(userId)) {
51+
log.info("User {} does not have SPV_PUBLISHER role", userId);
52+
return commonApiResponse(response, "User does not have SPV_PUBLISHER role", HttpStatus.FORBIDDEN);
53+
}
54+
55+
Map<String, Object> content = contentService.readContent(contentId, Arrays.asList(Constants.BATCHES, Constants.CREATED_BY, Constants.STATUS, Constants.COURSE_CATEGORY));
56+
57+
if (MapUtils.isEmpty(content)) {
58+
return commonApiResponse(response, "Content not found", HttpStatus.NOT_FOUND);
59+
}
60+
61+
String createdBy = (String) content.get(Constants.CREATED_BY);
62+
if(StringUtils.isNotBlank(createdBy) && !userId.equals(createdBy)){
63+
return commonApiResponse(response, "Content is not created by user", HttpStatus.BAD_REQUEST);
64+
}
65+
66+
if(!Constants.LEARNING_PATHWAY.equals(content.get(Constants.COURSE_CATEGORY))){
67+
return commonApiResponse(response, "Content is not learning pathway", HttpStatus.BAD_REQUEST);
68+
}
69+
70+
List<Map<String, Object>> batches = (List<Map<String, Object>>) content.get(Constants.BATCHES);
71+
72+
if (CollectionUtils.isEmpty(batches)) {
73+
log.info("No batches found for content {}, proceeding with retirement", contentId);
74+
return proceedWithRetirement(contentId, response);
75+
}
76+
77+
// Check for active enrollments
78+
if (hasActiveEnrollments(batches)) {
79+
log.info("Active enrollments found for content {}, cannot retire", contentId);
80+
return commonApiResponse(response, "Active enrollments available. Cannot retire the content.",
81+
HttpStatus.BAD_REQUEST);
82+
}
83+
84+
log.info("No active enrollments found for content {}, proceeding with retirement", contentId);
85+
return proceedWithRetirement(contentId, response);
86+
87+
} catch (Exception e) {
88+
log.error("Error while retiring content with validation for contentId: {}", contentId, e);
89+
return commonApiResponse(response, "Failed to retire content: " + e.getMessage(),
90+
HttpStatus.INTERNAL_SERVER_ERROR);
91+
}
92+
}
93+
94+
/**
95+
* Check if there are active enrollments for the content
96+
* @param batches - List of batches associated with content
97+
* @return true if active enrollments exist, false otherwise
98+
*/
99+
private boolean hasActiveEnrollments(List<Map<String, Object>> batches) {
100+
101+
for (Map<String, Object> batch : batches) {
102+
String batchId = (String) batch.get(Constants.BATCH_ID);
103+
104+
if (StringUtils.isBlank(batchId)) {
105+
continue;
106+
}
107+
log.debug("Checking enrollments for batchId: {}", batchId);
108+
Map<String, Object> properties = new HashMap<>();
109+
properties.put(Constants.BATCH_ID, batchId);
110+
List<Map<String, Object>> enrollments = cassandraOperation.getRecordsByProperties(
111+
Constants.KEYSPACE_SUNBIRD_COURSE,
112+
Constants.ENROLLMENT_BATCH_LOOKUP,
113+
properties,
114+
Arrays.asList(Constants.USER_ID, Constants.ACTIVE),
115+
null
116+
);
117+
118+
if (!CollectionUtils.isEmpty(enrollments)) {
119+
return true;
120+
}
121+
}
122+
return false;
123+
}
124+
125+
/**
126+
* Proceed with content retirement
127+
* @param contentId - Content ID to retire
128+
* @param response - ApiResponse object to populate
129+
* @return ApiResponse with retirement status
130+
*/
131+
private ApiResponse proceedWithRetirement(String contentId, ApiResponse response) {
132+
try {
133+
Map<String, Object> contentRetireStatusMap = contentService.retireContent(contentId);
134+
if (MapUtils.isNotEmpty(contentRetireStatusMap)) {
135+
log.info("Content retired successfully: {}", contentId);
136+
return commonApiResponse(response, "Content retired successfully", HttpStatus.OK);
137+
} else {
138+
log.info("Retirement API returned empty response for {}", contentId);
139+
return commonApiResponse(response, "Retirement API returned empty response",
140+
HttpStatus.INTERNAL_SERVER_ERROR);
141+
}
142+
} catch (Exception ex) {
143+
log.error("Failed to retire content {}", contentId, ex);
144+
return commonApiResponse(response, "Failed to retire content: " + ex.getMessage(),
145+
HttpStatus.INTERNAL_SERVER_ERROR);
146+
}
147+
}
148+
149+
/**
150+
* Check if user has SPV_PUBLISHER role
151+
* @param userId - User ID to validate
152+
* @return true if user has SPV_PUBLISHER role, false otherwise
153+
*/
154+
private boolean hasSPVPublisherRole(String userId) {
155+
try {
156+
log.debug("Checking if user {} has SPV_PUBLISHER role", userId);
157+
158+
Map<String, Object> properties = new HashMap<>();
159+
properties.put(Constants.USER_ID, userId);
160+
properties.put(Constants.ROLE, Constants.SPV_PUBLISHER);
161+
162+
List<Map<String, Object>> userRoles = cassandraOperation.getRecordsByProperties(
163+
Constants.KEYSPACE_SUNBIRD,
164+
Constants.TABLE_USER_ROLES,
165+
properties,
166+
null,
167+
null
168+
);
169+
170+
boolean hasRole = !CollectionUtils.isEmpty(userRoles);
171+
log.info("User {} has SPV_PUBLISHER role: {}", userId, hasRole);
172+
return hasRole;
173+
174+
} catch (Exception e) {
175+
log.error("Error checking role for user {}", userId, e);
176+
return false;
177+
}
178+
}
179+
180+
/**
181+
* Build response with custom data
182+
* @param response - ApiResponse object to populate
183+
* @param message - Message to set
184+
* @param statusCode - HTTP status code
185+
* @return ApiResponse with provided details
186+
*/
187+
private ApiResponse commonApiResponse(ApiResponse response, String message, HttpStatus statusCode) {
188+
response.put(Constants.MESSAGE, message);
189+
response.setResponseCode(statusCode);
190+
return response;
191+
}
192+
}

src/main/java/com/igot/cb/util/Constants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,11 @@ public class Constants {
528528
public static final String RETIREMENT_SCHEDULED_SUBJECT = "Retirement Scheduled for #courseName";
529529
public static final String COURSE_NAME_TAG = "#courseName";
530530
public static final String RETIREMENT_SCHEDULE_TEMPLATE = "contentretirementSchedule";
531+
public static final String LEARNING_PATHWAY = "Learning Pathway";
532+
public static final String TABLE_USER_ROLES = "user_roles";
533+
public static final String ROLE = "role";
534+
public static final String BATCHES = "batches";
535+
public static final String SPV_PUBLISHER = "SPV_PUBLISHER";
531536

532537
private Constants() {
533538
}

0 commit comments

Comments
 (0)