diff --git a/build/build-config.yml b/build/build-config.yml index ea8c9c688..cc9f05230 100644 --- a/build/build-config.yml +++ b/build/build-config.yml @@ -134,3 +134,8 @@ config: dockerfile: "build/maven/Dockerfile" - work-dir: "business-services/egov-apportion-service/src/main/resources/db" image-name: "egov-apportion-service-db" + - name: "builds/mGramSeva/utilities/egov-penalty-schedular" + build: + - work-dir: "utilities/Penalty" + image-name: "egov-penalty-schedular" + dockerfile: "build/maven/Dockerfile" diff --git a/business-services/billing-service/src/main/java/org/egov/demand/model/AggregatedDemandDetailResponse.java b/business-services/billing-service/src/main/java/org/egov/demand/model/AggregatedDemandDetailResponse.java new file mode 100644 index 000000000..7e3d0ebb2 --- /dev/null +++ b/business-services/billing-service/src/main/java/org/egov/demand/model/AggregatedDemandDetailResponse.java @@ -0,0 +1,41 @@ +package org.egov.demand.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class AggregatedDemandDetailResponse { + + private List>> mapOfDemandDetailList; + + private BigDecimal advanceAvailable; + + private BigDecimal advanceAdjusted; + + private BigDecimal remainingAdvance; + + private BigDecimal currentmonthBill; + + private BigDecimal currentMonthPenalty; + + private BigDecimal currentmonthTotalDue; + + private BigDecimal totalAreas; + + private BigDecimal totalAreasWithPenalty; + + private BigDecimal netdue; + + private BigDecimal netDueWithPenalty; + + private BigDecimal totalApplicablePenalty; +} diff --git a/business-services/billing-service/src/main/java/org/egov/demand/service/DemandService.java b/business-services/billing-service/src/main/java/org/egov/demand/service/DemandService.java index 7d717c049..79d43b2eb 100644 --- a/business-services/billing-service/src/main/java/org/egov/demand/service/DemandService.java +++ b/business-services/billing-service/src/main/java/org/egov/demand/service/DemandService.java @@ -39,17 +39,9 @@ */ package org.egov.demand.service; -import static org.egov.demand.util.Constants.ADVANCE_TAXHEAD_JSONPATH_CODE; - import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; +import java.math.RoundingMode; +import java.util.*; import java.util.stream.Collectors; import javax.validation.Valid; @@ -60,16 +52,8 @@ import org.egov.demand.amendment.model.AmendmentUpdate; import org.egov.demand.amendment.model.enums.AmendmentStatus; import org.egov.demand.config.ApplicationProperties; -import org.egov.demand.model.ApportionDemandResponse; -import org.egov.demand.model.AuditDetails; +import org.egov.demand.model.*; import org.egov.demand.model.BillV2.BillStatus; -import org.egov.demand.model.Demand; -import org.egov.demand.model.DemandApportionRequest; -import org.egov.demand.model.DemandCriteria; -import org.egov.demand.model.DemandDetail; -import org.egov.demand.model.DemandHistory; -import org.egov.demand.model.PaymentBackUpdateAudit; -import org.egov.demand.model.UpdateBillCriteria; import org.egov.demand.repository.AmendmentRepository; import org.egov.demand.repository.BillRepositoryV2; import org.egov.demand.repository.DemandRepository; @@ -83,6 +67,10 @@ import org.egov.demand.web.contract.UserSearchRequest; import org.egov.demand.web.contract.factory.ResponseFactory; import org.egov.demand.web.validator.DemandValidatorV1; +import org.egov.mdms.model.MasterDetail; +import org.egov.mdms.model.MdmsCriteria; +import org.egov.mdms.model.MdmsCriteriaReq; +import org.egov.mdms.model.ModuleDetail; import org.egov.tracer.model.CustomException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -96,6 +84,8 @@ import lombok.extern.slf4j.Slf4j; +import static org.egov.demand.util.Constants.*; + @Service @Slf4j public class DemandService { @@ -358,7 +348,7 @@ public List getDemands(DemandCriteria demandCriteria, RequestInfo reques } } } - + if (!CollectionUtils.isEmpty(demands) && !CollectionUtils.isEmpty(payers)) demands = demandEnrichmentUtil.enrichPayer(demands, payers); @@ -373,7 +363,207 @@ public void update(DemandRequest demandRequest, PaymentBackUpdateAudit paymentBa demandRepository.update(demandRequest, paymentBackUpdateAudit); } + public AggregatedDemandDetailResponse getAllDemands(DemandCriteria demandCriteria, RequestInfo requestInfo) { + + //demandValidatorV1.validateDemandCriteria(demandCriteria, requestInfo); + + UserSearchRequest userSearchRequest = null; + List payers = null; + List demands = null; + + String userUri = applicationProperties.getUserServiceHostName() + .concat(applicationProperties.getUserServiceSearchPath()); + + /* + * user type is CITIZEN by default because only citizen can have demand or payer can be null + */ + String citizenTenantId = demandCriteria.getTenantId().split("\\.")[0]; + + /* + * If payer related data is provided first then user search has to be made first followed by demand search + */ + + /* + * If no payer related data given then search demand first then enrich payer(user) data + */ + log.info("demandCriteria::"+demandCriteria); + demands = demandRepository.getDemands(demandCriteria); + log.info("demands:"+demands); + if (!demands.isEmpty()) { + Set payerUuids = demands.stream().filter(demand -> null != demand.getPayer()) + .map(demand -> demand.getPayer().getUuid()).collect(Collectors.toSet()); + + if (!CollectionUtils.isEmpty(payerUuids)) { + + userSearchRequest = UserSearchRequest.builder().requestInfo(requestInfo).uuid(payerUuids).build(); + + payers = mapper.convertValue(serviceRequestRepository.fetchResult(userUri, userSearchRequest), + UserResponse.class).getUser(); + } + } + log.info("demannds::"+demands); + + if (!CollectionUtils.isEmpty(demands) && !CollectionUtils.isEmpty(payers)) + demands = demandEnrichmentUtil.enrichPayer(demands, payers); + + log.info("demannddddds::"+demands); + List>> demandDetailsList = new ArrayList<>(); + + for (Demand demand : demands) { + log.info("Inside demand"); + Map> demandMap = new HashMap<>(); + Long taxPeriodFrom = (Long) demand.getTaxPeriodFrom(); + List demandDetails = demand.getDemandDetails(); + List filteredDemandDetaillist = demandDetails.stream() + .filter(detail -> { + BigDecimal difference = detail.getTaxAmount().subtract(detail.getCollectionAmount()); + return (difference.compareTo(BigDecimal.ZERO)) != 0; + }) // Filter condition + .collect(Collectors.toList()); + log.info("Filtered List:"+filteredDemandDetaillist); + if(!filteredDemandDetaillist.isEmpty()) { + demandMap.put(taxPeriodFrom, filteredDemandDetaillist); + demandDetailsList.add(demandMap); + } + } + log.info("demandDetailsList:"+demandDetailsList); + // Sorting the list of maps based on the key in descending order + List>> sortedDemandDetailsList = demandDetailsList.stream() + .sorted((mapA, mapB) -> { + Long keyA = mapA.keySet().stream().findFirst().orElse(0L); + Long keyB = mapB.keySet().stream().findFirst().orElse(0L); + return keyB.compareTo(keyA); // Descending order + }) + .collect(Collectors.toList()); + + log.info("Sorted map:"+sortedDemandDetailsList); + + List currentMonthDemandDetailList = new ArrayList<>(); + if (!sortedDemandDetailsList.isEmpty()) { + Map> firstMap = sortedDemandDetailsList.get(0); + firstMap.forEach((key, value) -> { + currentMonthDemandDetailList.addAll(value); // Get all details from the first map + }); + } + // Extract RemainingMonthDemandDetailList + List remainingMonthDemandDetailList = new ArrayList<>(); + if (sortedDemandDetailsList.size() > 1) { + for (int i = 1; i < sortedDemandDetailsList.size(); i++) { + Map> map = sortedDemandDetailsList.get(i); + map.forEach((key, value) -> { + remainingMonthDemandDetailList.addAll(value); // Collect all details from the other maps + }); + } + } + log.info("currentMonthDemandDetailList"+currentMonthDemandDetailList); + log.info("remainingMonthDemandDetailList"+remainingMonthDemandDetailList); + BigDecimal currentmonthBill = BigDecimal.ZERO; + BigDecimal currentMonthPenalty = BigDecimal.ZERO; + BigDecimal currentmonthTotalDue = BigDecimal.ZERO; + BigDecimal advanceAvailable = BigDecimal.ZERO; + BigDecimal advanceAdjusted = BigDecimal.ZERO; + BigDecimal remainingAdvance = BigDecimal.ZERO; + BigDecimal totalAreas = BigDecimal.ZERO; + BigDecimal totalAreasWithPenalty = BigDecimal.ZERO; + BigDecimal netdue = BigDecimal.ZERO; + BigDecimal netDueWithPenalty = BigDecimal.ZERO; + BigDecimal totalApplicablePenalty =BigDecimal.ZERO; + + currentmonthBill = currentMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("10101")) // filter by taxHeadCode + .map(dd -> dd.getTaxAmount().subtract(dd.getCollectionAmount())) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + log.info("currentMonthDemandDetailList::::"+currentMonthDemandDetailList); + currentMonthPenalty = currentMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_TIME_PENALTY")) // filter by taxHeadCode + .map(dd -> dd.getTaxAmount().subtract(dd.getCollectionAmount())) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + log.info("currentMonthDemandDetailListafter::::"+currentMonthDemandDetailList); + log.info("currentMonthPenalty" + currentMonthPenalty); + currentmonthTotalDue = currentmonthBill.add(currentMonthPenalty); + if(currentMonthPenalty.equals(BigDecimal.ZERO)) { + List masterDetails = new ArrayList<>(); + MasterDetail masterDetail = new MasterDetail("Penalty", "[?(@)]"); + masterDetails.add(masterDetail); + ModuleDetail moduleDetail = ModuleDetail.builder().moduleName("ws-services-calculation").masterDetails(masterDetails).build(); + List moduleDetails = new ArrayList<>(); + moduleDetails.add(moduleDetail); + MdmsCriteria mdmsCriteria = MdmsCriteria.builder().tenantId(demandCriteria.getTenantId()) + .moduleDetails(moduleDetails) + .build(); + MdmsCriteriaReq mdmsreq = MdmsCriteriaReq.builder().mdmsCriteria(mdmsCriteria).requestInfo(requestInfo).build(); + DocumentContext mdmsData = util.getAttributeValues(mdmsreq); + if (!mdmsData.equals(null)) { + List> paymentMasterDataList = mdmsData.read(PENALTY_PATH_CODE); + Map paymentMasterData = paymentMasterDataList.get(0); + Integer rate = (Integer) paymentMasterData.get("rate"); + String penaltyType = String.valueOf(paymentMasterData.get("type")); + totalApplicablePenalty = currentmonthBill.multiply(new BigDecimal(rate).divide(new BigDecimal(100))); + totalApplicablePenalty = totalApplicablePenalty.setScale(0, RoundingMode.CEILING); + } else { + log.info("MDMS data is Null Penalty not connfigured"); + } + } + + + //Tax headcode for WScharges,legacypenalty,legacyarea + List taxHeadCodesToFilterWithoutPenalty = Arrays.asList("10102", "10201", "10101"); + + // Initialize the variable for the sum of taxAmount - collectedAmount for the filtered tax head codes + totalAreas = remainingMonthDemandDetailList.stream() + .filter(dd -> taxHeadCodesToFilterWithoutPenalty.contains(dd.getTaxHeadMasterCode())) // Filter by tax head codes + .map(dd -> dd.getTaxAmount().subtract(dd.getCollectionAmount())) // Calculate taxAmount - collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); // Sum all results + + BigDecimal penaltyInRemainingMonth= remainingMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_TIME_PENALTY")) // filter by taxHeadCode + .map(dd -> dd.getTaxAmount().subtract(dd.getCollectionAmount())) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + + totalAreasWithPenalty = totalAreas.add(penaltyInRemainingMonth); + + netdue = currentmonthBill.add(totalAreas); + netDueWithPenalty = currentmonthTotalDue.add(totalAreasWithPenalty); + + BigDecimal currentMonthAdvanceAvailable=currentMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_ADVANCE_CARRYFORWARD")) // filter by taxHeadCode + .map(dd -> dd.getTaxAmount()) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal currentMonthAdvanceCollected= currentMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_ADVANCE_CARRYFORWARD")) // filter by taxHeadCode + .map(dd -> dd.getCollectionAmount()) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal remainingMonthAdvanceAvailable = remainingMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_ADVANCE_CARRYFORWARD")) // filter by taxHeadCode + .map(dd -> dd.getTaxAmount()) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal remainingMonthAdvanceCollected= remainingMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_ADVANCE_CARRYFORWARD")) // filter by taxHeadCode + .map(dd -> dd.getCollectionAmount()) // map to the balance between taxAmount and collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); + advanceAvailable = currentMonthAdvanceAvailable.add(remainingMonthAdvanceAvailable); + advanceAdjusted = currentMonthAdvanceCollected.add(remainingMonthAdvanceCollected); + remainingAdvance = advanceAvailable.subtract(advanceAdjusted); + + //BigDecimal currentMonthBill + AggregatedDemandDetailResponse aggregatedDemandDetailResponse = AggregatedDemandDetailResponse.builder() + .mapOfDemandDetailList(sortedDemandDetailsList) + .currentmonthBill(currentmonthBill) + .currentMonthPenalty(currentMonthPenalty) + .currentmonthTotalDue(currentmonthTotalDue) + .totalAreas(totalAreas) + .totalAreasWithPenalty(totalAreasWithPenalty) + .netdue(netdue) + .netDueWithPenalty(netDueWithPenalty) + .advanceAdjusted(advanceAdjusted) + .advanceAvailable(advanceAvailable) + .remainingAdvance(remainingAdvance) + .totalApplicablePenalty(totalApplicablePenalty).build(); + + + return aggregatedDemandDetailResponse; + } /** * Calls the demand apportion API if any advance amoount is available for that comsumer code * @param demandRequest The demand request for create diff --git a/business-services/billing-service/src/main/java/org/egov/demand/util/Constants.java b/business-services/billing-service/src/main/java/org/egov/demand/util/Constants.java index 7ddff20a9..61af1d62f 100644 --- a/business-services/billing-service/src/main/java/org/egov/demand/util/Constants.java +++ b/business-services/billing-service/src/main/java/org/egov/demand/util/Constants.java @@ -20,6 +20,7 @@ public class Constants { public static final String TAXPERIOD_PATH_CODE = "$.MdmsRes.BillingService.TaxPeriod"; public static final String TAXHEADMASTER_PATH_CODE = "$.MdmsRes.BillingService.TaxHeadMaster"; public static final String BUSINESSSERVICE_PATH_CODE = "$.MdmsRes.BillingService.BusinessService.*.code"; + public static final String PENALTY_PATH_CODE = "$.MdmsRes.ws-services-calculation.Penalty"; public static final String BUSINESSSERVICE_MODULE_PATH = "$.MdmsRes.BillingService.BusinessService"; diff --git a/business-services/billing-service/src/main/java/org/egov/demand/web/controller/DemandController.java b/business-services/billing-service/src/main/java/org/egov/demand/web/controller/DemandController.java index 6d3331a67..c4b1e28d6 100644 --- a/business-services/billing-service/src/main/java/org/egov/demand/web/controller/DemandController.java +++ b/business-services/billing-service/src/main/java/org/egov/demand/web/controller/DemandController.java @@ -46,9 +46,7 @@ import org.egov.common.contract.request.RequestInfo; import org.egov.demand.config.ApplicationProperties; -import org.egov.demand.model.Demand; -import org.egov.demand.model.DemandCriteria; -import org.egov.demand.model.DemandHistory; +import org.egov.demand.model.*; import org.egov.demand.producer.Producer; import org.egov.demand.service.DemandService; import org.egov.demand.util.migration.DemandMigration; @@ -162,5 +160,15 @@ public ResponseEntity history(@RequestBody RequestInfoWrapper requestInfoWrap responseInfo(responseFactory.getResponseInfo(requestInfo, HttpStatus.OK)).build(); return new ResponseEntity<>(response, HttpStatus.OK); } + + @PostMapping("_getAggregateDemandDetails") + public ResponseEntity getAggregatedDemandDetails(@RequestBody RequestInfoWrapper requestInfoWrapper, + @ModelAttribute @Valid DemandCriteria demandCriteria) { + + RequestInfo requestInfo = requestInfoWrapper.getRequestInfo(); + + AggregatedDemandDetailResponse demands = demandService.getAllDemands(demandCriteria, requestInfo); + return new ResponseEntity<>(demands, HttpStatus.OK); + } } \ No newline at end of file diff --git a/core-services/egov-notification-sms/src/main/java/org/egov/web/notification/sms/config/SMSProperties.java b/core-services/egov-notification-sms/src/main/java/org/egov/web/notification/sms/config/SMSProperties.java index e039f20e9..df71a4718 100644 --- a/core-services/egov-notification-sms/src/main/java/org/egov/web/notification/sms/config/SMSProperties.java +++ b/core-services/egov-notification-sms/src/main/java/org/egov/web/notification/sms/config/SMSProperties.java @@ -93,7 +93,7 @@ public class SMSProperties { @Value("${save.sms.entity.enabled}") private boolean isSaveSmsEnable; - @Value("#{'${sms.error.codes}'.split(',')}") + @Value("#{'${sms.disabled.tenants.list}'.split(',')}") protected List smsDisabledTenantList; @Setter(AccessLevel.PROTECTED) private List whitelistPatterns; diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/config/WSCalculationConfiguration.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/config/WSCalculationConfiguration.java index 005fa4286..43bd663ba 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/config/WSCalculationConfiguration.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/config/WSCalculationConfiguration.java @@ -1,6 +1,7 @@ package org.egov.wscalculation.config; import java.math.BigDecimal; +import java.math.BigInteger; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -249,5 +250,16 @@ public class WSCalculationConfiguration { @Value("${sms.exclude.tenant}") private String smsExcludeTenant; - + + @Value("${penalty.applicable.in.days}") + private Integer penaltyApplicableDays; + + @Value("${penalty.start.threshold.time}") + private String penaltyStartThresholdTime; + + @Value("${is.penalty.feature.enable}") + private boolean isPenaltyEnabled; + + @Value("${egov.update.demand.add.penalty}") + private String updateAddPenaltytopic; } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/constants/WSCalculationConstant.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/constants/WSCalculationConstant.java index 0427838ae..cd2ca1378 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/constants/WSCalculationConstant.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/constants/WSCalculationConstant.java @@ -184,6 +184,10 @@ public class WSCalculationConstant { public static final String JSONPATH_ROOT_FOR_billingService = "$.MdmsRes.BillingService"; public static final String JSONPATH_ROOT_FOR_Allowed_PAyment = "$.MdmsRes.BillingService.PaymentService"; + public static final String JSONPATH_ROOT_FOR_ws_service_calculator = "$.MdmsRes.ws-services-calculation"; + public static final String JSONPATH_ROOT_FOR_Penalty = "$.MdmsRes.ws-services-calculation.Penalty"; + + public static final String JSON_PATH_ROOT_FOR_Allowed_PAyment = "$.MdmsRes.BillingService.BusinessService"; diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/consumer/DemandGenerationConsumer.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/consumer/DemandGenerationConsumer.java index 0aba61a11..7517b165c 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/consumer/DemandGenerationConsumer.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/consumer/DemandGenerationConsumer.java @@ -16,6 +16,7 @@ import java.util.Set; import java.util.stream.Collectors; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.lang3.StringUtils; import org.egov.common.contract.request.RequestInfo; import org.egov.tracer.model.CustomException; @@ -33,19 +34,7 @@ import org.egov.wscalculation.util.WSCalculationUtil; import org.egov.wscalculation.validator.WSCalculationValidator; import org.egov.wscalculation.validator.WSCalculationWorkflowValidator; -import org.egov.wscalculation.web.models.Action; -import org.egov.wscalculation.web.models.ActionItem; -import org.egov.wscalculation.web.models.BulkDemand; -import org.egov.wscalculation.web.models.CalculationCriteria; -import org.egov.wscalculation.web.models.CalculationReq; -import org.egov.wscalculation.web.models.Category; -import org.egov.wscalculation.web.models.Demand; -import org.egov.wscalculation.web.models.Event; -import org.egov.wscalculation.web.models.EventRequest; -import org.egov.wscalculation.web.models.OwnerInfo; -import org.egov.wscalculation.web.models.Recipient; -import org.egov.wscalculation.web.models.SMSRequest; -import org.egov.wscalculation.web.models.Source; +import org.egov.wscalculation.web.models.*; import org.egov.wscalculation.web.models.users.UserDetailResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.annotation.KafkaListener; @@ -547,4 +536,10 @@ public void generateBulkDemandForULB(HashMap messageData) { } + @KafkaListener(topics = { + "${egov.update.demand.add.penalty}" }, containerFactory = "kafkaListenerContainerFactory") + public void updateAddPenalty(HashMap messageData) { + DemandRequest demandRequest = mapper.convertValue(messageData, DemandRequest.class); + demandService.updateDemandAddPenalty(demandRequest.getRequestInfo(), demandRequest.getDemands()); + } } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/DemandRepository.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/DemandRepository.java index 6b78d5190..e7e0dbb15 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/DemandRepository.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/DemandRepository.java @@ -1,20 +1,27 @@ package org.egov.wscalculation.repository; +import java.math.BigInteger; +import java.util.ArrayList; import java.util.List; +import java.util.Set; +import lombok.extern.slf4j.Slf4j; import org.egov.common.contract.request.RequestInfo; import org.egov.tracer.model.CustomException; import org.egov.wscalculation.config.WSCalculationConfiguration; +import org.egov.wscalculation.repository.builder.DemandQueryBuilder; import org.egov.wscalculation.web.models.Demand; import org.egov.wscalculation.web.models.DemandRequest; import org.egov.wscalculation.web.models.DemandResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.fasterxml.jackson.databind.ObjectMapper; @Repository +@Slf4j public class DemandRepository { @@ -27,6 +34,12 @@ public class DemandRepository { @Autowired private ObjectMapper mapper; + @Autowired + private DemandQueryBuilder queryBuilder; + + @Autowired + private JdbcTemplate jdbcTemplate; + /** * Creates demand @@ -66,5 +79,12 @@ public List updateDemand(RequestInfo requestInfo, List demands){ } } + public List getDemandsToAddPenalty(String tenantId, BigInteger penaltyThresholdTime, Integer penaltyApplicableAfterDays) { + List preparedStmtList = new ArrayList<>(); + String query = queryBuilder.getPenaltyQuery(tenantId, penaltyThresholdTime, penaltyApplicableAfterDays); + log.info("query:"+ query); + return jdbcTemplate.queryForList(query, String.class); + } + } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/builder/DemandQueryBuilder.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/builder/DemandQueryBuilder.java new file mode 100644 index 000000000..d29e92174 --- /dev/null +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/repository/builder/DemandQueryBuilder.java @@ -0,0 +1,46 @@ +package org.egov.wscalculation.repository.builder; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.math.BigInteger; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Set; + +@Component +@Slf4j +public class DemandQueryBuilder { + private final static String selectClause = "SELECT b.demandid FROM egbs_demanddetail_v1 b "; + private final static String subQuery = "SELECT dt.demandid FROM egbs_demand_v1 d LEFT OUTER JOIN egbs_demanddetail_v1 dt ON d.id = dt.demandid AND dt.taxamount > dt.collectionamount " + + "AND dt.taxheadcode = '10101'"+"AND d.status = 'ACTIVE'"; + private final static String firstWhereClause = "WHERE demandid IN (" ; + private final static String secondWhereClause = ") AND b.tenantid = '"; + + private final static String groupByClause = " GROUP BY b.demandid " + + "HAVING COUNT(*) = 1 "; + + public String getPenaltyQuery(String tenantId, BigInteger penaltyThresholdDate, Integer daysToBeSubstracted ) { + //TODO: find out days + long currentTimeMillis = System.currentTimeMillis(); + long tenDaysAgoMillis = Instant.ofEpochMilli(currentTimeMillis) + .minus(daysToBeSubstracted, ChronoUnit.DAYS) + .toEpochMilli(); + String subStringQuery ; + subStringQuery = subQuery + " AND d.tenantid = '"+tenantId+"'" + + " AND d.createdtime < " + tenDaysAgoMillis + " AND d.taxperiodfrom > " + penaltyThresholdDate; + String firstStringWhereClause; + firstStringWhereClause = firstWhereClause + subStringQuery + secondWhereClause + tenantId+"'"+ groupByClause; + String query ; + query = selectClause + firstStringWhereClause; + StringBuilder builder = new StringBuilder(query); + log.info("Query formed :" + builder.toString()); + return builder.toString(); + + } +} diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/service/DemandService.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/service/DemandService.java index e4a03511b..a7efaad06 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/service/DemandService.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/service/DemandService.java @@ -12,33 +12,20 @@ import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.format.TextStyle; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Function; import java.util.stream.Collectors; import javax.validation.Valid; +import io.swagger.models.auth.In; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpStatus; import org.egov.common.contract.request.RequestInfo; import org.egov.common.contract.request.User; -import org.egov.mdms.model.MasterDetail; -import org.egov.mdms.model.MdmsCriteria; -import org.egov.mdms.model.MdmsCriteriaReq; -import org.egov.mdms.model.ModuleDetail; +import org.egov.mdms.model.*; import org.egov.tracer.model.CustomException; import org.egov.wscalculation.config.WSCalculationConfiguration; import org.egov.wscalculation.constants.WSCalculationConstant; @@ -51,28 +38,11 @@ import org.egov.wscalculation.util.WSCalculationUtil; import org.egov.wscalculation.validator.WSCalculationValidator; import org.egov.wscalculation.validator.WSCalculationWorkflowValidator; -import org.egov.wscalculation.web.models.BulkDemand; -import org.egov.wscalculation.web.models.Calculation; -import org.egov.wscalculation.web.models.Category; -import org.egov.wscalculation.web.models.Demand; +import org.egov.wscalculation.web.models.*; import org.egov.wscalculation.web.models.Demand.StatusEnum; -import org.egov.wscalculation.web.models.DemandDetail; -import org.egov.wscalculation.web.models.DemandDetailAndCollection; -import org.egov.wscalculation.web.models.DemandPenaltyResponse; -import org.egov.wscalculation.web.models.DemandRequest; -import org.egov.wscalculation.web.models.DemandResponse; -import org.egov.wscalculation.web.models.GetBillCriteria; -import org.egov.wscalculation.web.models.OwnerInfo; -import org.egov.wscalculation.web.models.Property; -import org.egov.wscalculation.web.models.Recipient; -import org.egov.wscalculation.web.models.RequestInfoWrapper; -import org.egov.wscalculation.web.models.SMSRequest; -import org.egov.wscalculation.web.models.TaxHeadEstimate; -import org.egov.wscalculation.web.models.TaxPeriod; -import org.egov.wscalculation.web.models.WaterConnection; -import org.egov.wscalculation.web.models.WaterConnectionRequest; import org.egov.wscalculation.web.models.users.UserDetailResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; @@ -641,6 +611,19 @@ public List searchDemand(String tenantId, Set consumerCodes, Lon } + public List searchDemandBydemandId(String tenantId, Set demandids, + RequestInfo requestInfo) { + Object result = serviceRequestRepository.fetchResult( + getDemandSearchURLByDemandId(tenantId, demandids), + RequestInfoWrapper.builder().requestInfo(requestInfo).build()); + try { + return mapper.convertValue(result, DemandResponse.class).getDemands(); + } catch (IllegalArgumentException e) { + throw new CustomException("PARSING_ERROR", "Failed to parse response from Demand Search"); + } + + } + /** * Creates demand Search url based on tenantId,businessService, and * @@ -723,6 +706,18 @@ public StringBuilder getDemandSearchURL(String tenantId, Set consumerCod return url; } + public StringBuilder getDemandSearchURLByDemandId(String tenantId, Set demandIds) { + StringBuilder url = new StringBuilder(configs.getBillingServiceHost()); + url.append(configs.getDemandSearchEndPoint()); + url.append("?"); + url.append("tenantId="); + url.append(tenantId); + url.append("&"); + url.append("demandId="); + url.append(StringUtils.join(demandIds, ',')); + log.info("Search demand url:"+url); + return url; + } /** * * @param getBillCriteria Bill Criteria @@ -1408,5 +1403,97 @@ public boolean isOnlinePaymentAllowed(RequestInfo requestInfo, String tenantId) else return true; } + public List getDemandToAddPenalty(String tenantid,BigInteger penaltyThresholdDate,Integer penaltyApplicableAfterDays){ + return demandRepository.getDemandsToAddPenalty(tenantid,penaltyThresholdDate,penaltyApplicableAfterDays); + } + + public ResponseEntity addPenalty(@Valid RequestInfo requestInfo, AddPenaltyCriteria addPenaltyCriteria) { + if(config.isPenaltyEnabled()) { + if (requestInfo.getUserInfo().equals(null)) { + + } + List masterDetails = new ArrayList<>(); + MasterDetail masterDetail = new MasterDetail("Penalty", "[?(@)]"); + masterDetails.add(masterDetail); + ModuleDetail moduleDetail = ModuleDetail.builder().moduleName("ws-services-calculation").masterDetails(masterDetails).build(); + List moduleDetails = new ArrayList<>(); + moduleDetails.add(moduleDetail); + MdmsCriteria mdmsCriteria = MdmsCriteria.builder().tenantId(addPenaltyCriteria.getTenantId()) + .moduleDetails(moduleDetails) + .build(); + Map paymentMasterData = calculatorUtils.getPenaltyMasterForTenantId(addPenaltyCriteria.getTenantId(), mdmsCriteria, requestInfo); + + Integer rate= (Integer) paymentMasterData.get("rate"); + String penaltyType = String.valueOf(paymentMasterData.get("type")); + String penaltySubType = (String) paymentMasterData.get("subType"); + String startingDay = (String) paymentMasterData.get("startingDay"); + Integer applicableAfterDays = (Integer) paymentMasterData.get("applicableAfterDays"); + List demandIds = getDemandToAddPenalty(addPenaltyCriteria.getTenantId(), new BigInteger(config.getPenaltyStartThresholdTime()),applicableAfterDays); + if (rate > 0) { + demandIds.stream().forEach(demandId -> { + Set demandids = new HashSet<>(); + demandids.add(demandId); + List demands = searchDemandBydemandId(addPenaltyCriteria.getTenantId(), demandids, requestInfo); + if (!CollectionUtils.isEmpty(demands)) { + Demand demand = demands.get(0); + Boolean isPenaltyExistForDemand = demand.getDemandDetails().stream().anyMatch(demandDetail -> { + return demandDetail.getTaxHeadMasterCode().equalsIgnoreCase(WSCalculationConstant.WS_TIME_PENALTY); + }); + if (!isPenaltyExistForDemand) { + if (!CollectionUtils.isEmpty(demand.getDemandDetails()) && demand.getDemandDetails().size() == 1) { + demand.setDemandDetails(addTimePenalty(rate, penaltyType, penaltySubType, demand)); + demands.clear(); + demands.add(demand); + DemandRequest demandRequest = DemandRequest.builder().requestInfo(requestInfo).demands(demands).build(); + producer.push(config.getUpdateAddPenaltytopic(), demandRequest); + } + } + } + }); + } else { + return new ResponseEntity<>(org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED); + } + } + return new ResponseEntity<>(org.springframework.http.HttpStatus.ACCEPTED); + } + public List addTimePenalty(Integer rate, String type, String SubType,Demand demand) { + // TODO: if type is fixed annd subtype is curretmonnth than only add penalty + //TODO : check for metered connection also what is taxheadcode + + BigDecimal taxPercentage = BigDecimal.valueOf(Double.valueOf(rate)); + List demandDetailList= demand.getDemandDetails(); + DemandDetail waterChargeDemandDetails = null; + if(!CollectionUtils.isEmpty(demandDetailList)) { + if(demandDetailList.get(0).getTaxHeadMasterCode().equalsIgnoreCase(WSCalculationConstant.WS_CHARGE)){ + //mapper.convertValue(demandDetailList.stream().filter(demandDetail -> demandDetail.getTaxHeadMasterCode().equalsIgnoreCase(WSCalculationConstant.WS_CHARGE)), DemandDetail.class) ; + waterChargeDemandDetails=demandDetailList.get(0); + BigDecimal netPayableAmountWithouttax= waterChargeDemandDetails.getTaxAmount().subtract(waterChargeDemandDetails.getCollectionAmount()); + if(netPayableAmountWithouttax.signum()> 0) { + BigDecimal tax = netPayableAmountWithouttax.multiply(taxPercentage.divide(WSCalculationConstant.HUNDRED)); + //round off to next higest number + tax = roundOffTax(tax); + DemandDetail timeDemandDetail = DemandDetail.builder().demandId(demand.getId()) + .taxHeadMasterCode(WSCalculationConstant.WS_TIME_PENALTY) + .taxAmount(tax) + .collectionAmount(BigDecimal.ZERO) + .tenantId(demand.getTenantId()).build(); + + demandDetailList.add(timeDemandDetail); + } + } + } + return demandDetailList; + + } + + public BigDecimal roundOffTax (BigDecimal tax) { + + // Round the value up to the next highest integer + return tax.setScale(0, RoundingMode.CEILING); + } + + public void updateDemandAddPenalty(RequestInfo requestInfo , List demands) { + demandRepository.updateDemand(requestInfo,demands); + } } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/util/CalculatorUtil.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/util/CalculatorUtil.java index 1381ef966..dc11204fd 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/util/CalculatorUtil.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/util/CalculatorUtil.java @@ -394,5 +394,27 @@ public Map getAllowedPaymentForTenantId(String tenantId, MdmsCri + } + public Map getPenaltyMasterForTenantId(String tenantId, MdmsCriteria mdmsCriteria, RequestInfo requestInfo) { + MdmsCriteriaReq mdmsCriteriaReq = MdmsCriteriaReq.builder().mdmsCriteria(mdmsCriteria).requestInfo(requestInfo).build(); + Object res = serviceRequestRepository.fetchResult(getMdmsSearchUrl(), mdmsCriteriaReq); + if (res == null) { + throw new CustomException("MDMS_ERROR_FOR_BILLING_FREQUENCY", "ERROR IN FETCHING THE ALLOWED PAYMENT FOR TENANTID " + tenantId); + } + log.info("Response", res); + Map mdmsres = JsonPath.read(res, WSCalculationConstant.JSONPATH_ROOT_FOR_mdmsRes); + Map mdmsPenaltyMaster = JsonPath.read(res,WSCalculationConstant.JSONPATH_ROOT_FOR_ws_service_calculator); + if(mdmsres.isEmpty() || mdmsPenaltyMaster.isEmpty()) { + log.info("Inside No MDMS response found for tenantId::::" +tenantId); + String stateLevelTenantId = tenantId.split("\\.")[0]; + mdmsCriteriaReq.getMdmsCriteria().setTenantId(stateLevelTenantId); + res = serviceRequestRepository.fetchResult(getMdmsSearchUrl(), mdmsCriteriaReq); + } + + List> jsonOutput = JsonPath.read(res, WSCalculationConstant.JSONPATH_ROOT_FOR_Penalty); + return jsonOutput.get(0); + + + } } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/controller/CalculatorController.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/controller/CalculatorController.java index ae575b689..b9d2e7b96 100644 --- a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/controller/CalculatorController.java +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/controller/CalculatorController.java @@ -5,17 +5,8 @@ import javax.validation.Valid; -import org.egov.wscalculation.web.models.AdhocTaxReq; -import org.egov.wscalculation.web.models.BulkDemand; -import org.egov.wscalculation.web.models.BulkDemandResponse; -import org.egov.wscalculation.web.models.Calculation; -import org.egov.wscalculation.web.models.CalculationReq; -import org.egov.wscalculation.web.models.CalculationRes; -import org.egov.wscalculation.web.models.Demand; -import org.egov.wscalculation.web.models.DemandPenaltyResponse; -import org.egov.wscalculation.web.models.DemandResponse; -import org.egov.wscalculation.web.models.GetBillCriteria; -import org.egov.wscalculation.web.models.RequestInfoWrapper; +import org.egov.common.contract.request.RequestInfo; +import org.egov.wscalculation.web.models.*; import org.egov.wscalculation.service.DemandService; import org.egov.wscalculation.service.WSCalculationService; import org.egov.wscalculation.service.WSCalculationServiceImpl; @@ -117,4 +108,11 @@ public ResponseEntity getPenaltyDetails(@RequestBody @Val return new ResponseEntity<>(demandPenaltyResponse, HttpStatus.OK); } + + @PostMapping("/_addPenalty") + public ResponseEntity addPenalty(@RequestBody PenaltyRequest penaltyRequest) { + return demandService.addPenalty(penaltyRequest.getRequestInfo(),penaltyRequest.getAddPenaltyCriteria()); + + } + } diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/AddPenaltyCriteria.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/AddPenaltyCriteria.java new file mode 100644 index 000000000..4b065e591 --- /dev/null +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/AddPenaltyCriteria.java @@ -0,0 +1,19 @@ +package org.egov.wscalculation.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AddPenaltyCriteria { + + @JsonProperty("tenantId") + private String tenantId; +} diff --git a/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/PenaltyRequest.java b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/PenaltyRequest.java new file mode 100644 index 000000000..c4ae96440 --- /dev/null +++ b/municipal-services/ws-calculator/src/main/java/org/egov/wscalculation/web/models/PenaltyRequest.java @@ -0,0 +1,20 @@ +package org.egov.wscalculation.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; +import org.egov.common.contract.request.RequestInfo; +import org.springframework.validation.annotation.Validated; + +@Validated +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Builder +public class PenaltyRequest { + @JsonProperty("requestInfo") + private RequestInfo requestInfo; + + @JsonProperty("addPenaltyCriteria") + private AddPenaltyCriteria addPenaltyCriteria; +} diff --git a/municipal-services/ws-calculator/src/main/resources/application.properties b/municipal-services/ws-calculator/src/main/resources/application.properties index 9b8bb7a36..d983bd124 100644 --- a/municipal-services/ws-calculator/src/main/resources/application.properties +++ b/municipal-services/ws-calculator/src/main/resources/application.properties @@ -146,3 +146,9 @@ sms.demand.enabled: true sms.payment.link.enabled: true sms.bill.download.enabled: true sms.exclude.tenant="pb.testing" + +#Penalty Config +penalty.start.threshold.time= 10000000 +penalty.applicable.in.days= 10 +is.penalty.feature.enable= true +egov.update.demand.add.penalty= egov-update-demand-add-penalty \ No newline at end of file diff --git a/utilities/Penalty/pom.xml b/utilities/Penalty/pom.xml new file mode 100644 index 000000000..81b5f02eb --- /dev/null +++ b/utilities/Penalty/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.6 + + + org.egov + egov-penalty-schedular + 1.0-SNAPSHOT + egov-penalty-schedular + egov-penalty schedular + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.postgresql + postgresql + runtime + ${postgresql.version} + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.egov.services + ifix-services-common + 0.0.1-SNAPSHOT + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + com.google.code.gson + gson + 2.9.0 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + javax.xml.bind + jaxb-api + 2.3.1 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.11.4 + + + com.vladmihalcea + hibernate-types-52 + 2.3.5 + + + org.egov + mdms-client + 0.0.4-SNAPSHOT + compile + + + org.flywaydb + flyway-core + + + org.bouncycastle + bcprov-jdk15on + 1.69 + + + org.apache.cxf + cxf-rt-frontend-jaxws + 3.5.0 + + + org.apache.cxf + cxf-rt-transports-http + 3.5.0 + + + org.projectlombok + lombok + 1.18.22 + compile + + + + + + repo.digit.org + eGov ERP Releases Repository + https://nexus-repo.digit.org/nexus/content/repositories/releases/ + + + repo.digit.org.snapshots + eGov ERP Releases Repository + https://nexus-repo.digit.org/nexus/content/repositories/snapshots/ + + + repo.digit.org.public + eGov Public Repository Group + https://nexus-repo.digit.org/nexus/content/groups/public/ + + + + + + 1.8 + 2.17.1 + 42.3.3 + + + \ No newline at end of file diff --git a/utilities/Penalty/src/main/java/org/egov/PenaltySchedularApplication.java b/utilities/Penalty/src/main/java/org/egov/PenaltySchedularApplication.java new file mode 100644 index 000000000..735daa26e --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/PenaltySchedularApplication.java @@ -0,0 +1,12 @@ +package org.egov; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +public class PenaltySchedularApplication { + public static void main(String[] args) { + SpringApplication.run(PenaltySchedularApplication.class, args); + } +} \ No newline at end of file diff --git a/utilities/Penalty/src/main/java/org/egov/config/PenaltyShedularConfiguration.java b/utilities/Penalty/src/main/java/org/egov/config/PenaltyShedularConfiguration.java new file mode 100644 index 000000000..86fc7b389 --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/config/PenaltyShedularConfiguration.java @@ -0,0 +1,49 @@ +package org.egov.config; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.List; +import java.util.TimeZone; + +@Component +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PenaltyShedularConfiguration { + + @Value("${app.timezone}") + private String timeZone; + + @PostConstruct + public void initialize() { + TimeZone.setDefault(TimeZone.getTimeZone(timeZone)); + } + + //egov-mdms + @Value("${egov.mdms.host}") + private String egovMdmsHost; + + @Value("${egov.mdms.search.endpoint}") + private String egovMdmsSearchUrl; + + @Value("${mdms.event.tenantId}") + private String tenantId; + + @Value("${egov.wscalculator.host}") + private String egovWaterCalculatorHost; + + @Value("${egov.wscalculator.url}") + private String egovWaterCalculatorSearchUrl; + + @Value("${egov.penalty.enabled}") + private boolean isPenaltyEnabled; + + @Value("#{'${egov.penalty.enabled.division.code.list}'.split(',')}") + private List penaltyEnabledDivisionlist; +} + diff --git a/utilities/Penalty/src/main/java/org/egov/job/PenaltySchedularJob.java b/utilities/Penalty/src/main/java/org/egov/job/PenaltySchedularJob.java new file mode 100644 index 000000000..bb80024a5 --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/job/PenaltySchedularJob.java @@ -0,0 +1,83 @@ +package org.egov.job; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.egov.common.contract.request.RequestInfo; +import org.egov.config.PenaltyShedularConfiguration; +import org.egov.model.AddPenaltyCriteria; +import org.egov.model.PenaltyRequest; +import org.egov.model.Tenant; +import org.egov.util.MDMSClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@Slf4j +@AllArgsConstructor +@NoArgsConstructor +public class PenaltySchedularJob implements ApplicationRunner { + + @Autowired + private MDMSClient mdmsClient; + + @Autowired + private PenaltyShedularConfiguration adapterConfiguration; + + @Autowired + private RestTemplate restTemplate; + + @Override + public void run(ApplicationArguments args) throws Exception { + + try { + List tenantList = mdmsClient.getTenants(); + tenantList=tenantList.stream().filter( + tenant -> { + return adapterConfiguration.getPenaltyEnabledDivisionlist().contains(tenant.getDivisionCode()); + }).collect(Collectors.toList()); + + System.out.println(tenantList.size()); + + tenantList.stream().forEach(tenant -> { + + addPenaltyEventToWaterCalculator(AddPenaltyCriteria.builder().tenantId(tenant.getCode()).build()); + + }); + + } catch (Exception e) { + log.info("Exception occurred while running PenaltySchedularJob", e); + } + } + + public void addPenaltyEventToWaterCalculator(AddPenaltyCriteria penaltyCriteria) { + PenaltyRequest penaltyRequest = PenaltyRequest.builder().requestInfo(RequestInfo.builder().build()).addPenaltyCriteria(penaltyCriteria).build(); + log.info("Posting request to add Penalty for tenantid:" +penaltyCriteria.getTenantId()); + log.info("Penalty Request", penaltyRequest); + if (penaltyCriteria.getTenantId() != null) { + try { + restTemplate.put(getWaterConnnectionAddPennanltyUrl(), penaltyRequest); + + log.info("Posted request to add Penalty for tenant:" + penaltyCriteria.getTenantId()); + } catch (RestClientException e) { + log.info("Error while calling to water calculator service for tenant :" + penaltyCriteria.getTenantId() + " ERROR MESSAGE:" + e.getMessage(), e.getCause()); + } + } + } + + /** + * @return - return iFix event publish url + */ + public String getWaterConnnectionAddPennanltyUrl() { + return (adapterConfiguration.getEgovWaterCalculatorHost() + adapterConfiguration.getEgovWaterCalculatorSearchUrl()); + } + + +} diff --git a/utilities/Penalty/src/main/java/org/egov/model/AddPenaltyCriteria.java b/utilities/Penalty/src/main/java/org/egov/model/AddPenaltyCriteria.java new file mode 100644 index 000000000..954d5a20a --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/model/AddPenaltyCriteria.java @@ -0,0 +1,18 @@ +package org.egov.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AddPenaltyCriteria { + private String limit; + private String offset; + private String tenantId; + private List tenantids; +} diff --git a/utilities/Penalty/src/main/java/org/egov/model/PenaltyRequest.java b/utilities/Penalty/src/main/java/org/egov/model/PenaltyRequest.java new file mode 100644 index 000000000..47d6724c8 --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/model/PenaltyRequest.java @@ -0,0 +1,21 @@ +package org.egov.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; +import org.egov.common.contract.request.RequestInfo; +import org.springframework.validation.annotation.Validated; + +@Validated +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Builder +public class PenaltyRequest { + @JsonProperty("requestInfo") + private RequestInfo requestInfo; + + @JsonProperty("addPenaltyCriteria") + private AddPenaltyCriteria addPenaltyCriteria; +} + diff --git a/utilities/Penalty/src/main/java/org/egov/model/Tenant.java b/utilities/Penalty/src/main/java/org/egov/model/Tenant.java new file mode 100644 index 000000000..4c1516740 --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/model/Tenant.java @@ -0,0 +1,14 @@ +package org.egov.model; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Tenant { + private String code; + private String divisionCode; + private String divisionName; +} diff --git a/utilities/Penalty/src/main/java/org/egov/util/MDMSClient.java b/utilities/Penalty/src/main/java/org/egov/util/MDMSClient.java new file mode 100644 index 000000000..542af33cd --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/util/MDMSClient.java @@ -0,0 +1,101 @@ +package org.egov.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.minidev.json.JSONArray; +import org.egov.common.contract.request.RequestInfo; +import org.egov.config.PenaltyShedularConfiguration; +import org.egov.mdms.model.*; +import org.egov.model.Tenant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Component +@Slf4j +@AllArgsConstructor +@NoArgsConstructor +public class MDMSClient { + + @Autowired + private PenaltyShedularConfiguration adapterConfiguration; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private ObjectMapper objectMapper; + + private List tenantids = null; + + @PostConstruct + protected void loadTenantsFromMdms() { + try { + MasterDetail masterDetail = MasterDetail.builder().name(PenaltySchedularConstant.MDMS_TENANT_MASTER_NAME).build(); + ModuleDetail moduleDetail = ModuleDetail.builder().moduleName(PenaltySchedularConstant.MDMS_MODULE_NAME) + .masterDetails(Arrays.asList(masterDetail)).build(); + + MdmsCriteria mdmsCriteria = MdmsCriteria.builder().tenantId(adapterConfiguration.getTenantId()) + .moduleDetails(Arrays.asList(moduleDetail)).build(); + + MdmsCriteriaReq mdmsCriteriaReq = MdmsCriteriaReq.builder().requestInfo(RequestInfo.builder().build()) + .mdmsCriteria(mdmsCriteria).build(); + + //header + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + //request + HttpEntity request = new HttpEntity<>(mdmsCriteriaReq, headers); + + ResponseEntity response = + restTemplate.postForEntity(adapterConfiguration.getEgovMdmsHost() + adapterConfiguration.getEgovMdmsSearchUrl(), + request, MdmsResponse.class); + + MdmsResponse mdmsResponse = null; + if (response != null && response.getBody() != null) { + mdmsResponse = response.getBody(); + }else { + return; + } + + if (mdmsResponse != null && (mdmsResponse.getMdmsRes() == null || mdmsResponse.getMdmsRes().isEmpty())) { + log.info("Tenants file is missing in mdms!!"); + } else { + if (mdmsResponse.getMdmsRes().get(PenaltySchedularConstant.MDMS_MODULE_NAME) != null && mdmsResponse.getMdmsRes().get(PenaltySchedularConstant.MDMS_MODULE_NAME) + .get(PenaltySchedularConstant.MDMS_TENANT_MASTER_NAME) != null) { + JSONArray tenantResponse = mdmsResponse.getMdmsRes().get(PenaltySchedularConstant.MDMS_MODULE_NAME) + .get(PenaltySchedularConstant.MDMS_TENANT_MASTER_NAME); + + ObjectReader reader = objectMapper.readerFor(objectMapper.getTypeFactory().constructCollectionType(List.class, + Tenant.class)); + + tenantids = reader.readValue(tenantResponse.toString()); + } + + } + + } catch (IOException e) { + log.info("Error occurred while getting the account to gp mapping from MDMS", e); + } + } + + public List getTenants() { + if (tenantids == null || tenantids.isEmpty()) { + return Collections.emptyList(); + } + return tenantids; + } +} diff --git a/utilities/Penalty/src/main/java/org/egov/util/PenaltySchedularConstant.java b/utilities/Penalty/src/main/java/org/egov/util/PenaltySchedularConstant.java new file mode 100644 index 000000000..536ffb10e --- /dev/null +++ b/utilities/Penalty/src/main/java/org/egov/util/PenaltySchedularConstant.java @@ -0,0 +1,7 @@ +package org.egov.util; + +public class PenaltySchedularConstant { + public static final String MDMS_MODULE_NAME = "tenant"; + public static final String MDMS_TENANT_MASTER_NAME = "tenants"; + +} \ No newline at end of file diff --git a/utilities/Penalty/src/main/resources/application.properties b/utilities/Penalty/src/main/resources/application.properties new file mode 100644 index 000000000..9ec915bf1 --- /dev/null +++ b/utilities/Penalty/src/main/resources/application.properties @@ -0,0 +1,17 @@ +app.timezone=UTC + +#-----Disable the Web application----------------------# +spring.main.web-application-type=none + +#----------------MDMS config---------------------# +egov.mdms.host=http://localhost:8094 +egov.mdms.search.endpoint=/mdms-v2/v1/_search +mdms.event.tenantId=pb +egov.wscalculator.host=http://localhost:8083 +egov.wscalculator.url=/ws-calculator/waterCalculator/_addPenalty +egov.penalty.enabled= true +egov.penalty.enabled.division.code.list=DIV1038,DIV1001 + +#----------------aspect Configurations----------------# +timestamp.logging.enabled=true +