...
java -jar codegen-1.0-SNAPSHOT-jar-with-dependencies.jar -l -t -u https://raw.githubusercontent.com/egovernments/DIGIT-OSS/DIGIT-DEVELOPER-TUTORIAL/municipal-services/docs/birth-registration.yaml -a voterbirth-registration -b digit
3. Update the spring-boot-starter-parent to 2.2.6-RELEASE (After updating spring boot version do maven update)
...
Code Block |
---|
@Service public class BirthRegistrationService { @Autowired private BirthApplicationValidator validator; @Autowired private BirthApplicationEnrichment enrichmentUtil; @Autowired private UserService userService; @Autowired private WorkflowService workflowService; @Autowired private BirthRegistrationRepository birthRegistrationRepository; @Autowired private Producer producer; public List<BirthRegistrationApplication> registerBtRequest(BirthRegistrationRequest birthRegistrationRequest) { // Validate applications validator.validateBirthApplication(birthRegistrationRequest); // Enrich applications enrichmentUtil.enrichBirthApplication(birthRegistrationRequest); // Enrich/Upsert user in upon birth registration userService.callUserService(birthRegistrationRequest); // Initiate workflow for the new application workflowService.updateWorkflowStatus(birthRegistrationRequest); // Push the application to the topic for persister to listen and persist producer.push("save-bt-application", birthRegistrationRequest); // Return the response back to user return birthRegistrationRequest.getBirthRegistrationApplications(); } public List<BirthRegistrationApplication> searchBtApplications(RequestInfo requestInfo, BirthApplicationSearchCriteria birthApplicationSearchCriteria) { // Fetch applications from database according to the given search criteria List<BirthRegistrationApplication> applications = BirthRegistrationRepository.getApplications(voterApplicationSearchCriteriabirthApplicationSearchCriteria); // If no applications are found matching the given criteria, return an empty list if(CollectionUtils.isEmpty(applications)) return new ArrayList<>(); // Otherwise return the found applications return applications; } public BirthRegistrationApplication updateBtApplication(BirthRegistrationRequest birthRegistrationRequest) { // Validate whether the application that is being requested for update indeed exists BirthRegistrationApplication existingApplication = validator.validateApplicationExistence(birthRegistrationRequest.getBirthRegistrationApplications().get(0)); existingApplication.setWorkflow(birthRegistrationRequest.getBirthRegistrationApplications().get(0).getWorkflow()); birthRegistrationRequest.setBirthRegistrationApplications(Collections.singletonList(existingApplication)); // Enrich application upon update enrichmentUtil.enrichBirthApplicationUponUpdate(birthRegistrationRequest); workflowService.updateWorkflowStatus(birthRegistrationRequest); // Just like create request, update request will be handled asynchronously by the persister producer.push("update-bt-application", birthRegistrationRequest.getBirthRegistrationApplications().get(0)); return birthRegistrationRequest.getBirthRegistrationApplications().get(0); } } |
...
Code Block |
---|
@Component public class BirthApplicationEnrichment { @Autowired private IdgenUtil idgenUtil; public void enrichBirthApplication(BirthRegistrationRequest birthRegistrationRequest) { List<String> birthRegistrationIdList = idgenUtil.getIdList(birthRegistrationRequest.getRequestInfo(), birthRegistrationRequest.getBirthRegistrationApplications().get(0).getTenantId(), "btr.registrationid", "", birthRegistrationRequest.getBirthRegistrationApplications().size()); Integer index = 0; for(BirthRegistrationApplication application : birthRegistrationRequest.getBirthRegistrationApplications()){ // Enrich audit details AuditDetails auditDetails = AuditDetails.builder().createdBy(birthRegistrationRequest.getRequestInfo().getUserInfo().getUuid()).createdTime(System.currentTimeMillis()).lastModifiedBy(birthRegistrationRequest.getRequestInfo().getUserInfo().getUuid()).lastModifiedTime(System.currentTimeMillis()).build(); application.setAuditDetails(auditDetails); // Enrich UUID application.setId(UUID.randomUUID().toString()); // Enrich registration Id application.getAddress().setRegistrationId(application.getId()); // Enrich address UUID application.getAddress().setId(UUID.randomUUID().toString()); //Enrich application number from IDgen application.setApplicationNumber(voterRegistrationIdListbirthRegistrationIdList.get(index++)); } } public void enrichBirthApplicationUponUpdate(BirthRegistrationRequest birthRegistrationRequest) { // Enrich lastModifiedTime and lastModifiedBy in case of update birthRegistrationRequest.getBirthRegistrationApplications().get(0).getAuditDetails().setLastModifiedTime(System.currentTimeMillis()); birthRegistrationRequest.getBirthRegistrationApplications().get(0).getAuditDetails().setLastModifiedBy(voterRegistrationRequestbirthRegistrationRequest.getRequestInfo().getUserInfo().getUuid()); } } |
...
Code Block |
---|
@Service public class UserService { private UserUtil userUtils; private BTRConfiguration config; @Autowired public UserService(UserUtil userUtils, BTRConfiguration config) { this.userUtils = userUtils; this.config = config; } /** * Calls user service to enrich user from search or upsert user * @param request */ public void callUserService(BirthRegistrationRequest request){ request.getBirthRegistrationApplications().forEach(application -> { if(!StringUtils.isEmpty(application.getApplicant().getId())) enrichUser(application, request.getRequestInfo()); else upsertUser(application, request.getRequestInfo()); }); } private void upsertUser(BirthRegistrationApplication application, RequestInfo requestInfo){ Applicant applicant = application.getApplicant(); User user = User.builder().userName(applicant.getUserName()) .password(applicant.getPassword()) .salutation(applicant.getSalutation()) .name(applicant.getName()) .gender(applicant.getGender()) .mobileNumber(applicant.getMobileNumber()) .emailId(applicant.getEmailId()) .altContactNumber(applicant.getAltContactNumber()) .babyFirstName(applicant.babyFirstName()) .babyLastName(applicant.babyLastName()) .doctorAttendingBirth(applicant.doctorAttendingBirth()) .hospitalName(applicant.hospitalName()) .placeOfBirth(applicant.placeOfBirth()) .permanentAddress(applicant.getPermanentAddress()) .permanentCity(applicant.getPermanentCity()) .permanentPincode(applicant.getPermanentPincode()) .correspondenceCity(applicant.getCorrespondenceCity()) .correspondencePincode(applicant.getCorrespondencePincode()) .correspondenceAddress(applicant.getCorrespondenceAddress()) .active(applicant.getActive()) .locale(applicant.getLocale()) .signature(applicant.getSignature()) .accountLocked(applicant.getAccountLocked()) .fatherOrHusbandName(applicant.getFatherOrHusbandName()) .bloodGroup(applicant.getBloodGroup()) .identificationMark(applicant.getIdentificationMark()) .photo(applicant.getPhoto()) .otpReference(applicant.getOtpReference()) .tenantId(applicant.getTenantId()) .type(applicant.getType()) .roles(applicant.getRoles()) .tenantId(applicant.getTenantId()) .aadhaarNumber(applicant.getAadhaarNumber()) .build(); String tenantId = applicant.getTenantId(); User userServiceResponse = null; // Search on mobile number as user name UserDetailResponse userDetailResponse = searchUser(userUtils.getStateLevelTenant(tenantId),null, user.getMobileNumber()); if (!userDetailResponse.getUser().isEmpty()) { User userFromSearch = userDetailResponse.getUser().get(0); if(!user.getName().equalsIgnoreCase(userFromSearch.getName())){ userServiceResponse = updateUser(requestInfo,user,userFromSearch); } else userServiceResponse = userDetailResponse.getUser().get(0); } else { userServiceResponse = createUser(requestInfo,tenantId,user); } // Enrich the accountId applicant.setId(userServiceResponse.getUuid()); } private void enrichUser(VoterRegistrationApplicationBirthRegistrationApplication application, RequestInfo requestInfo){ String accountId = application.getApplicant().getId(); String tenantId = application.getApplicant().getTenantId(); UserDetailResponse userDetailResponse = searchUser(userUtils.getStateLevelTenant(tenantId),accountId,null); if(userDetailResponse.getUser().isEmpty()) throw new CustomException("INVALID_ACCOUNTID","No user exist for the given accountId"); else application.getApplicant().setId(userDetailResponse.getUser().get(0).getUuid()); } /** * Creates the user from the given userInfo by calling user service * @param requestInfo * @param tenantId * @param userInfo * @return */ private User createUser(RequestInfo requestInfo,String tenantId, User userInfo) { userUtils.addUserDefaultFields(userInfo.getMobileNumber(),tenantId, userInfo); StringBuilder uri = new StringBuilder(config.getUserHost()) .append(config.getUserContextPath()) .append(config.getUserCreateEndpoint()); UserDetailResponse userDetailResponse = userUtils.userCall(new CreateUserRequest(requestInfo, userInfo), uri); return userDetailResponse.getUser().get(0); } /** * Updates the given user by calling user service * @param requestInfo * @param user * @param userFromSearch * @return */ private User updateUser(RequestInfo requestInfo,User user,User userFromSearch) { userFromSearch.setName(user.getName()); userFromSearch.setActive(true); StringBuilder uri = new StringBuilder(config.getUserHost()) .append(config.getUserContextPath()) .append(config.getUserUpdateEndpoint()); UserDetailResponse userDetailResponse = userUtils.userCall(new CreateUserRequest(requestInfo, userFromSearch), uri); return userDetailResponse.getUser().get(0); } /** * calls the user search API based on the given accountId and userName * @param stateLevelTenant * @param accountId * @param userName * @return */ private UserDetailResponse searchUser(String stateLevelTenant, String accountId, String userName){ UserSearchRequest userSearchRequest =new UserSearchRequest(); userSearchRequest.setActive(true); userSearchRequest.setUserType("CITIZEN"); userSearchRequest.setTenantId(stateLevelTenant); if(StringUtils.isEmpty(accountId) && StringUtils.isEmpty(userName)) return null; if(!StringUtils.isEmpty(accountId)) userSearchRequest.setUuid(Collections.singletonList(accountId)); if(!StringUtils.isEmpty(userName)) userSearchRequest.setUserName(userName); StringBuilder uri = new StringBuilder(config.getUserHost()).append(config.getUserSearchEndpoint()); return userUtils.userCall(userSearchRequest,uri); } /** * calls the user search API based on the given list of user uuids * @param uuids * @return */ private Map<String,User> searchBulkUser(List<String> uuids){ UserSearchRequest userSearchRequest =new UserSearchRequest(); userSearchRequest.setActive(true); userSearchRequest.setUserType("CITIZEN"); if(!CollectionUtils.isEmpty(uuids)) userSearchRequest.setUuid(uuids); StringBuilder uri = new StringBuilder(config.getUserHost()).append(config.getUserSearchEndpoint()); UserDetailResponse userDetailResponse = userUtils.userCall(userSearchRequest,uri); List<User> users = userDetailResponse.getUser(); if(CollectionUtils.isEmpty(users)) throw new CustomException("USER_NOT_FOUND","No user found for the uuids"); Map<String,User> idToUserMap = users.stream().collect(Collectors.toMap(User::getUuid, Function.identity())); return idToUserMap; } } |
...
Code Block |
---|
@Autowired private RestTemplate restTemplate; @Autowired private VTRConfigurationBTRConfiguration config; public String getShortenedUrl(String url){ HashMap<String,String> body = new HashMap<>(); body.put("url",url); StringBuilder builder = new StringBuilder(config.getUrlShortnerHost()); builder.append(config.getUrlShortnerEndpoint()); String res = restTemplate.postForObject(builder.toString(), body, String.class); if(StringUtils.isEmpty(res)){ log.error("URL_SHORTENING_ERROR", "Unable to shorten url: " + url); ; return url; } else return res; } |
...
Code Block |
---|
@Component public class WorkflowService { @Autowired private ObjectMapper mapper; @Autowired private ServiceRequestRepository repository; @Autowired private BTRConfiguration config; public void updateWorkflowStatus(BirthRegistrationRequest birthRegistrationRequest) { birthRegistrationRequest.getBirthRegistrationApplications().forEach(application -> { ProcessInstance processInstance = getProcessInstanceForBTR(application, birthRegistrationRequest.getRequestInfo()); ProcessInstanceRequest workflowRequest = new ProcessInstanceRequest(birthRegistrationRequest.getRequestInfo(), Collections.singletonList(processInstance)); callWorkFlow(workflowRequest); }); } public State callWorkFlow(ProcessInstanceRequest workflowReq) { ProcessInstanceResponse response = null; StringBuilder url = new StringBuilder(config.getWfHost().concat(config.getWfTransitionPath())); Object optional = repository.fetchResult(url, workflowReq); response = mapper.convertValue(optional, ProcessInstanceResponse.class); return response.getProcessInstances().get(0).getState(); } private ProcessInstance getProcessInstanceForVTRgetProcessInstanceForBTR(BirthRegistrationApplication application, RequestInfo requestInfo) { Workflow workflow = application.getWorkflow(); ProcessInstance processInstance = new ProcessInstance(); processInstance.setBusinessId(application.getApplicationNumber()); processInstance.setAction(workflow.getAction()); processInstance.setModuleName("voterbirth-services"); processInstance.setTenantId(application.getTenantId()); processInstance.setBusinessService("VTRBTR"); processInstance.setDocuments(workflow.getDocuments()); processInstance.setComment(workflow.getComments()); if(!CollectionUtils.isEmpty(workflow.getAssignes())){ List<User> users = new ArrayList<>(); workflow.getAssignes().forEach(uuid -> { digit.web.models.User user = new digit.web.models.User(); user.setUuid(uuid); users.add(user); }); processInstance.setAssignes(users); } return processInstance; } private BusinessService getBusinessService(BirthRegistrationApplication application, RequestInfo requestInfo) { String tenantId = application.getTenantId(); StringBuilder url = getSearchURLWithParams(tenantId, "BTR"); RequestInfoWrapper requestInfoWrapper = RequestInfoWrapper.builder().requestInfo(requestInfo).build(); Object result = repository.fetchResult(url, requestInfoWrapper); BusinessServiceResponse response = null; try { response = mapper.convertValue(result, BusinessServiceResponse.class); } catch (IllegalArgumentException e) { throw new CustomException("PARSING ERROR", "Failed to parse response of workflow business service search"); } if (CollectionUtils.isEmpty(response.getBusinessServices())) throw new CustomException("BUSINESSSERVICE_NOT_FOUND", "The businessService " + "BTR" + " is not found"); return response.getBusinessServices().get(0); } private StringBuilder getSearchURLWithParams(String tenantId, String businessService) { StringBuilder url = new StringBuilder(config.getWfHost()); url.append(config.getWfBusinessServiceSearchPath()); url.append("?tenantId="); url.append(tenantId); url.append("&businessServices="); url.append(businessService); return url; } public ProcessInstanceRequest getProcessInstanceForBirthRegistrationPayment(BirthRegistrationRequest updateRequest) { BirthRegistrationApplication application = updateRequest.getBirthRegistrationApplications().get(0); ProcessInstance process = ProcessInstance.builder() .businessService("BTR") .businessId(application.getApplicationNumber()) .comment("Payment for birth registration processed") .moduleName("birth-services") .tenantId(application.getTenantId()) .action("PAY") .build(); return ProcessInstanceRequest.builder() .requestInfo(updateRequest.getRequestInfo()) .processInstances(Arrays.asList(process)) .build(); } } |
...
For our guide, we will be implementing a notification consumer which will listen onto the topic on which voter birth registration applications are created, create a customized message and send it to the notification service(sms/email) to be sent to the concerned users.
...
The final step in this process is the creation of configs to create a voter birth registration PDF for the citizens to download. For this, we will make use of DIGIT’s PDF service which uses PDFMake and Mustache libraries to generate PDF. A detailed documentation on PDF service and generating PDFs using PDF service can be found here - PDF Generation Service.
For our guide, we will follow the following steps to set up PDF service locally and generate PDF for our voter birth registration service -
i) Clone DIGIT Services repo.
...