diff --git a/reference-adapter/src/main/java/org/egov/ifix/consumer/EventTypeConsumer.java b/reference-adapter/src/main/java/org/egov/ifix/consumer/EventTypeConsumer.java index f389ef909..10126b0b6 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/consumer/EventTypeConsumer.java +++ b/reference-adapter/src/main/java/org/egov/ifix/consumer/EventTypeConsumer.java @@ -1,14 +1,9 @@ package org.egov.ifix.consumer; -import java.time.Instant; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; import org.egov.common.contract.request.RequestHeader; -import org.egov.common.contract.request.RequestHeader.RequestHeaderBuilder; import org.egov.ifix.mapper.EventMapper; import org.egov.ifix.models.FiscalEvent; import org.egov.ifix.models.FiscalEventRequest; @@ -17,17 +12,20 @@ import org.egov.ifix.persistance.EventPostingDetailRepository; import org.egov.ifix.service.PostEvent; import org.egov.ifix.service.ProjectService; -import org.egov.ifix.utils.MasterDataMappingUtil; +import org.egov.ifix.utils.ApplicationConfiguration; +import org.egov.ifix.utils.EventConstants; import org.egov.ifix.utils.RequestHeaderUtil; +import org.egov.ifix.exception.GenericCustomException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestClientException; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -37,10 +35,6 @@ @Slf4j public class EventTypeConsumer { - private static final String EVENT_TYPE = "eventType"; - - private static final String EVENT = "event"; - private List eventMappers; private Map eventTypeMap = new HashMap<>(); @@ -53,6 +47,12 @@ public class EventTypeConsumer { private ProjectService projectService; + @Autowired + private KafkaTemplate kafkaTemplate; + + @Autowired + private ApplicationConfiguration applicationConfiguration; + @Autowired public EventTypeConsumer(List eventMappers, PostEvent postEvent, EventPostingDetailRepository eventPostingDetailRepository, RequestHeaderUtil requestHeaderUtil, @@ -74,90 +74,261 @@ private void initializeEventTypeMap() { @KafkaListener(topics = "${kafka.topics.ifix.adaptor.mapper}") public void listen(final String record) { - process(record, null); +// process(record, null); + processFiscalEvent(record); } - public void process(final String record, EventPostingDetail detail) { - log.info("Received Message from topic: " + record); - JsonObject jsonObject = null; - log.info("\n\n"); + /** + * @param record + */ + private void processFiscalEvent(String record) { + log.info(EventConstants.LOG_INFO_PREFIX + "Transforming and collecting fiscal event: \n" + record); + + validateEventRequest(record); + FiscalEventRequest fiscalEventRequest = new FiscalEventRequest(); + List eventPostingDetailList = new ArrayList<>(); + + JsonObject jsonObject = JsonParser.parseString(record).getAsJsonObject(); + JsonObject eventJsonObject = jsonObject.getAsJsonObject(EventConstants.EVENT); + String eventId = eventJsonObject.get(EventConstants.ID).getAsString(); + try { - jsonObject = JsonParser.parseString(record).getAsJsonObject(); - EventMapper eventMapper = eventTypeMap.get(jsonObject.getAsJsonObject(EVENT).get(EVENT_TYPE).getAsString()); + RequestHeader header = requestHeaderUtil.polulateRequestHeader(jsonObject, new RequestHeader()); + fiscalEventRequest.setRequestHeader(header); + + EventMapper eventMapper = eventTypeMap.get(eventJsonObject.get(EventConstants.EVENT_TYPE).getAsString()); + List fiscalEvents = eventMapper.transformData(jsonObject); - FiscalEventRequest request = new FiscalEventRequest(); - RequestHeader header = new RequestHeader(); - header = requestHeaderUtil.polulateRequestHeader(jsonObject, header); - request.setRequestHeader(header); - loop: for (FiscalEvent event : fiscalEvents) { + fiscalEventRequest.setFiscalEvent(fiscalEvents); + + postFiscalEvent(record, eventId, fiscalEventRequest); + + } catch (Exception e) { + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.NON_RECOVERABLE_ERROR + + "Exception while transforming and collecting fiscal data. ", e); - if (jsonObject.getAsJsonObject(EVENT).get("projectId") != null) { - log.info("mgram prooject id " + jsonObject.getAsJsonObject(EVENT).get("projectId")); - String clientCode = jsonObject.getAsJsonObject(EVENT).get("projectId").getAsString(); - String iFixprojectId = projectService.getProjectId(clientCode, jsonObject); - event.setProjectId(iFixprojectId); + EventPostingDetail errorDetail = new EventPostingDetail(); + errorDetail.setEventId(eventJsonObject.get(EventConstants.ID).getAsString()); + errorDetail.setTenantId(eventJsonObject.get(EventConstants.TENANT_ID).getAsString()); + errorDetail.setEventType(eventJsonObject.get(EventConstants.EVENT_TYPE).getAsString()); + errorDetail.setCreatedDate(new Date()); + errorDetail.setLastModifiedDate(new Date()); + errorDetail.setStatus(EventConstants.NA); + errorDetail.setError("Internal Fiscal Event Conversion/Transformation error : " + e.getMessage()); + errorDetail.setRecord(record); + eventPostingDetailRepository.save(errorDetail); + } + } + + /** + * TODO: Only erroneous event should be captured and saved in DB (detail.setRecord(record)). + * There is no segragation between successfull or unsuccessfull fiscal event in response. + * Either whole fiscal event get fail or pass. + * + * @param record + * @param eventId + * @param fiscalEventRequest + * @param eventPostingDetailList + */ + public void postFiscalEvent(final String record, String eventId, FiscalEventRequest fiscalEventRequest) { + + List eventPostingDetailList = new ArrayList<>(); + + if (fiscalEventRequest != null && fiscalEventRequest.getFiscalEvent() != null && !StringUtils.isEmpty(record) + && !StringUtils.isEmpty(eventId)) { + try { + ResponseEntity fiscalEventResponseEntity = postEvent.post(fiscalEventRequest); + + eventPostingDetailList = wrapEventResponse(fiscalEventResponseEntity, + fiscalEventRequest.getFiscalEvent(), eventId, record); + } catch (RestClientException e) { + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.RECOVERABLE_ERROR + e.getMessage(), e); + eventPostingDetailList = composeEventPostingDetail(fiscalEventRequest.getFiscalEvent(), eventId, + HttpStatus.BAD_REQUEST, record, e.getMessage()); + +// kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventPostingDetailList); + + } catch (Exception e) { + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.NON_RECOVERABLE_ERROR + e.getMessage(), e); + eventPostingDetailList = composeEventPostingDetail(fiscalEventRequest.getFiscalEvent(), eventId, + HttpStatus.INTERNAL_SERVER_ERROR, record, e.getMessage()); + +// kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventPostingDetailList); + } + + eventPostingDetailRepository.saveAll(eventPostingDetailList); + }else { + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.NON_RECOVERABLE_ERROR + + "Invalid parameter to push event"); + } + } + + /** + * @param fiscalEventResponseEntity + * @param fiscalEventList + * @param eventId + * @param record + * @return + */ + private List wrapEventResponse(ResponseEntity fiscalEventResponseEntity, + List fiscalEventList, String eventId, String record) { + if (fiscalEventResponseEntity != null && fiscalEventResponseEntity.getStatusCode() != null + && fiscalEventList != null && !StringUtils.isEmpty(eventId) && !StringUtils.isEmpty(record)) { + List eventPostingDetailList = new ArrayList<>(); + + if (HttpStatus.Series.SERVER_ERROR.equals(fiscalEventResponseEntity.getStatusCode().series()) + || HttpStatus.Series.CLIENT_ERROR.equals(fiscalEventResponseEntity.getStatusCode().series())) { + + eventPostingDetailList = composeEventPostingDetail(fiscalEventList, eventId, + fiscalEventResponseEntity.getStatusCode(), record, EventConstants.NA); + + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.RECOVERABLE_ERROR + + "4 or 5 Series exception while sending request to Fiscal Event Service"); + +// kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventPostingDetailList); + + } else if (HttpStatus.Series.SUCCESSFUL.equals(fiscalEventResponseEntity.getStatusCode().series())) { + List respondedFiscalEvents = fiscalEventResponseEntity.getBody().getFiscalEvent(); + + if (respondedFiscalEvents != null && !respondedFiscalEvents.isEmpty()) { + eventPostingDetailList = composeEventPostingDetail(respondedFiscalEvents, eventId, + fiscalEventResponseEntity.getStatusCode(), EventConstants.NA,EventConstants.NA); + + log.info(EventConstants.LOG_INFO_PREFIX + "Succussfully send fiscal event to Fiscal Event Service"); + } else { + + eventPostingDetailList = composeEventPostingDetail(fiscalEventList, eventId, + fiscalEventResponseEntity.getStatusCode(), record, EventConstants.EMPTY_FISCAL_EVENT); + + log.error(EventConstants.LOG_ERROR_PREFIX + EventConstants.RECOVERABLE_ERROR + + "Unable to receive Fiscal Event list in response"); + +// kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventPostingDetailList); } - request.setFiscalEvent(event); - log.info("Project Id" + event.getProjectId()); + } + + return eventPostingDetailList; + } + + return Collections.emptyList(); + } + + + /** + * @param fiscalEventList + * @param eventId + * @param httpStatus + * @param record + * @return + */ + private List composeEventPostingDetail(List fiscalEventList, final String eventId, + final HttpStatus httpStatus, final String record, + final String error) { + if (fiscalEventList != null && !StringUtils.isEmpty(eventId) && httpStatus != null) { + return fiscalEventList.stream() + .map(fiscalEvent -> { + EventPostingDetail eventPostingDetail = new EventPostingDetail(); + eventPostingDetail.setEventId(eventId); + eventPostingDetail.setTenantId(fiscalEvent.getTenantId()); + eventPostingDetail.setReferenceId(fiscalEvent.getParentReferenceId()); + eventPostingDetail.setEventType(fiscalEvent.getEventType()); + eventPostingDetail.setCreatedDate(new Date()); + eventPostingDetail.setLastModifiedDate(new Date()); + eventPostingDetail.setProjectId(fiscalEvent.getProjectId()); + eventPostingDetail.setError(error); + eventPostingDetail.setStatus(String.valueOf(httpStatus.value())); + + if (HttpStatus.Series.SUCCESSFUL.equals(httpStatus.series())) { + eventPostingDetail.setIfixEventId(fiscalEvent.getId()); + } else { + eventPostingDetail.setRecord(record); + } + + return eventPostingDetail; + }).collect(Collectors.toList()); + } + return Collections.emptyList(); + } + + + public void process(final String record, EventPostingDetail detail) { + validateEventRequest(record); + FiscalEventRequest fiscalEventRequest = new FiscalEventRequest(); + JsonObject jsonObject = JsonParser.parseString(record).getAsJsonObject(); + JsonObject eventJsonObject = jsonObject.getAsJsonObject(EventConstants.EVENT); + + try { + RequestHeader header = requestHeaderUtil.polulateRequestHeader(jsonObject, new RequestHeader()); + fiscalEventRequest.setRequestHeader(header); + + EventMapper eventMapper = eventTypeMap.get(jsonObject.getAsJsonObject(EventConstants.EVENT) + .get(EventConstants.EVENT_TYPE).getAsString()); + + List fiscalEvents = eventMapper.transformData(jsonObject); + + loop: + for (FiscalEvent fiscalEvent : fiscalEvents) { + String clientProjectCode = eventJsonObject.get(EventConstants.PROJECT_ID).getAsString(); + + log.info(EventConstants.LOG_INFO_PREFIX + "MgramSeva project code " + clientProjectCode); + + String iFixProjectId = projectService.getProjectId(clientProjectCode, jsonObject); + + log.info(EventConstants.LOG_INFO_PREFIX + "IFix project id " + iFixProjectId); + + fiscalEvent.setProjectId(iFixProjectId); +// fiscalEventRequest.setFiscalEvent(fiscalEvent); if (detail == null) { detail = new EventPostingDetail(); - if (jsonObject.getAsJsonObject(EVENT).get("id") != null) { - detail.setEventId(jsonObject.getAsJsonObject(EVENT).get("id").getAsString()); - detail.setTenantId(event.getTenantId()); - detail.setReferenceId(event.getParentReferenceId()); - detail.setEventType(event.getEventType()); - detail.setCreatedDate(new Date()); - detail.setLastModifiedDate(new Date()); - - } + detail.setEventId(eventJsonObject.get(EventConstants.ID).getAsString()); + detail.setTenantId(fiscalEvent.getTenantId()); + detail.setReferenceId(fiscalEvent.getParentReferenceId()); + detail.setEventType(fiscalEvent.getEventType()); + detail.setCreatedDate(new Date()); + detail.setLastModifiedDate(new Date()); } try { - - ResponseEntity response = postEvent.post(request); + ResponseEntity response = postEvent.post(fiscalEventRequest); if (response.getStatusCode().series().equals(HttpStatus.Series.SERVER_ERROR) || response.getStatusCode().series().equals(HttpStatus.Series.CLIENT_ERROR)) { detail.setRecord(record); } else if (response.getStatusCode().series().equals(HttpStatus.Series.SUCCESSFUL)) { - detail.setIfixEventId(response.getBody().getFiscalEvent().get(0).getId()); } + detail.setStatus(String.valueOf(response.getStatusCode().value())); detail.setRecord(record); eventPostingDetailRepository.save(detail); } catch (ResourceAccessException e) { - log.info(e.getMessage(), e); + log.error(e.getMessage(), e); detail.setStatus("500"); detail.setError(extractedMessage(e)); detail.setRecord(record); eventPostingDetailRepository.save(detail); break loop; - } - catch (RestClientException e) { - log.info(e.getMessage(), e); + } catch (RestClientException e) { + log.error(e.getMessage(), e); detail.setStatus("400"); detail.setError(extractedMessage(e)); detail.setRecord(record); eventPostingDetailRepository.save(detail); - } } } catch (RuntimeException e) { - log.info(e.getMessage(), e); - - log.info(e.getMessage(), e); + log.error(e.getMessage(), e); EventPostingDetail errorDetail = new EventPostingDetail(); - errorDetail.setEventId(jsonObject.getAsJsonObject(EVENT).get("id").getAsString()); - errorDetail.setTenantId(jsonObject.getAsJsonObject(EVENT).get("tenantId").getAsString()); + errorDetail.setEventId(eventJsonObject.get(EventConstants.ID).getAsString()); + errorDetail.setTenantId(eventJsonObject.get(EventConstants.TENANT_ID).getAsString()); errorDetail.setReferenceId("Not extracted"); - errorDetail.setEventType(jsonObject.getAsJsonObject(EVENT).get(EVENT_TYPE).getAsString()); + errorDetail.setEventType(eventJsonObject.get(EventConstants.EVENT_TYPE).getAsString()); errorDetail.setCreatedDate(new Date()); errorDetail.setLastModifiedDate(new Date()); errorDetail.setStatus("400"); @@ -178,4 +349,45 @@ private String extractedMessage(Exception e) { return message; } + + /** + * TODO: Validation of whole event request still pending + * + * @param eventRequest + */ + private void validateEventRequest(String eventRequest) { + if (eventRequest != null) { + JsonObject jsonObject = JsonParser.parseString(eventRequest).getAsJsonObject(); + + if (!jsonObject.has(EventConstants.EVENT)) { + throw new GenericCustomException(EventConstants.EVENT, "Event attribute is missing in payload"); + } else { + Map errorMap = new HashMap<>(); + JsonObject eventObject = jsonObject.getAsJsonObject(EventConstants.EVENT); + + if (!eventObject.has(EventConstants.EVENT_TYPE)) { + errorMap.put(EventConstants.EVENT_TYPE, "Event Type is missing in payload"); + } + + if (!eventObject.has(EventConstants.PROJECT_ID) || eventObject.get(EventConstants.PROJECT_ID).isJsonNull()) { + errorMap.put(EventConstants.PROJECT_ID, "Project id is missing in event payload"); + } + + if (!eventObject.has(EventConstants.ID)) { + errorMap.put(EventConstants.ID, "Id is missing in event payload"); + } + + if (!eventObject.has(EventConstants.ENTITY) + || eventObject.getAsJsonArray(EventConstants.ENTITY).size() <= 0) { + errorMap.put(EventConstants.ENTITY, "Event Entity is missing in payload"); + } + + if (!errorMap.isEmpty()) { + throw new GenericCustomException(errorMap); + } + } + }else { + throw new GenericCustomException(EventConstants.PAYLOAD, "Invalid payload"); + } + } } diff --git a/reference-adapter/src/main/java/org/egov/ifix/controller/EventController.java b/reference-adapter/src/main/java/org/egov/ifix/controller/EventController.java index 1986f2626..43f66d969 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/controller/EventController.java +++ b/reference-adapter/src/main/java/org/egov/ifix/controller/EventController.java @@ -28,7 +28,7 @@ public class EventController { private EventService eventService; @PostMapping("/events/v1/_push") - public ResponseEntitypushEvents( @Valid @RequestBody EventRequest eventRequest) { + public ResponseEntitypushEvents(@RequestBody EventRequest eventRequest) { log.debug("request received"); eventService.pushEvent(eventRequest); EventResponse response=new EventResponse(); diff --git a/reference-adapter/src/main/java/org/egov/ifix/exception/ExceptionAdvise.java b/reference-adapter/src/main/java/org/egov/ifix/exception/ExceptionAdvise.java new file mode 100644 index 000000000..7da21a528 --- /dev/null +++ b/reference-adapter/src/main/java/org/egov/ifix/exception/ExceptionAdvise.java @@ -0,0 +1,90 @@ +package org.egov.ifix.exception; + +import org.egov.common.contract.response.Error; +import org.egov.common.contract.response.ErrorResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@ControllerAdvice +public class ExceptionAdvise { + + /** + * @param request + * @param exception + * @return + */ + @ExceptionHandler({Exception.class}) + @ResponseBody + public ResponseEntity exceptionHandler(HttpServletRequest request, Exception exception) { + ErrorResponse errorResponse = new ErrorResponse(); + List errorList = new ArrayList<>(); + HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + + try { + if (exception instanceof BindException) { + BindException bindException = (BindException) exception; + errorResponse.setErrors(getBindingErrors(bindException.getBindingResult())); + } else if (exception instanceof HttpCustomException) { + HttpCustomException customException = (HttpCustomException) exception; + Map errorMap = customException.getErrors(); + + if (errorMap != null && !errorMap.isEmpty()) { + for (Map.Entry entry : errorMap.entrySet()) { + Error error = new Error(); + error.setCode((String) entry.getKey()); + error.setMessage((String) entry.getValue()); + errorList.add(error); + } + } else { + Error error = new Error(); + error.setCode(customException.getCode()); + error.setMessage(customException.getMessage()); + errorList.add(error); + } + errorResponse.setErrors(errorList); + httpStatus = customException.getHttpStatus(); + }else { + errorResponse.setErrors(new ArrayList(Collections.singletonList( + new Error(HttpStatus.INTERNAL_SERVER_ERROR.name(), exception.getMessage(), + exception.getLocalizedMessage())))); + } + } catch (Exception e) { + errorResponse.setErrors(new ArrayList(Collections.singletonList( + new Error(HttpStatus.INTERNAL_SERVER_ERROR.name(), "An unhandled exception occurred", + "Exception occur while binding exceptions")))); + } + + return new ResponseEntity(errorResponse, httpStatus); + } + + + /** + * @param bindingResult + * @return + */ + private List getBindingErrors(BindingResult bindingResult) { + List errors = new ArrayList<>(); + List objectErrors = bindingResult.getAllErrors(); + + for (ObjectError objectError : objectErrors) { + Error error = new Error(); + String[] codes = objectError.getCodes(); + error.setCode(codes[0]); + error.setMessage(objectError.getDefaultMessage()); + errors.add(error); + } + return errors; + } +} diff --git a/reference-adapter/src/main/java/org/egov/ifix/exception/GenericCustomException.java b/reference-adapter/src/main/java/org/egov/ifix/exception/GenericCustomException.java new file mode 100644 index 000000000..64c7e1ca0 --- /dev/null +++ b/reference-adapter/src/main/java/org/egov/ifix/exception/GenericCustomException.java @@ -0,0 +1,27 @@ +package org.egov.ifix.exception; + +import lombok.Data; + +import java.util.Map; + +@Data +public class GenericCustomException extends RuntimeException{ + private String code; + private String message; + private Map errors; + + public GenericCustomException(String code, String message, Map errors) { + this.code = code; + this.message = message; + this.errors = errors; + } + + public GenericCustomException(String code, String message) { + this.code = code; + this.message = message; + } + + public GenericCustomException(Map errors) { + this.errors = errors; + } +} diff --git a/reference-adapter/src/main/java/org/egov/ifix/exception/HttpCustomException.java b/reference-adapter/src/main/java/org/egov/ifix/exception/HttpCustomException.java new file mode 100644 index 000000000..ef140c063 --- /dev/null +++ b/reference-adapter/src/main/java/org/egov/ifix/exception/HttpCustomException.java @@ -0,0 +1,35 @@ +package org.egov.ifix.exception; + +import lombok.Data; +import org.springframework.http.HttpStatus; + +import java.util.Map; + +@Data +public class HttpCustomException extends RuntimeException{ + private String code; + private String message; + private Map errors; + private HttpStatus httpStatus = null; + + public HttpCustomException() { + } + + public HttpCustomException(String code, String message, HttpStatus httpStatus) { + this.code = code; + this.message = message; + this.httpStatus = httpStatus; + } + + public HttpCustomException(Map errors, HttpStatus httpStatus) { + this.message = errors.toString(); + this.errors = errors; + this.httpStatus = httpStatus; + } + public HttpCustomException(Map errors) { + this.message = errors.toString(); + this.errors = errors; + } + + +} diff --git a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/bill/BillEventTypeImpl.java b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/bill/BillEventTypeImpl.java index 51da052ef..112f90bda 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/bill/BillEventTypeImpl.java +++ b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/bill/BillEventTypeImpl.java @@ -10,6 +10,7 @@ import org.egov.ifix.models.EventTypeEnum; import org.egov.ifix.models.FiscalEvent; import org.egov.ifix.service.ChartOfAccountService; +import org.egov.ifix.service.ProjectService; import org.egov.ifix.utils.ApplicationConfiguration; import org.egov.ifix.utils.EventConstants; import org.egov.ifix.utils.MasterDataMappingUtil; @@ -42,8 +43,9 @@ public class BillEventTypeImpl implements EventMapper { private ApplicationConfiguration applicationConfiguration; private ChartOfAccountService chartOfAccountService; - - + + @Autowired + private ProjectService projectService; @Autowired public BillEventTypeImpl(ApplicationConfiguration applicationConfiguration,ChartOfAccountService chartOfAccountService ) { @@ -56,6 +58,9 @@ public BillEventTypeImpl(ApplicationConfiguration applicationConfiguration,Chart public List transformData(JsonObject data) { log.info("Bill event impl executing"); JsonArray entities = data.getAsJsonObject(EventConstants.EVENT).getAsJsonArray(EventConstants.ENTITY); + String clientProjectCode = data.getAsJsonObject(EventConstants.EVENT).get(EventConstants.PROJECT_ID).getAsString(); + String iFixProjectId = projectService.getProjectId(clientProjectCode, data); + List fiscalEvents = new ArrayList(); for (int i = 0; i < entities.size(); i++) { JsonArray demands = entities.get(i).getAsJsonObject().getAsJsonArray(DEMAND); @@ -66,7 +71,8 @@ public List transformData(JsonObject data) { FiscalEvent fiscalEvent = FiscalEvent.builder().tenantId(applicationConfiguration.getTenantId()) .eventType(getEventType()).eventTime(Instant.now().toEpochMilli()) .referenceId(demand.get(REFERANCE_ID).getAsString()).parentEventId(null).parentReferenceId(null) - .amountDetails(getAmounts(demand,data)).build(); + .amountDetails(getAmounts(demand,data)) + .projectId(iFixProjectId).build(); fiscalEvents.add(fiscalEvent); } diff --git a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/demand/DemandEventTypeImpl.java b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/demand/DemandEventTypeImpl.java index 9984b1ee8..c998e4b86 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/demand/DemandEventTypeImpl.java +++ b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/demand/DemandEventTypeImpl.java @@ -10,6 +10,7 @@ import org.egov.ifix.models.EventTypeEnum; import org.egov.ifix.models.FiscalEvent; import org.egov.ifix.service.ChartOfAccountService; +import org.egov.ifix.service.ProjectService; import org.egov.ifix.utils.ApplicationConfiguration; import org.egov.ifix.utils.EventConstants; import org.egov.ifix.utils.MasterDataMappingUtil; @@ -43,6 +44,9 @@ public class DemandEventTypeImpl implements EventMapper { private ChartOfAccountService chartOfAccountService; + @Autowired + private ProjectService projectService; + @Autowired public DemandEventTypeImpl(ApplicationConfiguration applicationConfiguration, ChartOfAccountService chartOfAccountService) { this.applicationConfiguration = applicationConfiguration; @@ -52,6 +56,9 @@ public DemandEventTypeImpl(ApplicationConfiguration applicationConfiguration, Ch @Override public List transformData(JsonObject data) { JsonArray entities = data.getAsJsonObject(EventConstants.EVENT).getAsJsonArray(EventConstants.ENTITY); + String clientProjectCode = data.getAsJsonObject(EventConstants.EVENT).get(EventConstants.PROJECT_ID).getAsString(); + String iFixProjectId = projectService.getProjectId(clientProjectCode, data); + List fiscalEvents = new ArrayList(); for (int i = 0; i < entities.size(); i++) { JsonArray demands = entities.get(i).getAsJsonObject().getAsJsonArray("Demands"); @@ -62,7 +69,8 @@ public List transformData(JsonObject data) { FiscalEvent fiscalEvent = FiscalEvent.builder().tenantId(applicationConfiguration.getTenantId()) .eventType(getEventType()).eventTime(Instant.now().toEpochMilli()) .referenceId(demand.get(REFERANCE_ID).getAsString()).parentEventId(null).parentReferenceId(null) - .amountDetails(getAmounts(demand,data)).build(); + .amountDetails(getAmounts(demand,data)) + .projectId(iFixProjectId).build(); fiscalEvents.add(fiscalEvent); } diff --git a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/payment/PaymentEventTypeImpl.java b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/payment/PaymentEventTypeImpl.java index c7e29dbf8..41de5ea2d 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/payment/PaymentEventTypeImpl.java +++ b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/payment/PaymentEventTypeImpl.java @@ -9,6 +9,7 @@ import org.egov.ifix.models.EventTypeEnum; import org.egov.ifix.models.FiscalEvent; import org.egov.ifix.service.ChartOfAccountService; +import org.egov.ifix.service.ProjectService; import org.egov.ifix.utils.ApplicationConfiguration; import org.egov.ifix.utils.EventConstants; import org.egov.ifix.utils.MasterDataMappingUtil; @@ -47,6 +48,9 @@ public class PaymentEventTypeImpl implements EventMapper { private ChartOfAccountService chartOfAccountService; + @Autowired + private ProjectService projectService; + @Autowired public PaymentEventTypeImpl(ApplicationConfiguration applicationConfiguration, ChartOfAccountService chartOfAccountService) { @@ -63,6 +67,9 @@ public String getEventType() { public List transformData(JsonObject data) { log.info("PAYMENT event impl executing"); JsonArray payments = data.getAsJsonObject(EventConstants.EVENT).getAsJsonArray(EventConstants.ENTITY); + String clientProjectCode = data.getAsJsonObject(EventConstants.EVENT).get(EventConstants.PROJECT_ID).getAsString(); + String iFixProjectId = projectService.getProjectId(clientProjectCode, data); + List fiscalEvents = new ArrayList(); for (int i = 0; i < payments.size(); i++) { JsonObject payment = payments.get(i).getAsJsonObject().getAsJsonObject(PAYMENT); @@ -70,7 +77,8 @@ public List transformData(JsonObject data) { FiscalEvent fiscalEvent = FiscalEvent.builder().tenantId(applicationConfiguration.getTenantId()) .eventType(getEventType()).eventTime(Instant.now().toEpochMilli()) .referenceId(payment.get(REFERANCE_ID).getAsString()).parentEventId(null).parentReferenceId(null) - .amountDetails(getAmounts(payment,data)).build(); + .amountDetails(getAmounts(payment,data)) + .projectId(iFixProjectId).build(); fiscalEvents.add(fiscalEvent); diff --git a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/receipt/ReceiptEventTypeImpl.java b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/receipt/ReceiptEventTypeImpl.java index 4007de759..b34a83545 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/receipt/ReceiptEventTypeImpl.java +++ b/reference-adapter/src/main/java/org/egov/ifix/mapper/impl/receipt/ReceiptEventTypeImpl.java @@ -9,6 +9,7 @@ import org.egov.ifix.models.EventTypeEnum; import org.egov.ifix.models.FiscalEvent; import org.egov.ifix.service.ChartOfAccountService; +import org.egov.ifix.service.ProjectService; import org.egov.ifix.utils.ApplicationConfiguration; import org.egov.ifix.utils.EventConstants; import org.egov.ifix.utils.MasterDataMappingUtil; @@ -44,6 +45,9 @@ public class ReceiptEventTypeImpl implements EventMapper { private ChartOfAccountService chartOfAccountService; + @Autowired + private ProjectService projectService; + @Autowired public ReceiptEventTypeImpl(ApplicationConfiguration applicationConfiguration, ChartOfAccountService chartOfAccountService) { @@ -59,15 +63,21 @@ public String getEventType() { @Override public List transformData(JsonObject data) { log.info("Receipt event impl executing"); - JsonArray payments = data.getAsJsonObject(EventConstants.EVENT).getAsJsonArray(EventConstants.ENTITY); + JsonObject eventJsonObject = data.getAsJsonObject(EventConstants.EVENT); + + JsonArray payments = eventJsonObject.getAsJsonArray(EventConstants.ENTITY); List fiscalEvents = new ArrayList(); for (int i = 0; i < payments.size(); i++) { JsonObject payment = payments.get(i).getAsJsonObject().getAsJsonObject(PAYMENT); + String clientProjectCode = eventJsonObject.get(EventConstants.PROJECT_ID).getAsString(); + String iFixProjectId = projectService.getProjectId(clientProjectCode, data); + FiscalEvent fiscalEvent = FiscalEvent.builder().tenantId(applicationConfiguration.getTenantId()) .eventType(getEventType()).eventTime(Instant.now().toEpochMilli()) .referenceId(payment.get(REFERANCE_ID).getAsString()).parentEventId(null).parentReferenceId(null) - .amountDetails(getAmounts(payment, data)).build(); + .amountDetails(getAmounts(payment, data)) + .projectId(iFixProjectId).build(); fiscalEvents.add(fiscalEvent); diff --git a/reference-adapter/src/main/java/org/egov/ifix/models/FiscalEventRequest.java b/reference-adapter/src/main/java/org/egov/ifix/models/FiscalEventRequest.java index 6696c40c0..78133e9cd 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/models/FiscalEventRequest.java +++ b/reference-adapter/src/main/java/org/egov/ifix/models/FiscalEventRequest.java @@ -11,6 +11,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + /** * Fiscal event request along with request metadata @@ -28,7 +30,7 @@ public class FiscalEventRequest { private RequestHeader requestHeader = null; @JsonProperty("fiscalEvent") - private FiscalEvent fiscalEvent = null; + private List fiscalEvent = null; } diff --git a/reference-adapter/src/main/java/org/egov/ifix/persistance/EventPostingDetail.java b/reference-adapter/src/main/java/org/egov/ifix/persistance/EventPostingDetail.java index 62cf7f728..8067cea0b 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/persistance/EventPostingDetail.java +++ b/reference-adapter/src/main/java/org/egov/ifix/persistance/EventPostingDetail.java @@ -53,6 +53,9 @@ public class EventPostingDetail { @Size(max=4000,min=0) private String error; + + @Size(max=36) + private String projectId; @Lob diff --git a/reference-adapter/src/main/java/org/egov/ifix/service/EventService.java b/reference-adapter/src/main/java/org/egov/ifix/service/EventService.java index 09abfa5f7..f678593e9 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/service/EventService.java +++ b/reference-adapter/src/main/java/org/egov/ifix/service/EventService.java @@ -1,61 +1,75 @@ package org.egov.ifix.service; -import java.util.UUID; - +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.extern.slf4j.Slf4j; +import org.egov.ifix.models.Event; import org.egov.ifix.models.EventRequest; import org.egov.ifix.utils.ApplicationConfiguration; +import org.egov.ifix.exception.HttpCustomException; +import org.egov.ifix.utils.EventConstants; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; -import lombok.extern.slf4j.Slf4j; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; @Service @Slf4j public class EventService { - - private KafkaTemplate kafkaTemplate; - - private ApplicationConfiguration applicationConfiguration; + @Autowired + private KafkaTemplate kafkaTemplate; + @Autowired + private ApplicationConfiguration applicationConfiguration; - - - @Autowired - public EventService(KafkaTemplate kafkaTemplate, - ApplicationConfiguration applicationConfiguration - ) { - this.kafkaTemplate = kafkaTemplate; - this.applicationConfiguration = applicationConfiguration; - } - + public void pushEvent(EventRequest eventRequest) { + validateAndEnrichEventRequest(eventRequest); - public void pushEvent(EventRequest eventRequest) { + log.info(EventConstants.LOG_INFO_PREFIX + "Send request on queue"); - eventRequest.getEvent().setId(UUID.randomUUID().toString()); - log.info("Send request on queue"); - this.kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventRequest); + kafkaTemplate.send(applicationConfiguration.getMapperTopicName(), eventRequest); + } - } + /** + * @param eventRequest + */ + private void validateAndEnrichEventRequest(EventRequest eventRequest) { + Map errorMap = new HashMap<>(); - public KafkaTemplate getKafkaTemplate() { - return kafkaTemplate; - } + if (eventRequest != null && eventRequest.getEvent() != null + && !StringUtils.isEmpty(applicationConfiguration.getMapperTopicName())) { + Event event = eventRequest.getEvent(); + if (event.getEventType() == null){ + errorMap.put(EventConstants.EVENT_TYPE, "Invalid Event Type or it is missing in payload"); + } - public void setKafkaTemplate(KafkaTemplate kafkaTemplate) { - this.kafkaTemplate = kafkaTemplate; - } + if (StringUtils.isEmpty(event.getProjectId())) { + errorMap.put(EventConstants.PROJECT_ID, "Project id is missing in event payload"); + } + if (StringUtils.isEmpty(event.getTenantId())) { + errorMap.put(EventConstants.TENANT_ID, "Tenant id is missing in event payload"); + } - public ApplicationConfiguration getApplicationConfiguration() { - return applicationConfiguration; - } - + if (event.getEntity() == null || event.getEntity().isEmpty()) { + errorMap.put(EventConstants.ENTITY, "Event Entity is missing in payload"); + } + }else { + throw new HttpCustomException(EventConstants.REQUEST_EVENT, "Invalid event request", HttpStatus.BAD_REQUEST); + } - public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) { - this.applicationConfiguration = applicationConfiguration; + if (!errorMap.isEmpty()) { + throw new HttpCustomException(errorMap, HttpStatus.BAD_REQUEST); + }else { + eventRequest.getEvent().setId(UUID.randomUUID().toString()); + } } diff --git a/reference-adapter/src/main/java/org/egov/ifix/utils/ApplicationConfiguration.java b/reference-adapter/src/main/java/org/egov/ifix/utils/ApplicationConfiguration.java index 3d98c1799..d4f6d91b6 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/utils/ApplicationConfiguration.java +++ b/reference-adapter/src/main/java/org/egov/ifix/utils/ApplicationConfiguration.java @@ -15,7 +15,13 @@ public class ApplicationConfiguration { @Value("${kafka.topics.ifix.adaptor.mapper}") private String mapperTopicName; - + + @Value("${kafka.topics.ifix.adaptor.error}") + private String errorTopicName; + + @Value("${kafka.topics.ifix.adaptor.http.error}") + private String httpErrorTopicName; + @Value("${state.goverment.code}") private String tenantId; diff --git a/reference-adapter/src/main/java/org/egov/ifix/utils/EventConstants.java b/reference-adapter/src/main/java/org/egov/ifix/utils/EventConstants.java index ec124b31f..4663ea7f0 100644 --- a/reference-adapter/src/main/java/org/egov/ifix/utils/EventConstants.java +++ b/reference-adapter/src/main/java/org/egov/ifix/utils/EventConstants.java @@ -6,4 +6,15 @@ public class EventConstants { public static final String ENTITY = "entity"; public static final String EVENT_TYPE = "eventType"; + public static final String PAYLOAD = "PAYLOAD"; + public static final String REQUEST_EVENT = "REQUEST_EVENT"; + public static final String LOG_INFO_PREFIX = "<<< INFO >>> "; + public static final String LOG_ERROR_PREFIX = "<<< ERROR >>> "; + public static final String RECOVERABLE_ERROR = "### RECOVERABLE ERROR ###"; + public static final String NON_RECOVERABLE_ERROR = "### NON RECOVERABLE ERROR ###"; + public static final String PROJECT_ID = "projectId"; + public static final String ID = "id"; + public static final String TENANT_ID = "tenantId"; + public static final String NA = "N/A"; + public static final String EMPTY_FISCAL_EVENT = "EMPTY FISCAL EVENT"; } diff --git a/reference-adapter/src/main/resources/application.properties b/reference-adapter/src/main/resources/application.properties index e078708cb..a79c9ef6c 100644 --- a/reference-adapter/src/main/resources/application.properties +++ b/reference-adapter/src/main/resources/application.properties @@ -29,6 +29,8 @@ spring.kafka.listener.missing-topics-fatal=false #----------Localization topic names------------ kafka.topics.ifix.adaptor.mapper=ifix-adaptor-mapper +kafka.topics.ifix.adaptor.error = ifix-adaptor-error +kafka.topics.ifix.adaptor.http.error=ifix-adaptor-http-error #-------------------------------------------------------------- event.config.path=classpath:HeadCodeToCoaMapping.yml #egov.persist.yml.repo.path=file:///home/aniket/Documents/core-services/egov-persister/src/main/resources/pgr-services-persister.yml,file:///home/aniket/Documents/core-services/egov-persister/src/main/resources/apportion-persister.yml,file:///home/aniket/Documents/core-services/egov-persister/src/main/resources/apportion-persister.yml @@ -36,16 +38,25 @@ event.config.path=classpath:HeadCodeToCoaMapping.yml state.goverment.code=pb -#-------------------------------KeyCloak credentials------------------ -keycloak.host=https://ifix-dev.ifix.org.in +#----------------------DEV--KeyCloak credentials------------------------- +#keycloak.host=https://ifix-dev.ifix.org.in +#keycloak.token.url=/auth/realms/ifix/protocol/openid-connect/token +#keycloak.credentials.clientid=mgramseva +#keycloak.credentials.clientsecret=d95bbcdd-a80f-4030-b706-c0adc6723e72 +#keycloak.credentials.granttype=client_credentials + +#----------------------QA-KeyCloak credentials---------------------------- +keycloak.host=https://ifix-qa.ifix.org.in keycloak.token.url=/auth/realms/ifix/protocol/openid-connect/token -keycloak.credentials.clientid=mgramseva -keycloak.credentials.clientsecret=d95bbcdd-a80f-4030-b706-c0adc6723e72 +keycloak.credentials.clientid=mgramseva-qa +keycloak.credentials.clientsecret=c545af74-d134-4e0c-8ed6-927517d0edcb keycloak.credentials.granttype=client_credentials + #------------------------------------------------------- #-----------------------------Ifix Details------------------------- -ifix.host=https://ifix-dev.ifix.org.in +#ifix.host=https://ifix-dev.ifix.org.in +ifix.host=https://ifix-qa.ifix.org.in ifix.event.url=/fiscal-event-service/events/v1/_push ifix.coa.search.url=/ifix-master-data/chartOfAccount/v1/_search ifix.project.search.url=/ifix-master-data/project/v1/_search @@ -62,7 +73,7 @@ spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto= update -spring.jpa.showSql=true +#spring.jpa.showSql=true #----------------------------------Redis ----------------------------- spring.redis.host=127.0.0.1 @@ -71,6 +82,7 @@ spring.redis.port=6379 #------------------------Scheduler config firetime=0 0 0/1 * * ? +#firetime=0 48 11 * * ?