Skip to content

Commit a7c22eb

Browse files
4.8.32 dev v1 (#190)
* KB-12451 : Q10 | Retirement | DEV | Schedular for checking the retirement and update the retirement * KB-12451 : Q10 | Retirement | DEV | Schedular for checking the retirement and update the retirement
1 parent 5e7de87 commit a7c22eb

12 files changed

+644
-2
lines changed

src/main/java/com/igot/cb/CbExtCourseServiceApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.springframework.context.annotation.ComponentScan;
1414
import org.springframework.http.client.ClientHttpRequestFactory;
1515
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
16+
import org.springframework.scheduling.annotation.EnableScheduling;
1617
import org.springframework.web.client.RestTemplate;
1718

1819

@@ -23,6 +24,7 @@
2324
@ComponentScan(basePackages = "com.igot.cb")
2425
@EntityScan("com.igot.cb")
2526
@SpringBootApplication
27+
@EnableScheduling
2628
public class CbExtCourseServiceApplication {
2729

2830

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.igot.cb.controller;
2+
3+
import com.igot.cb.model.ApiResponse;
4+
import com.igot.cb.service.ContentRetirementService;
5+
import org.springframework.http.HttpStatus;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.GetMapping;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/admin/content/retirement")
13+
public class ContentRetirementController {
14+
15+
private final ContentRetirementService contentRetirementService;
16+
17+
public ContentRetirementController(ContentRetirementService contentRetirementService) {
18+
this.contentRetirementService = contentRetirementService;
19+
}
20+
21+
@GetMapping("/schedule")
22+
public ResponseEntity<ApiResponse> runManually() {
23+
ApiResponse response = contentRetirementService.processDueRetirements();
24+
return new ResponseEntity<>(response, HttpStatus.OK);
25+
}
26+
27+
@GetMapping("/notify/users")
28+
public ResponseEntity<String> triggerNotifications() {
29+
30+
//notificationService.triggerNotificationJob();
31+
32+
return ResponseEntity
33+
.status(HttpStatus.CREATED)
34+
.body("Notification job accepted");
35+
}
36+
37+
}
38+

src/main/java/com/igot/cb/service/ContentInfoServiceImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,19 @@ public Map<String, Object> readExternalContent(String contentId) {
204204
}
205205
return Collections.emptyMap();
206206
}
207+
208+
public Map<String, Object> retireContent(String contentId) {
209+
StringBuilder url = new StringBuilder();
210+
211+
url.append(propertiesCache.getProperty(Constants.CONTENT_SERVICE_HOST))
212+
.append(propertiesCache.getProperty(Constants.CONTENT_RETIRE_END_POINT)).append("/" + contentId);
213+
214+
Map<String, Object> response = (Map<String, Object>) outboundRequestHandlerService
215+
.fetchResultUsingDelete(url.toString(), new HashMap<>(), new HashMap<>());
216+
if (null != response && Constants.OK.equalsIgnoreCase((String) response.get(Constants.RESPONSE_CODE))) {
217+
Map<String, Object> contentResult = (Map<String, Object>) response.get(Constants.RESULT);
218+
return contentResult;
219+
}
220+
return Collections.emptyMap();
221+
}
207222
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.igot.cb.service;
2+
3+
import com.igot.cb.cassandra.CassandraOperation;
4+
import com.igot.cb.model.ApiResponse;
5+
import com.igot.cb.util.Constants;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.apache.commons.collections4.MapUtils;
8+
import org.springframework.stereotype.Service;
9+
import org.springframework.util.CollectionUtils;
10+
11+
import java.time.Instant;
12+
import java.time.LocalDate;
13+
import java.util.*;
14+
15+
@Slf4j
16+
@Service
17+
public class ContentRetirementService {
18+
19+
private final CassandraOperation cassandraOperation;
20+
private final ContentInfoServiceImpl contentService;
21+
22+
public ContentRetirementService(CassandraOperation cassandraOperation, ContentInfoServiceImpl contentService) {
23+
this.cassandraOperation = cassandraOperation;
24+
this.contentService = contentService;
25+
}
26+
27+
public ApiResponse processDueRetirements() {
28+
ApiResponse response = ApiResponse.createDefaultResponse("retirement.schedule.cron");
29+
30+
LocalDate today = LocalDate.now();
31+
32+
log.info("Running content retirement job for date <= {}", today);
33+
34+
Map<String, Object> propertiesMap = new HashMap<>();
35+
propertiesMap.put(Constants.STATUS, Constants.APPROVED);
36+
37+
List<String> fields = Arrays.asList(
38+
Constants.CONTENT_ID_KEY,
39+
Constants.REQUEST_ID_KEY,
40+
Constants.RETIREMENT_DATE_KEY,
41+
Constants.STATUS
42+
);
43+
44+
List<Map<String, Object>> records =
45+
cassandraOperation.getRecordsByProperties(
46+
Constants.KEYSPACE_SUNBIRD_COURSE,
47+
Constants.CONTENT_RETIREMENT_REQUEST_TABLE,
48+
propertiesMap,
49+
fields,
50+
null
51+
);
52+
53+
if (CollectionUtils.isEmpty(records)) {
54+
log.info("No approved content retirement requests found");
55+
response.getResult().put(Constants.CONTENT, new ArrayList<>());
56+
return response;
57+
}
58+
List<Map<String, Object>> responseList = new ArrayList<>();
59+
for (Map<String, Object> retirementRecord : records) {
60+
61+
LocalDate retirementDate = (LocalDate) retirementRecord.get(Constants.RETIREMENT_DATE);
62+
63+
if (retirementDate != null && !retirementDate.isAfter(today)) {
64+
responseList.add(retireContent(retirementRecord));
65+
}
66+
}
67+
response.getResult().put(Constants.CONTENT, responseList);
68+
return response;
69+
}
70+
71+
private Map<String, Object> retireContent(Map<String, Object> retirementRecord) {
72+
73+
Map<String, Object> result = new HashMap<>();
74+
75+
String contentId = (String) retirementRecord.get(Constants.CONTENT_ID);
76+
String requestId = (String) retirementRecord.get(Constants.REQUEST_ID);
77+
78+
result.put(Constants.CONTENT_ID, contentId);
79+
80+
try {
81+
Map<String, Object> contentRetireStatusMap =
82+
contentService.retireContent(contentId);
83+
84+
if (MapUtils.isNotEmpty(contentRetireStatusMap)) {
85+
86+
Map<String, Object> updateMap = new HashMap<>();
87+
updateMap.put(Constants.STATUS, Constants.RETIRED);
88+
updateMap.put(Constants.UPDATED_AT_KEY, Instant.now());
89+
90+
Map<String, Object> whereClause = new HashMap<>();
91+
whereClause.put(Constants.CONTENT_ID_KEY, contentId);
92+
whereClause.put(Constants.REQUEST_ID_KEY, requestId);
93+
94+
cassandraOperation.updateRecord(
95+
Constants.KEYSPACE_SUNBIRD_COURSE,
96+
Constants.CONTENT_RETIREMENT_REQUEST_TABLE,
97+
updateMap,
98+
whereClause
99+
);
100+
101+
log.info("Content retired successfully: {}", contentId);
102+
103+
result.put(Constants.RETIRED, true);
104+
result.put(Constants.MESSAGE, "Content retired successfully");
105+
106+
} else {
107+
log.warn("Retirement API returned empty response for {}", contentId);
108+
109+
result.put(Constants.RETIRED, false);
110+
result.put(Constants.MESSAGE, "Retirement API returned empty response");
111+
}
112+
113+
} catch (Exception ex) {
114+
log.error("Failed to retire content {}", contentId, ex);
115+
116+
result.put(Constants.RETIRED, false);
117+
result.put(Constants.MESSAGE, ex.getMessage());
118+
}
119+
120+
return result;
121+
}
122+
}
123+

src/main/java/com/igot/cb/service/OutboundRequestHandlerServiceImpl.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,73 @@ public Map<String, Object> fetchResultUsingPost(String uri, Object request, Map<
187187
}
188188
return response;
189189
}
190+
191+
/**
192+
* DELETE request helper which accepts an optional request object and headers map.
193+
*/
194+
public Map<String, Object> fetchResultUsingDelete(
195+
String uri,
196+
Object request,
197+
Map<String, String> headersValues) {
198+
199+
ObjectMapper mapper = new ObjectMapper();
200+
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
201+
202+
Map<String, Object> response = null;
203+
204+
try {
205+
HttpHeaders headers = new HttpHeaders();
206+
if (!CollectionUtils.isEmpty(headersValues)) {
207+
headersValues.forEach(headers::set);
208+
}
209+
headers.setContentType(MediaType.APPLICATION_JSON);
210+
211+
HttpEntity<Object> entity = new HttpEntity<>(request, headers);
212+
213+
if (log.isDebugEnabled()) {
214+
StringBuilder str = new StringBuilder(this.getClass().getCanonicalName())
215+
.append(".fetchResultUsingDelete")
216+
.append(System.lineSeparator());
217+
str.append("URI: ").append(uri).append(System.lineSeparator());
218+
str.append("Request: ").append(mapper.writeValueAsString(request)).append(System.lineSeparator());
219+
log.debug(str.toString());
220+
}
221+
222+
ResponseEntity<Map> responseEntity = restTemplate.exchange(
223+
uri,
224+
HttpMethod.DELETE,
225+
entity,
226+
Map.class
227+
);
228+
229+
response = responseEntity.getBody();
230+
231+
if (log.isDebugEnabled()) {
232+
log.debug("Response: {}", mapper.writeValueAsString(response));
233+
}
234+
235+
} catch (HttpStatusCodeException hce) {
236+
237+
try {
238+
response = new ObjectMapper().readValue(
239+
hce.getResponseBodyAsString(),
240+
new TypeReference<HashMap<String, Object>>() {}
241+
);
242+
} catch (Exception e1) {
243+
log.debug("Failed to parse error response: {}", hce.getResponseBodyAsString(), e1);
244+
}
245+
246+
log.error("Error received: {}", hce.getResponseBodyAsString(), hce);
247+
248+
} catch (Exception e) {
249+
log.error("Failed to call DELETE URL: {}", uri, e);
250+
try {
251+
log.warn("Error Response: {}", mapper.writeValueAsString(response));
252+
} catch (Exception e1) {
253+
log.debug("Failed to parse error response", e1);
254+
}
255+
}
256+
257+
return response;
258+
}
190259
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,17 @@ public class Constants {
493493
public static final String EXTERNAL_CONTENT_READ_END_POINT = "external.content.read.endpoint";
494494
public static final String MINISTRY_OR_STATEID = "ministryOrStateId";
495495
public static final String MINISTRY_OR_STATETYPE = "ministryOrStateType";
496+
public static final String CONTENT_RETIREMENT_REQUEST_TABLE = "content_retirement_requests";
497+
public static final String REQUEST_ID = "requestId";
498+
public static final String RETIREMENT_DATE = "retirementDate";
499+
public static final String APPROVED = "Approved";
500+
public static final String RETIRED = "Retired";
501+
public static final String CONTENT_RETIRE_END_POINT = "content.service.retire.url";
502+
public static final String REQUEST_ID_KEY = "request_id";
503+
public static final String RETIREMENT_DATE_KEY = "retirement_date";
504+
public static final String CONTENT_ID_KEY = "content_id";
505+
public static final String UPDATED_AT_KEY = "updated_at";
506+
496507
private Constants() {
497508
}
498509
}

src/main/resources/application.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,5 @@ cios.search.offset=0
111111
cios.integration.search.host=http://localhost:7002
112112
cios.integration.search=/ciosIntegration/v1/search/content
113113
external.content.read.endpoint=/cios/v1/content/read
114-
cbpores.service.host=http://localhost:7001
114+
cbpores.service.host=http://localhost:7001
115+
content.service.retire.url=/content/v4/retire

src/main/resources/cassandratablecolumn.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ orgid=orgId
2525
assignmenttype=assignmentType
2626
assignmenttypeinfo=assignmentTypeInfo
2727
rootorgid=rootOrgId
28-
additionalattributes=additionalAttributes
28+
additionalattributes=additionalAttributes
29+
content_id=contentId
30+
request_id=requestId
31+
retirement_date=retirementDate
32+
updated_at=updatedAt

0 commit comments

Comments
 (0)