diff --git a/pom.xml b/pom.xml index ff25492db..ed05a2309 100644 --- a/pom.xml +++ b/pom.xml @@ -219,6 +219,11 @@ jjwt 0.9.1 + + org.apache.commons + commons-csv + 1.9.0 + diff --git a/src/main/java/org/sunbird/common/util/Constants.java b/src/main/java/org/sunbird/common/util/Constants.java index 51e2f4a8b..35cb537a3 100644 --- a/src/main/java/org/sunbird/common/util/Constants.java +++ b/src/main/java/org/sunbird/common/util/Constants.java @@ -1088,6 +1088,9 @@ public class Constants { public static final String SECTION_LEVEL_DEFINITION = "sectionLevelDefinition"; public static final String ASSESSMENT_HIERARCHY_SAVE_NOT_AVBL = "Assessment hierarchy save point not available, failed to process request"; + public static final String SEQUENCE_NO = "seqno"; + public static final String API_EXPLORE_COURSE_UPDATE = "api.explore.course.update"; + public static final String API_EXPLORE_COURSE_DELETE = "api.explore.course.delete"; private Constants() { throw new IllegalStateException("Utility class"); diff --git a/src/main/java/org/sunbird/course/controller/ExploreCourseController.java b/src/main/java/org/sunbird/course/controller/ExploreCourseController.java index a17291461..4fa6ec8a6 100644 --- a/src/main/java/org/sunbird/course/controller/ExploreCourseController.java +++ b/src/main/java/org/sunbird/course/controller/ExploreCourseController.java @@ -1,8 +1,13 @@ package org.sunbird.course.controller; +import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.sunbird.common.model.SBApiResponse; import org.sunbird.course.service.ExploreCourseService; @@ -37,4 +42,16 @@ public ResponseEntity getPublicCourseListV2() { SBApiResponse response = courseService.getExploreCourseListV2(); return new ResponseEntity<>(response, response.getResponseCode()); } + + @PostMapping("/course/v1/explore/upsert") + public ResponseEntity upsertCourse(@RequestBody Map request) { + SBApiResponse response = courseService.upsertExploreCourse(request); + return new ResponseEntity<>(response, response.getResponseCode()); + } + + @DeleteMapping("/course/v1/explore/delete/{courseId}") + public ResponseEntity deleteExploreCourse(@PathVariable String courseId) { + SBApiResponse response = courseService.deleteExploreCourse(courseId); + return new ResponseEntity<>(response, response.getResponseCode()); + } } diff --git a/src/main/java/org/sunbird/course/service/ExploreCourseService.java b/src/main/java/org/sunbird/course/service/ExploreCourseService.java index f74331865..3f0861931 100644 --- a/src/main/java/org/sunbird/course/service/ExploreCourseService.java +++ b/src/main/java/org/sunbird/course/service/ExploreCourseService.java @@ -1,5 +1,6 @@ package org.sunbird.course.service; +import java.util.Map; import org.sunbird.common.model.SBApiResponse; /** @@ -32,4 +33,8 @@ public interface ExploreCourseService { * @return - Course details in Sunbird API Response format. */ public SBApiResponse getExploreCourseListV2(); + + public SBApiResponse upsertExploreCourse(Map request); + + public SBApiResponse deleteExploreCourse(String id); } diff --git a/src/main/java/org/sunbird/course/service/ExploreCourseServiceImpl.java b/src/main/java/org/sunbird/course/service/ExploreCourseServiceImpl.java index 0e4a60608..e64574c75 100644 --- a/src/main/java/org/sunbird/course/service/ExploreCourseServiceImpl.java +++ b/src/main/java/org/sunbird/course/service/ExploreCourseServiceImpl.java @@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; import org.sunbird.cache.RedisCacheMgr; import org.sunbird.cassandra.utils.CassandraOperation; import org.sunbird.common.model.SBApiResponse; @@ -20,6 +21,7 @@ import org.sunbird.common.util.Constants; import org.sunbird.common.util.ProjectUtil; import org.sunbird.core.exception.ApplicationLogicError; +import org.sunbird.staff.model.StaffInfo; /** * Implementation of ExploreCourseService @@ -183,4 +185,134 @@ public SBApiResponse getExploreCourseListV2() { } return response; } + + @Override + public SBApiResponse upsertExploreCourse(Map requestObj) { + SBApiResponse response = + ProjectUtil.createDefaultResponse(Constants.API_EXPLORE_COURSE_UPDATE); + logger.info("ExploreCourseService::upsertExploreCourse:inside method"); + Map masterData = (Map) requestObj.get(Constants.REQUEST); + String errMsg = validateUpsertRequest(masterData); + if (StringUtils.isNotBlank(errMsg)) { + response.getParams().setErrmsg(errMsg); + response.setResponseCode(HttpStatus.BAD_REQUEST); + return response; + } + try { + List dataList = (List) masterData.get(Constants.DATA); + Iterator iterator = dataList.iterator(); + + while (iterator.hasNext()) { + Map itemMap = (Map) iterator.next(); + Map request = new HashMap<>(); + request.put(Constants.IDENTIFIER, itemMap.get(Constants.IDENTIFIER)); + + List> listOfMasterData = cassandraOperation.getRecordsByProperties( + Constants.KEYSPACE_SUNBIRD, Constants.TABLE_EXPLORE_COURSE_LIST_V2, request, + new ArrayList<>()); + + if (CollectionUtils.isNotEmpty(listOfMasterData)) { + Map updateRequest = new HashMap<>(); + updateRequest.put(Constants.SEQUENCE_NO, itemMap.get(Constants.SEQUENCE_NO)); + Map updateResponse = cassandraOperation.updateRecord( + Constants.KEYSPACE_SUNBIRD, Constants.TABLE_EXPLORE_COURSE_LIST_V2, updateRequest, + request); + + if (updateResponse != null && !Constants.SUCCESS.equalsIgnoreCase( + (String) updateResponse.get(Constants.RESPONSE))) { + errMsg = String.format("Failed to update details"); + response.getParams().setErrmsg(errMsg); + response.setResponseCode(HttpStatus.BAD_REQUEST); + break; + } else { + response.getResult().put(Constants.STATUS, Constants.CREATED); + } + } else { + request.put(Constants.SEQUENCE_NO, itemMap.get(Constants.SEQUENCE_NO)); + response = cassandraOperation.insertRecord(Constants.KEYSPACE_SUNBIRD, + Constants.TABLE_EXPLORE_COURSE_LIST_V2, request); + response.setResponseCode(HttpStatus.OK); + if (!Constants.SUCCESS.equalsIgnoreCase((String) response.get(Constants.RESPONSE))) { + errMsg = String.format("Failed to create position"); + response.setResponseCode(HttpStatus.BAD_REQUEST); + response.getParams().setErrmsg(errMsg); + break; + } else { + response.getResult().put(Constants.STATUS, Constants.CREATED); + } + } + } + } catch (Exception e) { + errMsg = String.format("Exception occurred while performing upsert operation"); + logger.error(errMsg, e); + } + if (StringUtils.isNotBlank(errMsg)) { + response.getParams().setStatus(Constants.FAILED); + response.getParams().setErrmsg(errMsg); + response.setResponseCode(HttpStatus.BAD_REQUEST); + } + return response; + } + + @Override + public SBApiResponse deleteExploreCourse(String id) { + SBApiResponse response = ProjectUtil.createDefaultResponse(Constants.API_EXPLORE_COURSE_DELETE); + Map keyMap = new HashMap<>(); + keyMap.put(Constants.IDENTIFIER, id); + try { + List> existingDetails = cassandraOperation.getRecordsByProperties( + Constants.KEYSPACE_SUNBIRD, + Constants.TABLE_EXPLORE_COURSE_LIST_V2, keyMap, null); + if (!existingDetails.isEmpty()) { + cassandraOperation.deleteRecord(Constants.KEYSPACE_SUNBIRD, + Constants.TABLE_EXPLORE_COURSE_LIST_V2, keyMap); + response.getParams().setStatus(Constants.SUCCESSFUL); + response.getResult().put(Constants.STATUS, Constants.DELETED); + response.getResult().put(Constants.MESSAGE, "Deleted Explore Course for Id: " + id); + response.setResponseCode(HttpStatus.OK); + } else { + String errMsg = "Failed to find Course for OrgId: " + ", Id: " + id; + logger.error(errMsg); + response.getParams().setErrmsg(errMsg); + response.setResponseCode(HttpStatus.BAD_REQUEST); + } + } catch (Exception ex) { + String errMsg = + "Exception occurred while deleting the ExploredCourse. Exception: " + ex.getMessage(); + logger.error(errMsg, ex); + response.getParams().setErrmsg(errMsg); + response.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR); + } + return response; + } + + private String validateUpsertRequest(Map masterData) { + logger.info("ExploreCourseService::validateUpsertRequest:inside method"); + StringBuilder strBuilder = new StringBuilder(); + if (ObjectUtils.isEmpty(masterData)) { + strBuilder.append("Model object is empty."); + return strBuilder.toString(); + } + // Check if the requestData contains the key "data" + if (!masterData.containsKey(Constants.DATA) || !(masterData.get( + Constants.DATA) instanceof List)) { + strBuilder.append("Data is missing or invalid."); + return strBuilder.toString(); + } + List dataList = (List) masterData.get(Constants.DATA); + for (Object item : dataList) { + if (!(item instanceof Map)) { + strBuilder.append("Item in data list is not a valid map."); + return strBuilder.toString(); + } + Map itemMap = (Map) item; + if (!itemMap.containsKey(Constants.IDENTIFIER)) { + strBuilder.append("Item is missing 'identifier'. "); + } + if (!itemMap.containsKey(Constants.SEQUENCE_NO)) { + strBuilder.append("Item is missing seqno. "); + } + } + return strBuilder.toString(); + } } diff --git a/src/main/java/org/sunbird/profile/controller/ProfileController.java b/src/main/java/org/sunbird/profile/controller/ProfileController.java index 6e4666c5d..f17b950da 100644 --- a/src/main/java/org/sunbird/profile/controller/ProfileController.java +++ b/src/main/java/org/sunbird/profile/controller/ProfileController.java @@ -1,12 +1,15 @@ package org.sunbird.profile.controller; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; @@ -20,6 +23,9 @@ import org.sunbird.common.model.SBApiResponse; import org.sunbird.common.util.Constants; import org.sunbird.profile.service.ProfileService; +import org.sunbird.profile.service.UserBulkUploadService; + +import javax.swing.plaf.PanelUI; @RestController public class ProfileController { @@ -156,4 +162,16 @@ public ResponseEntity profileUpdateV2( SBApiResponse response = profileService.profileUpdateV2(request, userToken, authToken, rootOrgId); return new ResponseEntity<>(response, response.getResponseCode()); } + + @PostMapping("/user/v2/bulkupload") + public ResponseEntity bulkUploadV2(@RequestParam(value = "file", required = true) MultipartFile multipartFile, + @RequestHeader(Constants.X_AUTH_USER_ORG_ID) String rootOrgId, + @RequestHeader(Constants.X_AUTH_USER_CHANNEL) String channel, + @RequestHeader(Constants.X_AUTH_USER_ID) String userId, + @RequestHeader(Constants.X_AUTH_TOKEN) String userAuthToken) throws UnsupportedEncodingException { + log.info(String.format("bulkupload channel name:%s,OrgId:%s", + URLDecoder.decode(channel, "UTF-8"), rootOrgId)); + SBApiResponse uploadResponse = profileService.bulkUpload(multipartFile, rootOrgId, URLDecoder.decode(channel, "UTF-8"), userId, userAuthToken); + return new ResponseEntity<>(uploadResponse, uploadResponse.getResponseCode()); + } } diff --git a/src/main/java/org/sunbird/profile/service/ProfileService.java b/src/main/java/org/sunbird/profile/service/ProfileService.java index cb67ceaa5..ede321210 100644 --- a/src/main/java/org/sunbird/profile/service/ProfileService.java +++ b/src/main/java/org/sunbird/profile/service/ProfileService.java @@ -54,4 +54,6 @@ public interface ProfileService { * @throws Exception if any error occurs during the profile update process. */ SBApiResponse profileUpdateV2(Map request, String userToken, String authToken, String rootOrgId) ; + + SBApiResponse bulkUploadV2(MultipartFile mFile, String orgId, String orgName, String userId, String userAuthToken); } diff --git a/src/main/java/org/sunbird/profile/service/ProfileServiceImpl.java b/src/main/java/org/sunbird/profile/service/ProfileServiceImpl.java index 5ece3838c..d3dc31867 100644 --- a/src/main/java/org/sunbird/profile/service/ProfileServiceImpl.java +++ b/src/main/java/org/sunbird/profile/service/ProfileServiceImpl.java @@ -2166,6 +2166,53 @@ private String validateExistingPhoneEmail(Map profileDetailsMap) return ""; } + @Override + public SBApiResponse bulkUploadV2(MultipartFile mFile, String orgId, String channel, String userId, String userAuthToken) { + SBApiResponse response = ProjectUtil.createDefaultResponse(Constants.API_USER_BULK_UPLOAD); + try { + if (isFileExistForProcessingForMDO(orgId)) { + setErrorDataForMdo(response, "Failed to upload for another request as previous request is in processing state, please try after some time."); + return response; + } + SBApiResponse uploadResponse = storageService.uploadFile(mFile, serverConfig.getBulkUploadContainerName()); + if (!HttpStatus.OK.equals(uploadResponse.getResponseCode())) { + setErrorData(response, String.format("Failed to upload file. Error: %s", + (String) uploadResponse.getParams().getErrmsg())); + return response; + } + + Map uploadedFile = new HashMap<>(); + uploadedFile.put(Constants.ROOT_ORG_ID, orgId); + uploadedFile.put(Constants.IDENTIFIER, UUID.randomUUID().toString()); + uploadedFile.put(Constants.FILE_NAME, uploadResponse.getResult().get(Constants.NAME)); + uploadedFile.put(Constants.FILE_PATH, uploadResponse.getResult().get(Constants.URL)); + uploadedFile.put(Constants.DATE_CREATED_ON, new Timestamp(System.currentTimeMillis())); + uploadedFile.put(Constants.STATUS, Constants.INITIATED_CAPITAL); + uploadedFile.put(Constants.COMMENT, StringUtils.EMPTY); + uploadedFile.put(Constants.CREATED_BY, userId); + + SBApiResponse insertResponse = cassandraOperation.insertRecord(Constants.DATABASE, + Constants.TABLE_USER_BULK_UPLOAD, uploadedFile); + + if (!Constants.SUCCESS.equalsIgnoreCase((String) insertResponse.get(Constants.RESPONSE))) { + setErrorData(response, "Failed to update database with user bulk upload file details."); + return response; + } + + response.getParams().setStatus(Constants.SUCCESSFUL); + response.setResponseCode(HttpStatus.OK); + response.getResult().putAll(uploadedFile); + uploadedFile.put(Constants.ORG_NAME, channel); + uploadedFile.put(Constants.X_AUTH_TOKEN, userAuthToken); + kafkaProducer.pushWithKey(serverConfig.getUserBulkUploadTopic(), uploadedFile, orgId); + sendBulkUploadNotification(orgId, channel, (String) uploadResponse.getResult().get(Constants.URL)); + } catch (Exception e) { + setErrorData(response, + String.format("Failed to process user bulk upload request. Error: ", e.getMessage())); + } + return response; + } + } diff --git a/src/main/java/org/sunbird/profile/service/UserBulkUploadService.java b/src/main/java/org/sunbird/profile/service/UserBulkUploadService.java index 641b99ed8..f17335cda 100644 --- a/src/main/java/org/sunbird/profile/service/UserBulkUploadService.java +++ b/src/main/java/org/sunbird/profile/service/UserBulkUploadService.java @@ -2,6 +2,10 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; import org.apache.commons.lang.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; @@ -27,10 +31,11 @@ import org.sunbird.user.registration.model.UserRegistration; import org.sunbird.user.service.UserUtilityService; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.*; @@ -65,7 +70,8 @@ public void initiateUserBulkUploadProcess(String inputData) { updateUserBulkUploadStatus(inputDataMap.get(Constants.ROOT_ORG_ID), inputDataMap.get(Constants.IDENTIFIER), Constants.STATUS_IN_PROGRESS_UPPERCASE, 0, 0, 0); storageService.downloadFile(inputDataMap.get(Constants.FILE_NAME)); - processBulkUpload(inputDataMap); + //processBulkUpload(inputDataMap); + processCSVBulkUploadV2(inputDataMap); } else { logger.error(String.format("Error in the Kafka Message Received : %s", errList)); } @@ -276,8 +282,8 @@ private void processBulkUpload(HashMap inputDataMap) throws IOEx if (!ProjectUtil.validateEmployeeId(userRegistration.getEmployeeId())) { invalidErrList.add("Invalid Employee ID : Employee ID can contain alphabetic, alphanumeric or numeric character(s) and have a max length of 30"); } - if(userRegistration.getEmployeeId().contains(Constants.SPACE)){ - invalidErrList.add("Employee Id cannot contain spaces"); + if (userRegistration.getEmployeeId().contains(Constants.SPACE)) { + invalidErrList.add("Invalid Employee ID : Employee Id cannot contain spaces"); } } } @@ -326,7 +332,7 @@ private void processBulkUpload(HashMap inputDataMap) throws IOEx List tagList = new ArrayList(); if (!StringUtils.isEmpty(tagStr)) { String[] tagStrList = tagStr.split(",", -1); - for(String tag : tagStrList) { + for (String tag : tagStrList) { tagList.add(tag.trim()); } } @@ -417,6 +423,275 @@ private void processBulkUpload(HashMap inputDataMap) throws IOEx file.delete(); } } + public void processCSVBulkUploadV2(HashMap inputDataMap) throws IOException { + File file = null; + CSVParser csvParser = null; + CSVPrinter csvPrinter = null; + BufferedWriter bufferedWriter = null; + FileWriter fileWriter = null; + int totalRecordsCount = 0; + int noOfSuccessfulRecords = 0; + int failedRecordsCount = 0; + String status = ""; + + try { + file = new File(Constants.LOCAL_BASE_PATH + inputDataMap.get(Constants.FILE_NAME)); + if (file.exists() && file.length() > 0) { + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)); + csvParser = new CSVParser(reader, CSVFormat.INFORMIX_UNLOAD.withFirstRecordAsHeader()); + + List csvRecords = csvParser.getRecords(); + List> updatedRecords = new ArrayList<>(); + List headers = new ArrayList<>(csvParser.getHeaderNames()); + headers.replaceAll(header -> header.replaceAll("^\"|\"$", "")); + + if (!headers.contains("Status")) { + headers.add("Status"); + } + if (!headers.contains("Error Details")) { + headers.add("Error Details"); + } + + for (CSVRecord record : csvRecords) { + totalRecordsCount++; + Map updatedRecord = new LinkedHashMap<>(record.toMap()); + List errList = new ArrayList<>(); + List invalidErrList = new ArrayList<>(); + + UserRegistration userRegistration = new UserRegistration(); + + if (isFieldEmpty(record, 0)) { + errList.add("Full Name"); + } else { + String fullName = record.get(0).trim(); + if (!fullName.matches("[a-zA-Z ]+")) { + invalidErrList.add("Invalid value for Full Name column type. Expecting string format"); + } else { + userRegistration.setFirstName(fullName); + if (!ProjectUtil.validateFullName(userRegistration.getFirstName())) { + invalidErrList.add("Invalid Full Name"); + } + } + } + + if (isFieldEmpty(record, 1)) { + errList.add("Email"); + } else { + String email = record.get(1).trim(); + userRegistration.setEmail(email); + } + + + if (isFieldEmpty(record, 2)) { + errList.add("Mobile Number"); + } else { + String phone = record.get(2).trim(); + if (phone.matches("^\\d+$")) { + userRegistration.setPhone(phone); + } else { + invalidErrList.add("Invalid value for Mobile Number column type. Expecting number format"); + } + } + if (!StringUtils.isBlank(userRegistration.getPhone()) && !ProjectUtil.validateContactPattern(userRegistration.getPhone())) { + invalidErrList.add("The Mobile Number provided is Invalid"); + } + + if (isFieldEmpty(record, 3)) { + errList.add("Group"); + } else { + String group = record.get(3).trim(); + userRegistration.setGroup(group); + if (!userUtilityService.validateGroup(userRegistration.getGroup())) { + invalidErrList.add("Invalid Group : Group can be only among one of these " + serverProperties.getBulkUploadGroupValue()); + } + } + + if (isFieldEmpty(record, 4)) { + errList.add("Designation"); + } else { + String position = record.get(4).trim(); + userRegistration.setPosition(position); + if (!ProjectUtil.validateRegexPatternWithNoSpecialCharacter(userRegistration.getPosition()) || this.validateFieldValue(Constants.POSITION, userRegistration.getPosition())) { + invalidErrList.add("Invalid Designation: Designation should be added from default list and/or cannot contain special character"); + } + } + + if (!isFieldEmpty(record, 5)) { + String gender = record.get(5).trim(); + if (userUtilityService.validateGender(gender)) { + userRegistration.setGender(gender); + } else { + invalidErrList.add("Invalid Gender : Gender can be only among one of these " + serverProperties.getBulkUploadGenderValue()); + } + } + + if (!isFieldEmpty(record, 6)) { + String category = record.get(6).trim(); + if (userUtilityService.validateCategory(category)) { + userRegistration.setCategory(category); + } else { + invalidErrList.add("Invalid Category : Category can be only among one of these " + serverProperties.getBulkUploadCategoryValue()); + } + } + + if (!isFieldEmpty(record, 7)) { + String dob = record.get(7).trim(); + if (ProjectUtil.validateDate(dob)) { + userRegistration.setDob(dob); + } else { + invalidErrList.add("Invalid format for Date of Birth type. Expecting in dd-mm-yyyy format"); + } + } + + if (!isFieldEmpty(record, 8)) { + String motherTongue = record.get(8).trim(); + userRegistration.setDomicileMedium(motherTongue); + if (!ProjectUtil.validateRegexPatternWithNoSpecialCharacter(userRegistration.getDomicileMedium()) || this.validateFieldValue(Constants.LANGUAGES, userRegistration.getDomicileMedium())) { + invalidErrList.add("Invalid Mother Tongue: Mother Tongue should be added from default list and/or cannot contain special character"); + } + } + + if (!isFieldEmpty(record, 9)) { + String employeeId = record.get(9).trim(); + userRegistration.setEmployeeId(employeeId); + if (!ProjectUtil.validateEmployeeId(userRegistration.getEmployeeId())) { + invalidErrList.add("Invalid Employee ID : Employee ID can contain alphabetic, alphanumeric or numeric character(s) and have a max length of 30"); + } + if (userRegistration.getEmployeeId().contains(Constants.SPACE)) { + invalidErrList.add("Employee Id cannot contain spaces"); + } + } + + if (!isFieldEmpty(record, 10)) { + String pincode = record.get(10).trim(); + userRegistration.setPincode(pincode); + if (!ProjectUtil.validatePinCode(userRegistration.getPincode())) { + invalidErrList.add("Invalid Office Pin Code : Office Pin Code should be numeric and is of 6 digit."); + } + } + + if (!isFieldEmpty(record, 11)) { + String externalSystemId = record.get(11).trim(); + userRegistration.setExternalSystemId(externalSystemId); + if (!ProjectUtil.validateExternalSystemId(userRegistration.getExternalSystemId())) { + invalidErrList.add("Invalid External System ID : External System Id can contain alphanumeric characters and have a max length of 30"); + } + } + if (!isFieldEmpty(record, 12)) { + String externalSystem = record.get(12).trim(); + userRegistration.setExternalSystem(externalSystem); + if (!ProjectUtil.validateExternalSystem(userRegistration.getExternalSystem())) { + invalidErrList.add("Invalid External System Name : External System Name can contain only alphabets and alphanumeric and can have a max length of 255"); + } + } + + if (!isFieldEmpty(record, 13)) { + String tagStr = record.get(13).trim(); + List tagList = new ArrayList<>(); + if (!StringUtils.isEmpty(tagStr)) { + String[] tagStrList = tagStr.split("&", -1); + for (String tag : tagStrList) { + tagList.add(tag.trim()); + } + } + userRegistration.setTag(tagList); + if (!ProjectUtil.validateTag(userRegistration.getTag())) { + invalidErrList.add("Invalid Tag: Tags are separated by '&' and can contain only alphabets with spaces. e.g., Bihar Circle&Patna Division"); + } + } + userRegistration.setOrgName(inputDataMap.get(Constants.ORG_NAME)); + userRegistration.setChannel(inputDataMap.get(Constants.ORG_NAME)); + userRegistration.setSbOrgId(inputDataMap.get(Constants.ROOT_ORG_ID)); + + if (!errList.isEmpty()) { + failedRecordsCount++; + updatedRecord.put("Status", "FAILED"); + updatedRecord.put("Error Details", String.join(", ", errList)); + } else { + invalidErrList.addAll(validateEmailContactAndDomain(userRegistration)); + if (invalidErrList.isEmpty()) { + userRegistration.setUserAuthToken(inputDataMap.get(Constants.X_AUTH_TOKEN)); + String responseCode = userUtilityService.createBulkUploadUser(userRegistration); + if (!Constants.OK.equalsIgnoreCase(responseCode)) { + failedRecordsCount++; + updatedRecord.put("Status", "FAILED"); + updatedRecord.put("Error Details", responseCode); + } else { + noOfSuccessfulRecords++; + updatedRecord.put("Status", Constants.SUCCESSFUL_UPPERCASE); + updatedRecord.put("Error Details", ""); + } + } else { + failedRecordsCount++; + updatedRecord.put("Status", "FAILED"); + updatedRecord.put("Error Details", String.join(", ", invalidErrList)); + } + } + + updatedRecords.add(updatedRecord); + } + + // Write back updated records to the same CSV file + fileWriter = new FileWriter(file); + bufferedWriter = new BufferedWriter(fileWriter); + csvPrinter = new CSVPrinter(bufferedWriter, CSVFormat.INFORMIX_UNLOAD.withHeader(headers.toArray(new String[0]))); + + + for (Map record : updatedRecords) { + List recordValues = new ArrayList<>(); + for (String header : headers) { + recordValues.add(record.get(header)); + } + csvPrinter.printRecord(recordValues); + } + + if (totalRecordsCount == 0) { + List singleRow = new ArrayList<>(Collections.nCopies(headers.size(), "")); + singleRow.set(headers.indexOf("Status"), Constants.FAILED_UPPERCASE); + singleRow.set(headers.indexOf("Error Details"), Constants.EMPTY_FILE_FAILED); + csvPrinter.printRecord(singleRow); + status = Constants.FAILED_UPPERCASE; + } + csvPrinter.flush(); + + status = uploadTheUpdatedCSVFile(file); + + + status = (failedRecordsCount == 0 && totalRecordsCount == noOfSuccessfulRecords && totalRecordsCount >= 1) + ? Constants.SUCCESSFUL_UPPERCASE + : Constants.FAILED_UPPERCASE; + + updateUserBulkUploadStatus(inputDataMap.get(Constants.ROOT_ORG_ID), inputDataMap.get(Constants.IDENTIFIER), + status, totalRecordsCount, noOfSuccessfulRecords, failedRecordsCount); + + } else { + logger.info("Error in Process Bulk Upload: The File is not downloaded/present"); + status = Constants.FAILED_UPPERCASE; + } + updateUserBulkUploadStatus(inputDataMap.get(Constants.ROOT_ORG_ID), inputDataMap.get(Constants.IDENTIFIER), + status, 0, 0, 0); + } catch (Exception e) { + logger.error(String.format("Error in Process Bulk Upload %s", e.getMessage()), e); + updateUserBulkUploadStatus(inputDataMap.get(Constants.ROOT_ORG_ID), inputDataMap.get(Constants.IDENTIFIER), + Constants.FAILED_UPPERCASE, 0, 0, 0); + } finally { + if (csvParser != null) + csvParser.close(); + if (csvPrinter != null) + csvPrinter.close(); + if (bufferedWriter != null) + bufferedWriter.close(); + if (fileWriter != null) + fileWriter.close(); + if (file != null) + file.delete(); + } + } + + private boolean isFieldEmpty(CSVRecord record, int index) { + return record.get(index) == null || record.get(index).trim().isEmpty(); + } + private void setErrorDetails(StringBuffer str, List errList, Cell statusCell, Cell errorDetails) { str.append("Failed to process user record. Missing Parameters - ").append(errList); @@ -438,6 +713,17 @@ private String uploadTheUpdatedFile(File file, XSSFWorkbook wb) return Constants.SUCCESSFUL_UPPERCASE; } + private String uploadTheUpdatedCSVFile(File file) + throws IOException { + + SBApiResponse uploadResponse = storageService.uploadFile(file, serverProperties.getBulkUploadContainerName(),serverProperties.getCloudContainerName()); + if (!HttpStatus.OK.equals(uploadResponse.getResponseCode())) { + logger.info(String.format("Failed to upload file. Error: %s", + uploadResponse.getParams().getErrmsg())); + return Constants.FAILED_UPPERCASE; + } + return Constants.SUCCESSFUL_UPPERCASE; + } private List validateEmailContactAndDomain(UserRegistration userRegistration) { StringBuffer str = new StringBuffer(); List errList = new ArrayList<>(); diff --git a/src/main/java/org/sunbird/ratings/service/RatingServiceImpl.java b/src/main/java/org/sunbird/ratings/service/RatingServiceImpl.java index 09da2527c..08f372766 100644 --- a/src/main/java/org/sunbird/ratings/service/RatingServiceImpl.java +++ b/src/main/java/org/sunbird/ratings/service/RatingServiceImpl.java @@ -793,10 +793,7 @@ private String getProfileDetailsUrlForUser(String profileDetails, String userId) }); } if (MapUtils.isNotEmpty(profileDetailsMap)) { - personDetails = (Map) profileDetailsMap.get(Constants.PERSONAL_DETAILS); - } - if (MapUtils.isNotEmpty(personDetails)) { - profileImageUrl = (String) personDetails.get(Constants.PROFILE_IMAGE_URL); + profileImageUrl = (String) profileDetailsMap.get(Constants.PROFILE_IMAGE_URL); } } catch (Exception e) { logger.error("Not able to read the profile Details for userId: " + userId, e);