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 index 523548b53..dd554e5a8 100644 --- 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 @@ -29,10 +29,14 @@ public class AggregatedDemandDetailResponse { private BigDecimal currentmonthTotalDue; + private BigDecimal currentmonthRoundOff; + private BigDecimal totalAreas; private BigDecimal totalAreasWithPenalty; + private BigDecimal totalAreasRoundOff; + private BigDecimal netdue; private BigDecimal netDueWithPenalty; 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 acc049f64..47728c986 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 @@ -720,11 +720,20 @@ public int compare(Demand d1, Demand d2) { BigDecimal netdue = BigDecimal.ZERO; BigDecimal netDueWithPenalty = BigDecimal.ZERO; BigDecimal totalApplicablePenalty =BigDecimal.ZERO; + BigDecimal currentmonthRoundOff=BigDecimal.ZERO; + BigDecimal totalAreasRoundOff=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); + + currentmonthRoundOff = currentMonthDemandDetailList.stream() + .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_Round_Off")) // 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("currentmonthRoundOff::::"+currentmonthRoundOff); + log.info("currentMonthDemandDetailList::::"+currentMonthDemandDetailList); currentMonthPenalty = currentMonthDemandDetailList.stream() .filter(dd -> dd.getTaxHeadMasterCode().equals("WS_TIME_PENALTY")) // filter by taxHeadCode @@ -732,7 +741,8 @@ public int compare(Demand d1, Demand d2) { .reduce(BigDecimal.ZERO, BigDecimal::add); log.info("currentMonthDemandDetailListafter::::"+currentMonthDemandDetailList); log.info("currentMonthPenalty" + currentMonthPenalty); - currentmonthTotalDue = currentmonthBill.add(currentMonthPenalty); + currentmonthTotalDue = currentmonthBill.add(currentMonthPenalty).add(currentmonthRoundOff); + log.info("currentmonthTotalDue" + currentmonthTotalDue); if(currentMonthPenalty.equals(BigDecimal.ZERO)) { List masterDetails = new ArrayList<>(); MasterDetail masterDetail = new MasterDetail("Penalty", "[?(@)]"); @@ -759,7 +769,13 @@ public int compare(Demand d1, Demand d2) { //Tax headcode for WScharges,legacypenalty,legacyarea - List taxHeadCodesToFilterWithoutPenalty = Arrays.asList("10102", "10201", "10101"); + List taxHeadCodesToFilterWithoutPenalty = Arrays.asList("10102", "10201", "10101","WS_Round_Off"); + + // Initialize the variable for the sum of taxAmount - collectedAmount specifically for WS_Round_Off + totalAreasRoundOff = remainingMonthDemandDetailList.stream() + .filter(dd -> "WS_Round_Off".equals(dd.getTaxHeadMasterCode())) // Filter specifically for WS_Round_Off + .map(dd -> dd.getTaxAmount().subtract(dd.getCollectionAmount())) // Calculate taxAmount - collectedAmount + .reduce(BigDecimal.ZERO, BigDecimal::add); // Sum all results // Initialize the variable for the sum of taxAmount - collectedAmount for the filtered tax head codes totalAreas = remainingMonthDemandDetailList.stream() @@ -799,7 +815,7 @@ public int compare(Demand d1, Demand d2) { if(remainingAdvance !=BigDecimal.ZERO && currentmonthBill !=BigDecimal.ZERO && advanceAdjusted.equals(BigDecimal.ZERO)) { } - netdue = currentmonthBill.add(totalAreas).add(remainingAdvance); + netdue = currentmonthBill.add(totalAreas).add(remainingAdvance).add(currentmonthRoundOff); netDueWithPenalty = currentmonthTotalDue.add(totalAreasWithPenalty).add(remainingAdvance); //BigDecimal currentMonthBill @@ -808,8 +824,10 @@ public int compare(Demand d1, Demand d2) { .currentmonthBill(currentmonthBill) .currentMonthPenalty(currentMonthPenalty) .currentmonthTotalDue(currentmonthTotalDue) + .currentmonthRoundOff(currentmonthRoundOff) .totalAreas(totalAreas) .totalAreasWithPenalty(totalAreasWithPenalty) + .totalAreasRoundOff(totalAreasRoundOff) .netdue(netdue) .netDueWithPenalty(netDueWithPenalty) .advanceAdjusted(advanceAdjusted) diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/EgovEmployeeApplication.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/EgovEmployeeApplication.java index df126f012..aca1d4b2f 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/EgovEmployeeApplication.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/EgovEmployeeApplication.java @@ -55,6 +55,10 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import javax.net.ssl.*; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + @SpringBootApplication @ComponentScan(basePackages = { "org.egov.hrms", "org.egov.hrms.web.controllers" , "org.egov.hrms.config"}) @Import(TracerConfiguration.class) @@ -76,7 +80,36 @@ public ObjectMapper getObjectMapper() { return objectMapper; } + public static void trustSelfSignedSSL() { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + ctx.init(null, new TrustManager[]{tm}, null); + SSLContext.setDefault(ctx); + + // Disable hostname verification + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { + return true; + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + public static void main(String[] args) { + trustSelfSignedSSL(); SpringApplication.run(EgovEmployeeApplication.class, args); } } diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/config/PropertiesManager.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/config/PropertiesManager.java index e9adc7abb..99ad9107a 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/config/PropertiesManager.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/config/PropertiesManager.java @@ -125,4 +125,39 @@ public class PropertiesManager { @Value("${egov.hrms.max.pagination.limit}") public Integer hrmsMaxLimit; + + // FuzzyConfigs + @Value("${hrms.search.pagination.default.limit}") + public Long defaultLimit; + + @Value("${hrms.search.pagination.default.offset}") + public Long defaultOffset; + + @Value("${hrms.search.pagination.max.search.limit}") + public Long searchLimit; + + @Value("${hrms.search.pagination.max.search.limit}") + private Long maxSearchLimit; + + @Value("${hrms.fuzzy.search.is.wildcard}") + private Boolean isSearchWildcardBased; + + @Value("${hrms.search.name.fuziness}") + private String nameFuziness; + + // es configs + @Value("${elasticsearch.host}") + private String esHost; + + @Value("${hrms.es.index}") + private String esPTIndex; + + @Value("${elasticsearch.search.endpoint}") + private String esSearchEndpoint; + + @Value("${egov.es.username}") + private String userName; + + @Value("${egov.es.password}") + private String password; } \ No newline at end of file diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/ElasticSearchRepository.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/ElasticSearchRepository.java new file mode 100644 index 000000000..767262ca1 --- /dev/null +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/ElasticSearchRepository.java @@ -0,0 +1,84 @@ +package org.egov.hrms.repository; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.egov.hrms.config.PropertiesManager; +import org.egov.hrms.web.contract.EmployeeSearchCriteria; +import org.egov.tracer.model.CustomException; +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.Repository; +import org.springframework.web.client.RestTemplate; + +import java.util.Base64; +import java.util.List; + +@Slf4j +@Repository +public class ElasticSearchRepository { + private PropertiesManager config; + + private FuzzySearchQueryBuilder queryBuilder; + + private RestTemplate restTemplate; + + private ObjectMapper mapper; + + @Autowired + public ElasticSearchRepository(PropertiesManager config, FuzzySearchQueryBuilder queryBuilder, RestTemplate restTemplate, ObjectMapper mapper) { + this.config = config; + this.queryBuilder = queryBuilder; + this.restTemplate = restTemplate; + this.mapper = mapper; + } + + public Object fuzzySearchEmployees(EmployeeSearchCriteria criteria, List uuids) { + + + String url = getESURL(); + + String searchQuery = queryBuilder.getFuzzySearchQuery(criteria, uuids); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", getESEncodedCredentials()); + headers.setContentType(MediaType.APPLICATION_JSON); + log.info("Headers: " + headers.toString()); + HttpEntity requestEntity = new HttpEntity<>(searchQuery, headers); + ResponseEntity response = null; + try { + response = restTemplate.postForEntity(url, requestEntity, Object.class); + + } catch (Exception e) { + e.printStackTrace(); + throw new CustomException("ES_ERROR","Failed to fetch data from ES"); + } + + return response.getBody(); + + } + + + /** + * Generates elasticsearch search url from application properties + * + * @return + */ + private String getESURL() { + + StringBuilder builder = new StringBuilder(config.getEsHost()); + builder.append(config.getEsPTIndex()); + builder.append(config.getEsSearchEndpoint()); + + return builder.toString(); + } + + public String getESEncodedCredentials() { + String credentials = config.getUserName() + ":" + config.getPassword(); + byte[] credentialsBytes = credentials.getBytes(); + byte[] base64CredentialsBytes = Base64.getEncoder().encode(credentialsBytes); + return "Basic " + new String(base64CredentialsBytes); + } +} diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeQueryBuilder.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeQueryBuilder.java index 8812b302b..61f55da39 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeQueryBuilder.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeQueryBuilder.java @@ -105,7 +105,7 @@ public String paginationClause(EmployeeSearchCriteria criteria, StringBuilder bu pagination = pagination.replace("$offset", "0"); if(null != criteria.getLimit()){ - Integer limit = criteria.getLimit() + criteria.getOffset(); + Long limit = criteria.getLimit() + criteria.getOffset(); pagination = pagination.replace("$limit", limit.toString()); } else diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeRepository.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeRepository.java index 6062a0733..d0c8c10a0 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeRepository.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/EmployeeRepository.java @@ -70,7 +70,7 @@ public List fetchEmployees(EmployeeSearchCriteria criteria, RequestInf return employees; } - private List fetchEmployeesforAssignment(EmployeeSearchCriteria criteria, RequestInfo requestInfo) { + public List fetchEmployeesforAssignment(EmployeeSearchCriteria criteria, RequestInfo requestInfo) { List employeesIds = new ArrayList<>(); List preparedStmtList = new ArrayList<>(); String query = queryBuilder.getAssignmentSearchQuery(criteria, preparedStmtList); diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/FuzzySearchQueryBuilder.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/FuzzySearchQueryBuilder.java new file mode 100644 index 000000000..ef80e1369 --- /dev/null +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/repository/FuzzySearchQueryBuilder.java @@ -0,0 +1,160 @@ +package org.egov.hrms.repository; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; +import org.egov.hrms.config.PropertiesManager; +import org.egov.hrms.web.contract.EmployeeSearchCriteria; +import org.egov.tracer.model.CustomException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.util.CollectionUtils; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +@Repository +@Slf4j +public class FuzzySearchQueryBuilder { + private ObjectMapper mapper; + + private PropertiesManager config; + + @Autowired + public FuzzySearchQueryBuilder(ObjectMapper mapper, PropertiesManager config) { + this.mapper = mapper; + this.config = config; + } + + private static final String BASE_QUERY = "{\n" + + " \"from\": {{OFFSET}},\n" + + " \"size\": {{LIMIT}},\n" + + " \"sort\": {\n" + + " \"_score\": {\n" + + " \"order\": \"desc\"\n" + + " }\n" + + " },\n" + + " \"query\": {\n" + + " }\n" + + "}"; + + private static final String fuzzyQueryTemplate = "{\n" + + " \"match\": {\n" + + " \"{{VAR}}\": {\n" + + " \"query\": \"{{PARAM}}\",\n" + + " \"fuzziness\": \"{{FUZZINESS}}\"\n" + + " }\n" + + " }\n" + + " }"; + + private static final String wildCardQueryTemplate = "{\n" + + " \"query_string\": {\n" + + " \"default_field\": \"{{VAR}}\",\n" + + " \"query\": \"*{{PARAM}}*\"\n" + + " }\n" + + " }"; + + private static final String filterTemplate = "\"filter\": { " + + " }"; + + public String getFuzzySearchQuery(EmployeeSearchCriteria criteria, List ids) { + String finalQuery = ""; + + try { + String baseQuery = addPagination(criteria); + JsonNode node = mapper.readTree(baseQuery); + ObjectNode insideMatch = (ObjectNode)node.get("query"); + List fuzzyClauses = new LinkedList<>(); + + if(criteria.getName() != null){ + fuzzyClauses.add(getInnerNode(criteria.getName(),"Data.user.name",config.getNameFuziness())); + } + + ArrayNode tenantIdArray = mapper.createArrayNode(); + tenantIdArray.add(criteria.getTenantId()); + ObjectNode tenantIdFilter = mapper.createObjectNode(); + tenantIdFilter.putPOJO("terms", mapper.createObjectNode().putPOJO("Data.tenantId.keyword", tenantIdArray)); + fuzzyClauses.add(tenantIdFilter); + + if (criteria.getRoles() != null && !criteria.getRoles().isEmpty()) { + ArrayNode roleArray = mapper.createArrayNode(); + for (String role : criteria.getRoles()) { + ObjectNode roleNode = mapper.createObjectNode(); + roleNode.put("term", mapper.createObjectNode().put("Data.user.roles.code.keyword", role)); + roleArray.add(roleNode); + } + ObjectNode rolesBoolNode = mapper.createObjectNode(); + rolesBoolNode.putPOJO("bool", mapper.createObjectNode().putPOJO("should", roleArray)); + fuzzyClauses.add(rolesBoolNode); + + ObjectNode boolQuery = mapper.createObjectNode(); + boolQuery.putPOJO("must", fuzzyClauses); + insideMatch.putPOJO("bool", boolQuery); + finalQuery = mapper.writeValueAsString(node); + } + } catch (Exception e) { + log.error("ES_ERROR", e); + throw new CustomException("JSONNODE_ERROR", "Failed to build JSON query for fuzzy search"); + } + + log.info("finalQuery {}",finalQuery); + return finalQuery; + } + + private JsonNode getInnerNode(String param, String var, String fuziness) throws JsonProcessingException { + + String template; + if(config.getIsSearchWildcardBased()) + template = wildCardQueryTemplate; + else + template = fuzzyQueryTemplate; + String innerQuery = template.replace("{{PARAM}}",getEscapedString(param)); + innerQuery = innerQuery.replace("{{VAR}}",var); + + if(!config.getIsSearchWildcardBased()) + innerQuery = innerQuery.replace("{{FUZZINESS}}", fuziness); + + JsonNode innerNode = mapper.readTree(innerQuery); + return innerNode; + } + + private String addPagination(EmployeeSearchCriteria criteria) { + + Long limit = config.getDefaultLimit(); + Long offset = config.getDefaultOffset(); + + if (criteria.getLimit() != null && criteria.getLimit() <= config.getMaxSearchLimit()) + limit = criteria.getLimit(); + + if (criteria.getLimit() != null && criteria.getLimit() > config.getMaxSearchLimit()) + limit = config.getMaxSearchLimit(); + + if (criteria.getOffset() != null) + offset = criteria.getOffset(); + + String baseQuery = BASE_QUERY.replace("{{OFFSET}}", offset.toString()); + baseQuery = baseQuery.replace("{{LIMIT}}", limit.toString()); + + return baseQuery; + } + + /** + * Escapes special characters in given string + * @param inputString + * @return + */ + private String getEscapedString(String inputString){ + final String[] metaCharacters = {"\\","/","^","$","{","}","[","]","(",")",".","*","+","?","|","<",">","-","&","%"}; + for (int i = 0 ; i < metaCharacters.length ; i++) { + if (inputString.contains(metaCharacters[i])) { + inputString = inputString.replace(metaCharacters[i], "\\\\" + metaCharacters[i]); + } + } + return inputString; + } +} diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/service/EmployeeService.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/service/EmployeeService.java index b8d5bbb0d..f105cc7c7 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/service/EmployeeService.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/service/EmployeeService.java @@ -104,6 +104,9 @@ public class EmployeeService { @Autowired private ObjectMapper objectMapper; + @Autowired + private FuzzySearchService fuzzySearchService; + /** * Service method for create employee. Does following: * 1. Sets ids to all the objects using idgen service. @@ -138,11 +141,17 @@ public EmployeeResponse create(EmployeeRequest employeeRequest) { * @return */ public EmployeeResponse search(EmployeeSearchCriteria criteria, RequestInfo requestInfo) { + boolean userChecked = false; /*if(null == criteria.getIsActive() || criteria.getIsActive()) criteria.setIsActive(true); else criteria.setIsActive(false);*/ + if(criteria.getName()!=null){ + List fuzzyEmployees = fuzzySearchService.getEmployees(requestInfo, criteria); + return EmployeeResponse.builder().responseInfo(factory.createResponseInfoFromRequestInfo(requestInfo, true)) + .employees(fuzzyEmployees).build(); + } Map mapOfUsers = new HashMap(); if(!StringUtils.isEmpty(criteria.getPhone()) || !CollectionUtils.isEmpty(criteria.getRoles())) { Map userSearchCriteria = new HashMap<>(); diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/service/FuzzySearchService.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/service/FuzzySearchService.java new file mode 100644 index 000000000..e8e464343 --- /dev/null +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/service/FuzzySearchService.java @@ -0,0 +1,120 @@ +package org.egov.hrms.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.JsonPath; +import lombok.extern.slf4j.Slf4j; +import org.egov.common.contract.request.RequestInfo; +import org.egov.hrms.config.PropertiesManager; +import org.egov.hrms.model.Employee; +import org.egov.hrms.repository.ElasticSearchRepository; +import org.egov.hrms.repository.EmployeeRepository; +import org.egov.hrms.utils.HRMSConstants; +import org.egov.hrms.utils.HRMSUtils; +import org.egov.hrms.web.contract.EmployeeSearchCriteria; +import org.egov.hrms.web.contract.User; +import org.egov.hrms.web.contract.UserResponse; +import org.egov.tracer.model.CustomException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.egov.hrms.utils.HRMSConstants.ES_DATA_PATH; + +@Slf4j +@Service +public class FuzzySearchService { + @Autowired + private ElasticSearchRepository elasticSearchRepository; + @Autowired + private ObjectMapper mapper; + @Autowired + private EmployeeRepository employeeRepository; + @Autowired + private PropertiesManager config; + @Autowired + private UserService userService; + @Autowired + private HRMSUtils hrmsUtils; + + + public List getEmployees(RequestInfo requestInfo, EmployeeSearchCriteria criteria) { + + if(criteria.getTenantId() == null) + { criteria.setTenantId(config.getStateLevelTenantId()); } + + List idsFromDB = employeeRepository.fetchEmployeesforAssignment(criteria,requestInfo); + +// if(CollectionUtils.isEmpty(idsFromDB)) +// return new LinkedList<>(); + + validateFuzzySearchCriteria(criteria); + + Object esResponse = elasticSearchRepository.fuzzySearchEmployees(criteria, idsFromDB); + + Map> tenantIdToEmpId = getTenantIdToEmpIdMap(esResponse); + + List employees = new LinkedList<>(); + + for (Map.Entry> entry : tenantIdToEmpId.entrySet()) { + String tenantId = entry.getKey(); + Set empIds = entry.getValue(); + List empList = new ArrayList<>(empIds); + + EmployeeSearchCriteria employeeSearchCriteria = EmployeeSearchCriteria.builder().tenantId(tenantId).codes(empList).build(); + + employees.addAll(employeeRepository.fetchEmployees(employeeSearchCriteria, requestInfo)); + Set uuids = employees.stream().map(Employee::getUuid).collect(Collectors.toSet()); + Map map = new HashMap<>(); + map.put(HRMSConstants.HRMS_USER_SEARCH_CRITERA_UUID,uuids); + UserResponse userResponse = userService.getUser(requestInfo, map); + log.info("userResponse {}",userResponse); + List users = userResponse.getUser(); + hrmsUtils.enrichOwner(users, employees); + } + + return employees; + } + private void validateFuzzySearchCriteria(EmployeeSearchCriteria criteria){ + + if(criteria.getName() == null) + throw new CustomException("INVALID_SEARCH_CRITERIA","The search criteria is invalid"); + + } + private Map> getTenantIdToEmpIdMap(Object esResponse) { + + List> data; + Map> tenantIdToEmpIds = new LinkedHashMap<>(); + + + try { + data = JsonPath.read(esResponse, ES_DATA_PATH); + + + if (!CollectionUtils.isEmpty(data)) { + + for (Map map : data) { + + String tenantId = JsonPath.read(map, "$.tenantData.code"); + String empId = JsonPath.read(map, "$.code"); + if (tenantIdToEmpIds.containsKey(tenantId)) + tenantIdToEmpIds.get(tenantId).add(empId); + else { + Set empIds = new HashSet<>(); + empIds.add(empId); + tenantIdToEmpIds.put(tenantId, empIds); + } + + } + + } + + } catch (Exception e) { + throw new CustomException("PARSING_ERROR", "Failed to extract employeeIds from es response"); + } + + return tenantIdToEmpIds; + } +} diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSConstants.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSConstants.java index 645f6f288..994ee578d 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSConstants.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSConstants.java @@ -53,4 +53,11 @@ public class HRMSConstants { public static final String HRMS_USER_SERACH_CRITERIA_USERTYPE = "EMPLOYEE"; public static final String HRMS_USER_SERACH_CRITERIA_USERTYPE_CODE = "userType"; + // Fuzzy Search + public static final String ES_DATA_PATH = "$..Data"; + + public static final String ES_DATA_TENANTID_PATH = "$.tenantData.code"; + + public static final String ES_DATA_PROPERTYID_PATH = "$.propertyId"; + } diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSUtils.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSUtils.java index d9a9f1c8f..64e768b7f 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSUtils.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/utils/HRMSUtils.java @@ -1,14 +1,20 @@ package org.egov.hrms.utils; import java.security.SecureRandom; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; +import lombok.extern.slf4j.Slf4j; +import org.egov.hrms.model.Employee; import org.egov.hrms.web.contract.EmployeeSearchCriteria; +import org.egov.hrms.web.contract.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +@Slf4j @Service public class HRMSUtils { @@ -61,4 +67,19 @@ public boolean isAssignmentSearchReqd(EmployeeSearchCriteria criteria) { return (! CollectionUtils.isEmpty(criteria.getPositions()) || null != criteria.getAsOnDate() || !CollectionUtils.isEmpty(criteria.getDepartments()) || !CollectionUtils.isEmpty(criteria.getDesignations())); } + + public void enrichOwner(List users, List employees) { + + Map uuidToUserMap = new HashMap<>(); + users.forEach(user -> uuidToUserMap.put(user.getUuid(), user)); + + employees.forEach(employee -> { + User user = uuidToUserMap.get(employee.getUuid()); + if (user == null) { + log.info("USER SEARCH ERROR: The user with UUID : \"" + employee.getUuid() + "\" for the employee with Id \"" + employee.getId() + "\" is not present in user search response"); + } else { + employee.setUser(user); + } + }); + } } diff --git a/business-services/egov-hrms/src/main/java/org/egov/hrms/web/contract/EmployeeSearchCriteria.java b/business-services/egov-hrms/src/main/java/org/egov/hrms/web/contract/EmployeeSearchCriteria.java index eed0dd147..61915301c 100644 --- a/business-services/egov-hrms/src/main/java/org/egov/hrms/web/contract/EmployeeSearchCriteria.java +++ b/business-services/egov-hrms/src/main/java/org/egov/hrms/web/contract/EmployeeSearchCriteria.java @@ -56,9 +56,11 @@ public class EmployeeSearchCriteria { public String phone; - public Integer offset; + public Long offset; - public Integer limit; + public Long limit; + + private String name; public boolean isCriteriaEmpty(EmployeeSearchCriteria criteria) { diff --git a/business-services/egov-hrms/src/main/resources/application.properties b/business-services/egov-hrms/src/main/resources/application.properties index 71a102711..2804bb707 100644 --- a/business-services/egov-hrms/src/main/resources/application.properties +++ b/business-services/egov-hrms/src/main/resources/application.properties @@ -1,18 +1,18 @@ #---------------------------- DATABASE CONFIGURATIONS -----------------------------# spring.datasource.driver-class-name=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://localhost:5432/egov_hrms +spring.datasource.url=jdbc:postgresql://localhost:5432/demo spring.datasource.username=postgres -spring.datasource.password=postgres +spring.datasource.password=123 #----------------------------- FLYWAY CONFIGURATIONS ------------------------------# -spring.flyway.url=jdbc:postgresql://localhost:5432/egov_hrms +spring.flyway.url=jdbc:postgresql://localhost:5432/demo spring.flyway.user=postgres -spring.flyway.password=postgres -#spring.flyway.table=hr_employee_schema_version +spring.flyway.password=123 +spring.flyway.table=hr_employee_schema_version spring.flyway.baseline-on-migrate=true spring.flyway.outOfOrder=true spring.flyway.locations=classpath:/db/migration/main,db/migration/seed -spring.flyway.enabled=true +spring.flyway.enabled=false #--------------------------- PATH & PORT CONFIGURATIONS ---------------------------# server.contextPath=/egov-hrms @@ -73,10 +73,30 @@ egov.hrms.default.pwd.length=8 open.search.enabled.roles=SUPERUSER egov.pwd.allowed.special.characters=@#$% +#FuzzySearch +hrms.search.pagination.default.limit=50 +hrms.search.pagination.default.offset=0 +hrms.search.pagination.max.search.limit=5000 +hrms.fuzzy.search.is.wildcard=true +hrms.search.name.fuziness=2 + +#Elastic serach Properties +elasticsearch.host=http://elasticsearch-data.es-cluster:9200 + +elasticsearch.search.endpoint=/_search +egov.es.username=elastic +egov.es.password=EQYBhZhfrXeOA5IIqiHHCSlN +hrms.es.index=hrmsindex + #------------------------------ KAFKA CONFIGURATIONS ------------------------------# # KAFKA SERVER CONFIGURATIONS -spring.kafka.bootstrap.servers=localhost:9092 +#spring.kafka.bootstrap.servers=localhost:9092 spring.kafka.consumer.properties.spring.json.use.type.headers=false +kafka.enabled=false +spring.kafka.bootstrap.servers=none +spring.kafka.consumer.enable-auto-commit=false +spring.kafka.producer.enabled=false +spring.profiles.active=local # SPRING KAFKA CONSUMER CONFIGURATIONS spring.kafka.consumer.value-deserializer=org.egov.tracer.kafka.deserializer.HashMapDeserializer @@ -106,4 +126,4 @@ logging.pattern.console=%clr(%X{CORRELATION_ID:-}) %clr(%d{yyyy-MM-dd HH:mm:ss.S log4j.logger.org.springframework.jdbc.core = TRACE state.level.tenant.id=pb -sms.user.creation.enabled=true \ No newline at end of file +sms.user.creation.enabled=true diff --git a/frontend/mgramseva/lib/components/dashboard/bills_table.dart b/frontend/mgramseva/lib/components/dashboard/bills_table.dart index c0836879c..996cbcb9b 100644 --- a/frontend/mgramseva/lib/components/dashboard/bills_table.dart +++ b/frontend/mgramseva/lib/components/dashboard/bills_table.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:horizontal_data_table/horizontal_data_table.dart'; +import 'package:mgramseva/utils/constants/i18_key_constants.dart'; import 'package:mgramseva/utils/localization/application_localizations.dart'; import 'package:mgramseva/utils/models.dart'; import 'package:mgramseva/widgets/scroll_parent.dart'; @@ -147,64 +148,119 @@ class _BillsTable extends State { //if greater than 28 characters } + String getCurrentRoutePath(BuildContext context) { + final currentRoute = ModalRoute.of(context)!; + return currentRoute.settings.name ?? ''; +} + Widget _generateFirstColumnRow(BuildContext context, int index) { + return LayoutBuilder(builder: (context, constraints) { + bool showLeadger = getCurrentRoutePath(context) == "/home/householdRegister"; var data = widget.tableData[index].tableRow.first; + return ScrollParent( widget.scrollController, - InkWell( - onTap: () { - if (data.callBack != null) { - data.callBack!(data); - } - }, - child: Container( - decoration: BoxDecoration( - border: Border( - left: tableCellBorder, - bottom: tableCellBorder, - right: tableCellBorder, - )), - child: Text( - ApplicationLocalizations.of(context) - .translate(widget.tableData[index].tableRow.first.label), - style: widget.tableData[index].tableRow.first.style ?? - TextStyle(color: Theme.of(context).primaryColor), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + InkWell( + onTap: () { + if (data.callBack != null) { + data.callBack!(data); + } + }, + child: Container( + decoration: BoxDecoration( + border: Border( + left: tableCellBorder, + bottom: tableCellBorder, + right: tableCellBorder, + )), + child: Text( + ApplicationLocalizations.of(context).translate( + widget.tableData[index].tableRow.first.label), + style: widget.tableData[index].tableRow.first.style ?? + TextStyle(color: Theme.of(context).primaryColor), + ), + width: showLeadger ? widget.leftColumnWidth * 0.55 : widget.leftColumnWidth, + height: + widget.tableData[index].tableRow.first.label.length > 28 + ? columnRowIncreasedHeight(index) + : columnRowFixedHeight, + padding: + EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + ), ), - width: widget.leftColumnWidth, - height: widget.tableData[index].tableRow.first.label.length > 28 - ? columnRowIncreasedHeight(index) - : columnRowFixedHeight, - padding: EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), - alignment: Alignment.centerLeft, - ), + if(showLeadger) + Tooltip( + message: '${i18.dashboard.LEDGER_REPORTS}', + + child: IconButton(onPressed: () { + if (data.iconButtonCallBack != null) { + data.iconButtonCallBack!(data); + } + }, icon: Icon(Icons.insert_chart_outlined)), + ) + ], )); }); } Widget _generateColumnRow( BuildContext context, int index, String input, constraints, - {TextStyle? style}) { - return Container( - child: Row( - children: [ - Expanded( - child: Text( - ApplicationLocalizations.of(context).translate(input), - style: style, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ) - ], - ), - width: widget.leftColumnWidth, - height: widget.tableData[index].tableRow.first.label.length > 28 - ? columnRowIncreasedHeight(index) - : columnRowFixedHeight, - padding: EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), - alignment: Alignment.centerLeft, - ); + {TextStyle? style, int? i}) { + var data = widget.tableData[index].tableRow[i ?? 0]; + if (i != null) { + return InkWell( + onTap: () { + data.callBack!(data); + }, + child: Container( + child: Row( + children: [ + Expanded( + child: Text( + ApplicationLocalizations.of(context).translate(input), + style: style, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ) + ], + ), + width: widget.leftColumnWidth, + height: widget.tableData[index].tableRow.first.label.length > 28 + ? columnRowIncreasedHeight(index) + : columnRowFixedHeight, + padding: EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + ), + ); + } else { + return Container( + child: Row( + children: [ + Expanded( + child: Text( + ApplicationLocalizations.of(context).translate(input), + style: style, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ) + ], + ), + width: widget.leftColumnWidth, + height: widget.tableData[index].tableRow.first.label.length > 28 + ? columnRowIncreasedHeight(index) + : columnRowFixedHeight, + padding: EdgeInsets.only(left: 17, right: 5, top: 6, bottom: 6), + alignment: Alignment.centerLeft, + ); + } } Widget _generateRightHandSideColumnRow(BuildContext context, int index) { @@ -213,9 +269,13 @@ class _BillsTable extends State { return LayoutBuilder(builder: (context, constraints) { var list = []; for (int i = 1; i < data.tableRow.length; i++) { - list.add(_generateColumnRow( - context, index, data.tableRow[i].label, constraints, - style: data.tableRow[i].style)); + + list.add( + _generateColumnRow( + context, index, data.tableRow[i].label, constraints, + style: data.tableRow[i].style), + ); + } return Container( color: index % 2 == 0 ? const Color(0xffEEEEEE) : Colors.white, diff --git a/frontend/mgramseva/lib/components/house_connection_and_bill/new_consumer_bill.dart b/frontend/mgramseva/lib/components/house_connection_and_bill/new_consumer_bill.dart index 80fb993a6..31643fca6 100644 --- a/frontend/mgramseva/lib/components/house_connection_and_bill/new_consumer_bill.dart +++ b/frontend/mgramseva/lib/components/house_connection_and_bill/new_consumer_bill.dart @@ -243,10 +243,15 @@ class NewConsumerBillState extends State { houseHoldProvider.isfirstdemand) getLabelText( i18.common.CORE_ADVANCE_ADJUSTED, + double.parse(CommonProvider .getAdvanceAdjustedAmount( widget - .demandList)) <= + .demandList)) == 0 ? "₹ ${houseHoldProvider.aggDemandItems?.remainingAdvance}" : + double.parse(CommonProvider + .getAdvanceAdjustedAmount( + widget + .demandList)) < 0 ? "₹ ${double.parse(CommonProvider.getAdvanceAdjustedAmount(widget.demandList))}" : '- ₹${double.parse(CommonProvider.getAdvanceAdjustedAmount(widget.demandList))}', @@ -462,6 +467,8 @@ class NewConsumerBillState extends State { .CreatePDF( houseHoldProvider.createPDFBody, houseHoldProvider.createPDFPrams) .then((value) async { + + commonProvider.getFileFromPDFBillService( { "BillAndDemand": { diff --git a/frontend/mgramseva/lib/main.dart b/frontend/mgramseva/lib/main.dart index 8a12efb3d..ab8cbc08e 100644 --- a/frontend/mgramseva/lib/main.dart +++ b/frontend/mgramseva/lib/main.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:io'; import 'dart:isolate'; import 'dart:ui'; - // import 'package:dart_ping_ios/dart_ping_ios.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_core/firebase_core.dart'; diff --git a/frontend/mgramseva/lib/model/demand/demand_list.dart b/frontend/mgramseva/lib/model/demand/demand_list.dart index 93f894ffe..bacd07f51 100644 --- a/frontend/mgramseva/lib/model/demand/demand_list.dart +++ b/frontend/mgramseva/lib/model/demand/demand_list.dart @@ -143,6 +143,8 @@ class AggragateDemandDetails { double? currentMonthPenalty; @JsonKey(name: "currentmonthTotalDue") double? currentmonthTotalDue; + @JsonKey(name: "currentmonthRoundOff") + double? currentmonthRoundOff; @JsonKey(name: "totalAreas") double? totalAreas; @JsonKey(name: "totalAreasWithPenalty") diff --git a/frontend/mgramseva/lib/model/demand/demand_list.g.dart b/frontend/mgramseva/lib/model/demand/demand_list.g.dart index fa1596193..b94e57d19 100644 --- a/frontend/mgramseva/lib/model/demand/demand_list.g.dart +++ b/frontend/mgramseva/lib/model/demand/demand_list.g.dart @@ -142,6 +142,8 @@ AggragateDemandDetails _$AggragateDemandDetailsFromJson( ..currentMonthPenalty = (json['currentMonthPenalty'] as num?)?.toDouble() ..currentmonthTotalDue = (json['currentmonthTotalDue'] as num?)?.toDouble() + ..currentmonthRoundOff = + (json['currentmonthRoundOff'] as num?)?.toDouble() ..totalAreas = (json['totalAreas'] as num?)?.toDouble() ..totalAreasWithPenalty = (json['totalAreasWithPenalty'] as num?)?.toDouble() @@ -174,6 +176,7 @@ Map _$AggragateDemandDetailsToJson( 'currentmonthBill': instance.currentmonthBill, 'currentMonthPenalty': instance.currentMonthPenalty, 'currentmonthTotalDue': instance.currentmonthTotalDue, + 'currentmonthRoundOff': instance.currentmonthRoundOff, 'totalAreas': instance.totalAreas, 'totalAreasWithPenalty': instance.totalAreasWithPenalty, 'netdue': instance.netdue, diff --git a/frontend/mgramseva/lib/model/reports/leadger_report.dart b/frontend/mgramseva/lib/model/reports/leadger_report.dart new file mode 100644 index 000000000..c0549bba7 --- /dev/null +++ b/frontend/mgramseva/lib/model/reports/leadger_report.dart @@ -0,0 +1,165 @@ +class LedgerReport { + final List? ledgerReport; + final String? tenantName; + final String? financialYear; + final LeadgeResponseInfo? responseInfo; + + LedgerReport({ + this.ledgerReport, + this.tenantName, + this.financialYear, + this.responseInfo, + }); + + factory LedgerReport.fromJson(Map json) { + return LedgerReport( + ledgerReport: (json['ledgerReport'] as List?) + ?.map((e) => LedgerData.fromJson(e)) + .toList(), + tenantName: json['tenantName'] as String?, + financialYear: json['financialYear'] as String?, + responseInfo: LeadgeResponseInfo.fromJson(json['responseInfo']), + ); + } +} + +class LedgerData { + final Map? months; + LedgerData({this.months}); + factory LedgerData.fromJson(Map json) { + final monthData = {}; + json.forEach((key, value) { + monthData[key] = MonthData.fromJson(value); + }); + return LedgerData(months: monthData); + } +} + +class MonthData { + final LeadgerDemand? demand; + final List? payment; + final num? totalPaymentInMonth; + final num? totalBalanceLeftInMonth; + + MonthData( + {this.demand, + this.payment, + this.totalPaymentInMonth, + this.totalBalanceLeftInMonth}); + + factory MonthData.fromJson(Map json) { + return MonthData( + demand: LeadgerDemand.fromJson(json['demand']), + payment: (json['payment'] as List?) + ?.map((e) => LeadgerPayment.fromJson(e)) + .toList(), + totalPaymentInMonth: json['totalPaymentInMonth'] as num?, + totalBalanceLeftInMonth: json['totalBalanceLeftInMonth'] as num?, + ); + } +} + +class LeadgerDemand { + final String? consumerName; + final String? connectionNo; + final String? oldConnectionNo; + final String? userId; + final String? month; + final int? demandGenerationDate; + final String? code; + final num? monthlyCharges; + final num? penalty; + final num? totalForCurrentMonth; + final num? previousMonthBalance; + final num? totalDues; + final int? dueDateOfPayment; + final int? penaltyAppliedOnDate; + + LeadgerDemand({ + this.consumerName = "", + this.connectionNo, + this.oldConnectionNo = "", + this.userId = "", + this.month, + this.demandGenerationDate, + this.code = "", + this.monthlyCharges, + this.penalty, + this.totalForCurrentMonth, + this.previousMonthBalance, + this.totalDues, + this.dueDateOfPayment, + this.penaltyAppliedOnDate, + }); + + factory LeadgerDemand.fromJson(Map json) { + return LeadgerDemand( + consumerName: json['consumerName'] as String?, + connectionNo: json['connectionNo'] as String?, + oldConnectionNo: json['oldConnectionNo'] as String?, + userId: json['userId'] as String?, + month: json['month'] as String?, + demandGenerationDate: json['demandGenerationDate'] as int?, + code: json['code'] as String?, + monthlyCharges: json['monthlyCharges'] as num?, + penalty: json['penalty'] as num?, + totalForCurrentMonth: json['totalForCurrentMonth'] as num?, + previousMonthBalance: json['previousMonthBalance'] as num?, + totalDues: json['totalDues'] as num?, + dueDateOfPayment: json['dueDateOfPayment'] as int?, + penaltyAppliedOnDate: json['penaltyAppliedOnDate'] as int?, + ); + } +} + +class LeadgerPayment { + final dynamic paymentCollectionDate; + final String? receiptNo; + final num? amountPaid; + final num? balanceLeft; + + LeadgerPayment({ + this.paymentCollectionDate, + this.receiptNo, + this.amountPaid, + this.balanceLeft, + }); + + factory LeadgerPayment.fromJson(Map json) { + return LeadgerPayment( + paymentCollectionDate: json['paymentCollectionDate'], + receiptNo: json['receiptNo'] as String?, + amountPaid: json['amountPaid'] as num?, + balanceLeft: json['balanceLeft'] as num?, + ); + } +} + +class LeadgeResponseInfo { + final String? apiId; + final String? ver; + final dynamic ts; + final String? resMsgId; + final String? msgId; + final String? status; + + LeadgeResponseInfo({ + this.apiId, + this.ver, + this.ts, + this.resMsgId, + this.msgId, + this.status, + }); + + factory LeadgeResponseInfo.fromJson(Map json) { + return LeadgeResponseInfo( + apiId: json['apiId'] as String?, + ver: json['ver'] as String?, + ts: json['ts'], + resMsgId: json['resMsgId'] as String?, + msgId: json['msgId'] as String?, + status: json['status'] as String?, + ); + } +} diff --git a/frontend/mgramseva/lib/providers/bill_generation_details_provider.dart b/frontend/mgramseva/lib/providers/bill_generation_details_provider.dart index 212fb95a8..28369a513 100644 --- a/frontend/mgramseva/lib/providers/bill_generation_details_provider.dart +++ b/frontend/mgramseva/lib/providers/bill_generation_details_provider.dart @@ -4,12 +4,14 @@ import 'package:flutter/material.dart'; import 'package:mgramseva/model/bill/bill_generation_details/bill_generation_details.dart'; import 'package:mgramseva/model/bill/billing.dart'; import 'package:mgramseva/model/connection/water_connection.dart'; +import 'package:mgramseva/model/demand/demand_list.dart'; import 'package:mgramseva/model/localization/language.dart'; import 'package:mgramseva/model/mdms/connection_type.dart'; import 'package:mgramseva/model/mdms/property_type.dart'; import 'package:mgramseva/model/mdms/tax_head_master.dart'; import 'package:mgramseva/model/mdms/tax_period.dart'; import 'package:mgramseva/model/success_handler.dart'; +import 'package:mgramseva/providers/household_details_provider.dart'; import 'package:mgramseva/repository/bill_generation_details_repo.dart'; import 'package:mgramseva/repository/billing_service_repo.dart'; import 'package:mgramseva/repository/core_repo.dart'; @@ -174,6 +176,7 @@ class BillGenerationProvider with ChangeNotifier { billGenerateDetails.billYear = selectedBillYear; notifyListeners(); } + void clearBillYear() { selectedBillYear = null; billGenerateDetails.billYear = null; @@ -182,6 +185,7 @@ class BillGenerationProvider with ChangeNotifier { selectedBillPeriod = null; notifyListeners(); } + void onChangeOfBillCycle(cycle) { var val = cycle['code']; DateTime result = DateTime.parse(val.toString()); @@ -210,7 +214,7 @@ class BillGenerationProvider with ChangeNotifier { 'consumerCode': bill.consumerCode, 'businessService': bill.businessService, 'tenantId': commonProvider.userDetails?.selectedtenant?.code, - 'connectionType':waterconnection.connectionType + 'connectionType': waterconnection.connectionType }; Navigator.pushNamed(context, Routes.HOUSEHOLD_DETAILS_COLLECT_PAYMENT, arguments: query); @@ -315,32 +319,74 @@ class BillGenerationProvider with ChangeNotifier { '${billList.bill!.first.billNumber.toString()}'), callBack: () => onClickOfCollectPayment(billList.bill!.first, context), - callBackDownload: () => commonProvider - .getFileFromPDFBillService({ - "Bill": [billList.bill!.first] - }, { - "key": waterconnection.connectionType == 'Metered' - ? "ws-bill" - : "ws-bill-nm", - "tenantId": - commonProvider.userDetails!.selectedtenant!.code, - }, billList.bill!.first.mobileNumber, billList.bill!.first, - "Download"), - callBackWhatsApp: () => commonProvider - .getFileFromPDFBillService({ - "Bill": [billList.bill!.first], - }, { - "key": waterconnection.connectionType == 'Metered' - ? "ws-bill" - : "ws-bill-nm", - "tenantId": - commonProvider.userDetails!.selectedtenant!.code, - }, billList.bill!.first.mobileNumber, billList.bill!.first, - "Share"), + callBackDownload: () async { + var hhp = Provider.of( + navigatorKey.currentContext!, + listen: false); + // if (hhp.aggDemandItems == null) { + await BillingServiceRepository().fetchAggregateDemand({ + "tenantId": + commonProvider.userDetails!.selectedtenant!.code, + "consumerCode": + billList.bill?.first.consumerCode.toString(), + "businessService": "WS", + }).then((AggragateDemandDetails? value) { + if (value != null) { + hhp.aggDemandItems = value; + notifyListeners(); + } + }); + // } + return commonProvider.getFileFromPDFBillService({ + "BillAndDemand": { + "Bill": [billList.bill?.first], + "AggregatedDemands": hhp.aggDemandItems + } + }, { + "key": waterconnection.connectionType == 'Metered' + ? "ws-bill-v2" + : "ws-bill-nm-v2", + "tenantId": + commonProvider.userDetails!.selectedtenant!.code, + }, billList.bill!.first.mobileNumber, billList.bill!.first, + "Download"); + }, + callBackWhatsApp: () async { + var hhp = Provider.of( + navigatorKey.currentContext!, + listen: false); + // if (hhp.aggDemandItems == null) { + await BillingServiceRepository().fetchAggregateDemand({ + "tenantId": + commonProvider.userDetails!.selectedtenant!.code, + "consumerCode": + billList.bill?.first.consumerCode.toString(), + "businessService": "WS", + }).then((AggragateDemandDetails? value) { + if (value != null) { + hhp.aggDemandItems = value; + notifyListeners(); + } + }); + // } + return commonProvider.getFileFromPDFBillService({ + "BillAndDemand": { + "Bill": [billList.bill?.first], + "AggregatedDemands": hhp.aggDemandItems + } + }, { + "key": waterconnection.connectionType == 'Metered' + ? "ws-bill-v2" + : "ws-bill-nm-v2", + "tenantId": + commonProvider.userDetails!.selectedtenant!.code, + }, billList.bill!.first.mobileNumber, billList.bill!.first, + "Share"); + }, backButton: true, ); })); - } catch (e) { + } catch (e) { Navigator.pop(context); Navigator.of(context).pushReplacement( new MaterialPageRoute(builder: (BuildContext context) { @@ -357,100 +403,168 @@ class BillGenerationProvider with ChangeNotifier { var rateProvider = Provider.of( navigatorKey.currentContext!, listen: false); - var rate = rateProvider.wcBillingSlabs!.wCBillingSlabs!.where((element) => element.connectionType=='Non_Metered').toList(); - if(selectedBillPeriod!=null){ - showDialog(context: context, builder: (context)=>AlertDialog( - surfaceTintColor: Colors.white, - title: Text('${ApplicationLocalizations.of(context).translate(i18.common.CORE_CONFIRM)}'), - content: Container( - height: 370, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('${ApplicationLocalizations.of(context).translate(i18.demandGenerate.ARE_YOU_SURE_TO_GENERATE_DEMAND_FOR)} "${ApplicationLocalizations.of(context).translate(billGenerateDetails.serviceType!)}" ${ApplicationLocalizations.of(context).translate(i18.demandGenerate.WITH_MINIMUM_CHARGE_OF)} : '), - SizedBox(height: 10,), - FittedBox( - child: DataTable( - border: TableBorder.all( - width: 0.5, borderRadius: BorderRadius.all(Radius.circular(5)), - color: Colors.grey,), columns: [ - DataColumn( - label: Text( - "${ApplicationLocalizations.of(context).translate(i18.searchWaterConnection.CONNECTION_TYPE)}", - style: - TextStyle(color: Colors.black, fontWeight: FontWeight.bold), - )), - DataColumn( - label: Text( - "${ApplicationLocalizations.of(context).translate(i18.common.RATE_PERCENTAGE)}", - style: - TextStyle(color: Colors.black, fontWeight: FontWeight.bold), - )),], rows: [ - ...rate.map((e) => DataRow(cells: [ - DataCell(Text( - "${ApplicationLocalizations.of(context).translate("${e.buildingType}")}")), - DataCell(Text("${e.minimumCharge}")) - ])).toList() - ],), - ), - SizedBox(height: 10,), - Text('${ApplicationLocalizations.of(context).translate(i18.demandGenerate.NO_DEMAND_GEN_WITH_RATE_0)}'), //* Note : No Demand will be generated for the Service Type with rate set to 0. - ], - ), - ), - actions: - (rateProvider.wcBillingSlabs!.wCBillingSlabs!.where((element) => element.connectionType=='Non_Metered').length- rateProvider.wcBillingSlabs!.wCBillingSlabs!.where((element) => element.connectionType=='Non_Metered' && element.minimumCharge==0).length == 0 ) - ? - [TextButton(onPressed: (){ - Navigator.pop(context); - }, child: Text('${ApplicationLocalizations.of(context).translate(i18.consumerReciepts.CLOSE)}'))] - : - [TextButton(onPressed: () async{ - if(rateProvider.wcBillingSlabs!.wCBillingSlabs!.where((element) => element.connectionType=='Non_Metered').length- rateProvider.wcBillingSlabs!.wCBillingSlabs!.where((element) => element.connectionType=='Non_Metered' && element.minimumCharge==0).length == 0 ){ - Navigator.pop(context); - Notifiers.getToastMessage(context, '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.NO_SERVICE_PRESENT_WITH_RATE_MORE_THAN_0)}', 'ERROR'); //No Service type present with rate more than 0. - return; - } - try { - Loaders.showLoadingDialog(context); - var commonProvider = Provider.of( - navigatorKey.currentContext!, - listen: false); - var res2 = { - "tenantId": commonProvider.userDetails!.selectedtenant!.code, - "billingPeriod": selectedBillPeriod - }; - var billResponse2 = await BillGenerateRepository().bulkDemand(res2); - Navigator.pop(context); - String localizationText = getSubtitleText(context); - Navigator.of(context).pushReplacement( - new MaterialPageRoute(builder: (BuildContext context) { - return CommonSuccess(SuccessHandler( - ApplicationLocalizations.of(context) - .translate(i18.demandGenerate.GENERATE_DEMAND_SUCCESS), - localizationText, - i18.common.BACK_HOME, - Routes.BILL_GENERATE, - subHeader: - '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.BILLING_CYCLE_LABEL)}', - subTextFun: () => getLocalizedText(context), - subtitleFun: () => getSubtitleText(context))); - })); - } catch (e) { - Navigator.of(context).pushReplacement( - new MaterialPageRoute(builder: (BuildContext context) { - return ErrorPage(e.toString()); - })); - } - }, child: Text('${ApplicationLocalizations.of(context).translate(i18.common.YES)}')), - TextButton(onPressed: (){ - Navigator.pop(context); - }, child: Text('${ApplicationLocalizations.of(context).translate(i18.common.NO)}')),] - , - )); - }else{ - Notifiers.getToastMessage(context, '${ApplicationLocalizations.of(context).translate(i18.common.SELECT_BILLING_CYCLE)}', 'ERROR'); //Please select billing cycle + var rate = rateProvider.wcBillingSlabs!.wCBillingSlabs! + .where((element) => element.connectionType == 'Non_Metered') + .toList(); + if (selectedBillPeriod != null) { + showDialog( + context: context, + builder: (context) => AlertDialog( + surfaceTintColor: Colors.white, + title: Text( + '${ApplicationLocalizations.of(context).translate(i18.common.CORE_CONFIRM)}'), + content: Container( + height: 370, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.ARE_YOU_SURE_TO_GENERATE_DEMAND_FOR)} "${ApplicationLocalizations.of(context).translate(billGenerateDetails.serviceType!)}" ${ApplicationLocalizations.of(context).translate(i18.demandGenerate.WITH_MINIMUM_CHARGE_OF)} : '), + SizedBox( + height: 10, + ), + FittedBox( + child: DataTable( + border: TableBorder.all( + width: 0.5, + borderRadius: + BorderRadius.all(Radius.circular(5)), + color: Colors.grey, + ), + columns: [ + DataColumn( + label: Text( + "${ApplicationLocalizations.of(context).translate(i18.searchWaterConnection.CONNECTION_TYPE)}", + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold), + )), + DataColumn( + label: Text( + "${ApplicationLocalizations.of(context).translate(i18.common.RATE_PERCENTAGE)}", + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold), + )), + ], + rows: [ + ...rate + .map((e) => DataRow(cells: [ + DataCell(Text( + "${ApplicationLocalizations.of(context).translate("${e.buildingType}")}")), + DataCell(Text("${e.minimumCharge}")) + ])) + .toList() + ], + ), + ), + SizedBox( + height: 10, + ), + Text( + '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.NO_DEMAND_GEN_WITH_RATE_0)}'), //* Note : No Demand will be generated for the Service Type with rate set to 0. + ], + ), + ), + actions: (rateProvider.wcBillingSlabs!.wCBillingSlabs! + .where((element) => + element.connectionType == 'Non_Metered') + .length - + rateProvider.wcBillingSlabs!.wCBillingSlabs! + .where((element) => + element.connectionType == 'Non_Metered' && + element.minimumCharge == 0) + .length == + 0) + ? [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text( + '${ApplicationLocalizations.of(context).translate(i18.consumerReciepts.CLOSE)}')) + ] + : [ + TextButton( + onPressed: () async { + if (rateProvider.wcBillingSlabs!.wCBillingSlabs! + .where((element) => + element.connectionType == + 'Non_Metered') + .length - + rateProvider + .wcBillingSlabs!.wCBillingSlabs! + .where((element) => + element.connectionType == + 'Non_Metered' && + element.minimumCharge == 0) + .length == + 0) { + Navigator.pop(context); + Notifiers.getToastMessage( + context, + '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.NO_SERVICE_PRESENT_WITH_RATE_MORE_THAN_0)}', + 'ERROR'); //No Service type present with rate more than 0. + return; + } + try { + Loaders.showLoadingDialog(context); + var commonProvider = + Provider.of( + navigatorKey.currentContext!, + listen: false); + var res2 = { + "tenantId": commonProvider + .userDetails!.selectedtenant!.code, + "billingPeriod": selectedBillPeriod + }; + var billResponse2 = + await BillGenerateRepository() + .bulkDemand(res2); + Navigator.pop(context); + String localizationText = + getSubtitleText(context); + Navigator.of(context).pushReplacement( + new MaterialPageRoute( + builder: (BuildContext context) { + return CommonSuccess(SuccessHandler( + ApplicationLocalizations.of(context) + .translate(i18.demandGenerate + .GENERATE_DEMAND_SUCCESS), + localizationText, + i18.common.BACK_HOME, + Routes.BILL_GENERATE, + subHeader: + '${ApplicationLocalizations.of(context).translate(i18.demandGenerate.BILLING_CYCLE_LABEL)}', + subTextFun: () => + getLocalizedText(context), + subtitleFun: () => + getSubtitleText(context))); + })); + } catch (e) { + Navigator.of(context).pushReplacement( + new MaterialPageRoute( + builder: (BuildContext context) { + return ErrorPage(e.toString()); + })); + } + }, + child: Text( + '${ApplicationLocalizations.of(context).translate(i18.common.YES)}')), + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: Text( + '${ApplicationLocalizations.of(context).translate(i18.common.NO)}')), + ], + )); + } else { + Notifiers.getToastMessage( + context, + '${ApplicationLocalizations.of(context).translate(i18.common.SELECT_BILLING_CYCLE)}', + 'ERROR'); //Please select billing cycle } } else { autoValidation = true; @@ -499,13 +613,19 @@ class BillGenerationProvider with ChangeNotifier { List getFinancialYearList() { if (languageList?.mdmsRes?.billingService?.taxPeriodList != null) { - CommonMethods.getFilteredFinancialYearList(languageList?.mdmsRes?.billingService?.taxPeriodList ?? []); - languageList?.mdmsRes?.billingService?.taxPeriodList!.sort((a,b)=>a.fromDate!.compareTo(b.fromDate!)); + CommonMethods.getFilteredFinancialYearList( + languageList?.mdmsRes?.billingService?.taxPeriodList ?? + []); + languageList?.mdmsRes?.billingService?.taxPeriodList! + .sort((a, b) => a.fromDate!.compareTo(b.fromDate!)); return (languageList?.mdmsRes?.billingService?.taxPeriodList ?? []) .map((value) { - return value; - }).toList().reversed.toList(); + return value; + }) + .toList() + .reversed + .toList(); } return []; } @@ -521,8 +641,8 @@ class BillGenerationProvider with ChangeNotifier { return []; } - List> getBillingCycle() { - var dates = >[]; + List> getBillingCycle() { + var dates = >[]; if (billGenerateDetails.billYear != null && selectedBillYear != null) { DatePeriod ytd; var fromDate = DateFormats.getFormattedDateToDateTime( @@ -531,26 +651,27 @@ class BillGenerationProvider with ChangeNotifier { var toDate = DateFormats.getFormattedDateToDateTime( DateFormats.timeStampToDate(selectedBillYear.toDate)) as DateTime; - ytd = DatePeriod(fromDate,toDate,DateType.YTD); + ytd = DatePeriod(fromDate, toDate, DateType.YTD); /// Get months based on selected billing year var months = CommonMethods.getPastMonthUntilFinancialYTD(ytd); /// if selected year is future year means all the months will be removed - if(fromDate.year > ytd.endDate.year) months.clear(); + if (fromDate.year > ytd.endDate.year) months.clear(); for (var i = 0; i < months.length; i++) { var prevMonth = months[i].startDate; - Map r = {"code": prevMonth, "name": "${ApplicationLocalizations.of(navigatorKey.currentContext!) - .translate((Constants.MONTHS[prevMonth.month - 1])) + - " - " + - prevMonth.year.toString()}"}; + Map r = { + "code": prevMonth, + "name": + "${ApplicationLocalizations.of(navigatorKey.currentContext!).translate((Constants.MONTHS[prevMonth.month - 1])) + " - " + prevMonth.year.toString()}" + }; dates.add(r); } } if (dates.length > 0) { return dates; } - return >[]; + return >[]; } } diff --git a/frontend/mgramseva/lib/providers/household_register_provider.dart b/frontend/mgramseva/lib/providers/household_register_provider.dart index a9008d0c7..a92b9a8d0 100644 --- a/frontend/mgramseva/lib/providers/household_register_provider.dart +++ b/frontend/mgramseva/lib/providers/household_register_provider.dart @@ -1,9 +1,12 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:mgramseva/model/connection/water_connection.dart'; import 'package:mgramseva/model/connection/water_connections.dart'; import 'package:mgramseva/providers/common_provider.dart'; +import 'package:mgramseva/providers/reports_provider.dart'; import 'package:mgramseva/repository/search_connection_repo.dart'; import 'package:mgramseva/routers/routers.dart'; import 'package:mgramseva/screeens/household_register/household_pdf_creator.dart'; @@ -238,7 +241,8 @@ class HouseholdRegisterProvider with ChangeNotifier { : null, callBack: onSort), TableHeader(i18.householdRegister.ACTIVE_INACTIVE, - isSortingRequired: false, apiKey: 'status'), + isSortingRequired: false, apiKey: 'leadgerReport'), + // TableHeader("Ledger", apiKey: '/viewLeadger') ]; List get collectionHeaderListOLd => [ TableHeader(i18.common.CONNECTION_ID, @@ -293,6 +297,7 @@ class HouseholdRegisterProvider with ChangeNotifier { ? sortBy!.isAscending : null, callBack: onSort), + ]; List getCollectionsData(List list) { @@ -323,9 +328,6 @@ class HouseholdRegisterProvider with ChangeNotifier { } TableDataRow getCollectionRow(WaterConnection connection) { - var commonProvider = Provider.of( - navigatorKey.currentContext!, - listen: false); String? name = truncateWithEllipsis(connection.connectionHolders?.first.name ?? 'NA'); String? fatherName = truncateWithEllipsis( @@ -334,16 +336,9 @@ class HouseholdRegisterProvider with ChangeNotifier { TableData( '${connection.connectionNo?.split('/').first ?? ''}/...${connection.connectionNo?.split('/').last ?? ''} ${connection.connectionType == 'Metered' ? '- M' : ''}', callBack: onClickOfCollectionNo, + iconButtonCallBack: viewLeadger, apiKey: connection.connectionNo), - // TableData( - // '${commonProvider.userDetails?.selectedtenant?.city?.code ?? 'NA'}', - // ), - // TableData( - // '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(connection.tenantId ?? 'NA')}', - // ), - // TableData( - // '${connection.tenantId ?? 'NA'}', - // ), + TableData( '${name ?? 'NA'}', ), @@ -428,6 +423,15 @@ class HouseholdRegisterProvider with ChangeNotifier { 'status': waterConnection?.status }); } + viewLeadger(TableData tableData) { + log("Call Ledger View Here"); + var waterConnection = waterConnectionsDetails?.waterConnection + ?.firstWhere((element) => element.connectionNo == tableData.apiKey); + Navigator.pushNamed(navigatorKey.currentContext!, Routes.LEDGER_REPORTS, + arguments: { + 'waterconnections': waterConnection, + }); + } onSort(TableHeader header) { if (sortBy != null && sortBy!.key == header.apiKey) { diff --git a/frontend/mgramseva/lib/providers/reports_provider.dart b/frontend/mgramseva/lib/providers/reports_provider.dart index fd169ff9e..7b69a0f12 100644 --- a/frontend/mgramseva/lib/providers/reports_provider.dart +++ b/frontend/mgramseva/lib/providers/reports_provider.dart @@ -1,7 +1,10 @@ import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:mgramseva/model/reports/InactiveConsumerReportData.dart'; +import 'package:mgramseva/model/reports/leadger_report.dart'; import 'package:mgramseva/model/reports/vendor_report_data.dart'; import 'package:provider/provider.dart'; import 'package:syncfusion_flutter_xlsio/xlsio.dart'; @@ -34,15 +37,18 @@ class ReportsProvider with ChangeNotifier { var selectedBillYear; var selectedBillPeriod; var selectedBillCycle; + var consumerCode = ''; var billingyearCtrl = TextEditingController(); var billingcycleCtrl = TextEditingController(); List? demandreports; + List? ledgerReport; List? collectionreports; List? inactiveconsumers; List? expenseBillReportData; List? vendorReportData; WaterConnectionCountResponse? waterConnectionCount; BillsTableData genericTableData = BillsTableData([], []); + int limit = 10; int offset = 1; @@ -53,6 +59,7 @@ class ReportsProvider with ChangeNotifier { billingcycleCtrl.clear(); billingyearCtrl.clear(); demandreports = []; + ledgerReport = []; collectionreports = []; inactiveconsumers = []; expenseBillReportData = []; @@ -65,6 +72,15 @@ class ReportsProvider with ChangeNotifier { notifyListeners(); } + void updateConsumerCode(val) { + consumerCode = val; + notifyListeners(); + } + + void updateDefaultDate() { + onChangeOfBillYear(getFinancialYearListDropdown(billingYearList).first); + } + dispose() { streamController.close(); super.dispose(); @@ -82,6 +98,21 @@ class ReportsProvider with ChangeNotifier { TableHeader(i18.common.CORE_ADVANCE), TableHeader(i18.billDetails.TOTAL_AMOUNT), ]; + List get leadgerHeaderList => [ + TableHeader(i18.common.LEDGER_MONTH), + TableHeader(i18.common.LEDGER_DEMAND_GENERATION_DATE), + TableHeader(i18.common.LEDGER_MONTHLY_CHARGE), + TableHeader(i18.common.LEDGER_PREV_MONTH_BALANCE), + TableHeader(i18.common.LEDGER_TOTAL_DUE), + TableHeader(i18.common.LEDGER_DUE_DATE_PAYMENT), + TableHeader(i18.common.LEDGER_DATE), + TableHeader(i18.common.LEDGER_RECIPET_NO), + TableHeader(i18.common.LEDGER_AMOUNT), + TableHeader(i18.common.LEDGER_BALANCE), + TableHeader(i18.common.LEDGER_PENALTY_APPLIED_ON_DATE), + TableHeader(i18.common.LEDGER_PENALTY), + TableHeader(i18.common.LEDGER_BALANCE_FOR_THE_MONH), + ]; List get collectionHeaderList => [ TableHeader(i18.common.CONNECTION_ID), @@ -94,25 +125,24 @@ class ReportsProvider with ChangeNotifier { TableHeader(i18.billDetails.TOTAL_AMOUNT), ]; List get inactiveConsumerHeaderList => [ - TableHeader(i18.common.CONNECTION_ID), - TableHeader(i18.common.STATUS), - TableHeader(i18.common.INACTIVATED_DATE), - TableHeader(i18.common.INACTIVATED_BY_NAME), - ]; + TableHeader(i18.common.CONNECTION_ID), + TableHeader(i18.common.STATUS), + TableHeader(i18.common.INACTIVATED_DATE), + TableHeader(i18.common.INACTIVATED_BY_NAME), + ]; List get expenseBillReportHeaderList => [ - TableHeader(i18.expense.EXPENSE_TYPE), - TableHeader(i18.expense.VENDOR_NAME), - TableHeader(i18.expense.AMOUNT), - TableHeader(i18.expense.BILL_DATE), - TableHeader(i18.expense.EXPENSE_START_DATE), - TableHeader(i18.expense.EXPENSE_END_DATE), - TableHeader(i18.expense.APPLICATION_STATUS), - TableHeader(i18.expense.PAID_DATE), - TableHeader(i18.expense.HAS_ATTACHMENT), - TableHeader(i18.expense.CANCELLED_TIME), - TableHeader(i18.expense.CANCELLED_BY), - - ]; + TableHeader(i18.expense.EXPENSE_TYPE), + TableHeader(i18.expense.VENDOR_NAME), + TableHeader(i18.expense.AMOUNT), + TableHeader(i18.expense.BILL_DATE), + TableHeader(i18.expense.EXPENSE_START_DATE), + TableHeader(i18.expense.EXPENSE_END_DATE), + TableHeader(i18.expense.APPLICATION_STATUS), + TableHeader(i18.expense.PAID_DATE), + TableHeader(i18.expense.HAS_ATTACHMENT), + TableHeader(i18.expense.CANCELLED_TIME), + TableHeader(i18.expense.CANCELLED_BY), + ]; List get vendorReportHeaderList => [ TableHeader(i18.common.BILL_ID), @@ -138,6 +168,9 @@ class ReportsProvider with ChangeNotifier { if (type == i18.dashboard.VENDOR_REPORT) { getVendorReport(limit: response.limit, offset: response.offset); } + if (type == i18.dashboard.LEDGER_REPORTS) { + getLeadgerReport(limit: response.limit, offset: response.offset); + } } List getDemandsData(List list, @@ -145,6 +178,51 @@ class ReportsProvider with ChangeNotifier { return list.map((e) => getDemandRow(e, isExcel: isExcel)).toList(); } + List getLedgerData(List list, {isExcel = false}) { + return list.map((e) => getLedgerRow(e, isExcel: isExcel)).toList(); + } + + String formatYearMonth(String inputString) { + final length = inputString.length; + if (length < 4) { + return inputString; // Return the original string if length is less than 4 + } else { + return inputString.substring(0, length - 4) + + ' - ' + + inputString.substring(length - 4); + } + } + + String formatPaymentReceipts(List? payments) { + return payments?.map((payment) => payment.receiptNo)?.join(', ') ?? ''; + } + + TableDataRow getLedgerRow(LedgerData data, {bool isExcel = false}) { + return TableDataRow([ + TableData( + formatYearMonth('${data.months?.values.first.demand?.month}'), + ), + TableData( + '${DateFormats.leadgerTimeStampToDate(data.months?.values.first.demand?.demandGenerationDate)}'), + TableData('₹ ${data.months?.values.first.demand?.monthlyCharges}'), + TableData('₹ ${data.months?.values.first.demand?.previousMonthBalance}'), + TableData('₹ ${data.months?.values.first.demand?.totalDues}'), + TableData( + '${DateFormats.leadgerTimeStampToDate(data.months?.values.first.demand?.dueDateOfPayment)}'), + TableData( + '${DateFormats.leadgerTimeStampToDate(data.months?.values.first.payment?.first.paymentCollectionDate)}'), + // TableData('${data.months?.values.first.payment?.first.receiptNo}'), + TableData('${formatPaymentReceipts(data.months?.values?.first.payment)}'), + TableData('₹ ${data.months?.values.first.totalPaymentInMonth}'), + TableData( + '₹ ${(double.parse("${data.months?.values.first.demand?.totalDues}") - double.parse("${data.months?.values.first.totalPaymentInMonth}"))}'), + TableData( + '${DateFormats.leadgerTimeStampToDate(data.months?.values.first.demand?.penaltyAppliedOnDate)}'), + TableData('₹ ${data.months?.values.first.demand?.penalty}'), + TableData('₹ ${data.months?.values.first.payment?.first.balanceLeft}'), + ]); + } + TableDataRow getDemandRow(BillReportData data, {bool isExcel = false}) { String? name = CommonMethods.truncateWithEllipsis(20, data.consumerName!); return TableDataRow([ @@ -181,53 +259,80 @@ class ReportsProvider with ChangeNotifier { ? '${data.connectionNo ?? '-'}' : '${data.connectionNo?.split('/').first ?? ''}/...${data.connectionNo?.split('/').last ?? ''}', ), - TableData('${(data.oldConnectionNo == null ? null : data.oldConnectionNo!.isEmpty ? null : data.oldConnectionNo) ?? '-'}'), + TableData( + '${(data.oldConnectionNo == null ? null : data.oldConnectionNo!.isEmpty ? null : data.oldConnectionNo) ?? '-'}'), TableData('${name ?? '-'}'), TableData('${data.paymentMode ?? '-'}'), TableData('${data.paymentAmount ?? '0'}'), ]); } - List getInactiveConsumersData(List list, + + List getInactiveConsumersData( + List list, {bool isExcel = false}) { - return list.map((e) => getInactiveConsumersDataRow(e, isExcel: isExcel)).toList(); + return list + .map((e) => getInactiveConsumersDataRow(e, isExcel: isExcel)) + .toList(); } TableDataRow getInactiveConsumersDataRow(InactiveConsumerReportData data, {bool isExcel = false}) { - String? inactivatedBy = CommonMethods.truncateWithEllipsis(20, data.inactivatedByName!); + String? inactivatedBy = + CommonMethods.truncateWithEllipsis(20, data.inactivatedByName!); if (data.connectionNo != null && data.connectionNo!.isEmpty) { data.connectionNo = '-'; } - var inactivatedDate = DateFormats.timeStampToDate(data.inactiveDate?.toInt(),format: "dd/MM/yyyy"); + var inactivatedDate = DateFormats.timeStampToDate( + data.inactiveDate?.toInt(), + format: "dd/MM/yyyy"); return TableDataRow([ TableData( isExcel ? '${data.connectionNo ?? '-'}' : '${data.connectionNo?.split('/').first ?? ''}/...${data.connectionNo?.split('/').last ?? ''}', ), - TableData('${data.status??'-'}'), + TableData('${data.status ?? '-'}'), TableData('${inactivatedDate ?? '-'}'), TableData('${inactivatedBy ?? '-'}'), ]); } + List getExpenseBillReportData(List list, {bool isExcel = false}) { - return list.map((e) => getExpenseBillReportDataRow(e, isExcel: isExcel)).toList(); + return list + .map((e) => getExpenseBillReportDataRow(e, isExcel: isExcel)) + .toList(); } + TableDataRow getExpenseBillReportDataRow(ExpenseBillReportData data, {bool isExcel = false}) { - String? vendorName = CommonMethods.truncateWithEllipsis(20, data.vendorName!); - String? typeOfExpense = CommonMethods.truncateWithEllipsis(20, data.typeOfExpense!); - String? applicationStatus = CommonMethods.truncateWithEllipsis(20, data.applicationStatus!); - String? lastModifiedBy = CommonMethods.truncateWithEllipsis(20, data.lastModifiedBy!); - String? fileLink = CommonMethods.truncateWithEllipsis(20, data.filestoreid!); - var billDate = DateFormats.timeStampToDate(data.billDate?.toInt(),format: "dd/MM/yyyy"); - var taxPeriodFrom = DateFormats.timeStampToDate(data.taxPeriodFrom?.toInt(),format: "dd/MM/yyyy"); - var taxPeriodTo = DateFormats.timeStampToDate(data.taxPeriodTo?.toInt(),format: "dd/MM/yyyy"); - var paidDate = data.paidDate==0?'-':DateFormats.timeStampToDate(data.paidDate?.toInt(),format: "dd/MM/yyyy"); - var lastModifiedTime = data.lastModifiedTime==0?'-':DateFormats.timeStampToDate(data.lastModifiedTime?.toInt(),format: "dd/MM/yyyy"); + String? vendorName = + CommonMethods.truncateWithEllipsis(20, data.vendorName!); + String? typeOfExpense = + CommonMethods.truncateWithEllipsis(20, data.typeOfExpense!); + String? applicationStatus = + CommonMethods.truncateWithEllipsis(20, data.applicationStatus!); + String? lastModifiedBy = + CommonMethods.truncateWithEllipsis(20, data.lastModifiedBy!); + String? fileLink = + CommonMethods.truncateWithEllipsis(20, data.filestoreid!); + var billDate = DateFormats.timeStampToDate(data.billDate?.toInt(), + format: "dd/MM/yyyy"); + var taxPeriodFrom = DateFormats.timeStampToDate(data.taxPeriodFrom?.toInt(), + format: "dd/MM/yyyy"); + var taxPeriodTo = DateFormats.timeStampToDate(data.taxPeriodTo?.toInt(), + format: "dd/MM/yyyy"); + var paidDate = data.paidDate == 0 + ? '-' + : DateFormats.timeStampToDate(data.paidDate?.toInt(), + format: "dd/MM/yyyy"); + var lastModifiedTime = data.lastModifiedTime == 0 + ? '-' + : DateFormats.timeStampToDate(data.lastModifiedTime?.toInt(), + format: "dd/MM/yyyy"); return TableDataRow([ - TableData('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(typeOfExpense ?? '-')}'), + TableData( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(typeOfExpense ?? '-')}'), TableData('${vendorName ?? '-'}'), TableData('${data.amount ?? '-'}'), TableData('${billDate ?? '-'}'), @@ -240,20 +345,27 @@ class ReportsProvider with ChangeNotifier { TableData('${lastModifiedBy ?? '-'}'), ]); } + List getVendorReportData(List list, {bool isExcel = false}) { - return list.map((e) => getVendorReportDataRow(e, isExcel: isExcel)).toList(); + return list + .map((e) => getVendorReportDataRow(e, isExcel: isExcel)) + .toList(); } + TableDataRow getVendorReportDataRow(VendorReportData data, {bool isExcel = false}) { - String? vendorName = CommonMethods.truncateWithEllipsis(20, data.vendorName!); - String? typeOfExpense = CommonMethods.truncateWithEllipsis(20, data.typeOfExpense!); + String? vendorName = + CommonMethods.truncateWithEllipsis(20, data.vendorName!); + String? typeOfExpense = + CommonMethods.truncateWithEllipsis(20, data.typeOfExpense!); String? billId = CommonMethods.truncateWithEllipsis(20, data.billId!); return TableDataRow([ TableData('${billId ?? '-'}'), TableData('${vendorName ?? '-'}'), TableData('${data.mobileNo ?? '-'}'), - TableData('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(typeOfExpense ?? '-')}'), + TableData( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(typeOfExpense ?? '-')}'), ]); } @@ -261,14 +373,19 @@ class ReportsProvider with ChangeNotifier { notifyListeners(); } + updateSelectedBillYear(val) { + selectedBillYear = val; + notifyListeners(); + } + void onChangeOfBillYear(val) { selectedBillYear = val; - print(val.toString()); billingyearCtrl.text = val.toString(); billingcycleCtrl.clear(); selectedBillCycle = null; selectedBillPeriod = null; demandreports = []; + ledgerReport = []; collectionreports = []; inactiveconsumers = []; expenseBillReportData = []; @@ -290,6 +407,7 @@ class ReportsProvider with ChangeNotifier { .toString(), dateFormat: "dd/MM/yyyy"); demandreports = []; + ledgerReport = []; collectionreports = []; inactiveconsumers = []; expenseBillReportData = []; @@ -312,8 +430,8 @@ class ReportsProvider with ChangeNotifier { streamController.addError('error'); } } - List getFinancialYearListDropdownA( - LanguageList? languageList) { + + List getFinancialYearListDropdownA(LanguageList? languageList) { if (languageList?.mdmsRes?.billingService?.taxPeriodList != null) { CommonMethods.getFilteredFinancialYearList( languageList?.mdmsRes?.billingService?.taxPeriodList ?? @@ -321,15 +439,16 @@ class ReportsProvider with ChangeNotifier { languageList?.mdmsRes?.billingService?.taxPeriodList! .sort((a, b) => a.fromDate!.compareTo(b.fromDate!)); return (languageList?.mdmsRes?.billingService?.taxPeriodList ?? - []) + []) .reversed .toList(); } return []; } - List> getBillingCycleDropdownA( + + List> getBillingCycleDropdownA( dynamic selectedBillYear) { - List> dates = []; + List> dates = []; if (selectedBillYear != null) { DatePeriod ytd; var fromDate = DateFormats.getFormattedDateToDateTime( @@ -349,10 +468,11 @@ class ReportsProvider with ChangeNotifier { for (var i = 0; i < months.length; i++) { var prevMonth = months[i].startDate; - var r = {"code": prevMonth, "name": '${ApplicationLocalizations.of(navigatorKey.currentContext!) - .translate((Constants.MONTHS[prevMonth.month - 1])) + - " - " + - prevMonth.year.toString()}'}; + var r = { + "code": prevMonth, + "name": + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate((Constants.MONTHS[prevMonth.month - 1])) + " - " + prevMonth.year.toString()}' + }; dates.add(r); } } @@ -367,8 +487,8 @@ class ReportsProvider with ChangeNotifier { // } return dates; } - List getFinancialYearListDropdown( - LanguageList? languageList) { + + List getFinancialYearListDropdown(LanguageList? languageList) { if (languageList?.mdmsRes?.billingService?.taxPeriodList != null) { CommonMethods.getFilteredFinancialYearList( languageList?.mdmsRes?.billingService?.taxPeriodList ?? @@ -387,9 +507,8 @@ class ReportsProvider with ChangeNotifier { return []; } - List> getBillingCycleDropdown( - dynamic selectedBillYear) { - var dates = >[]; + List> getBillingCycleDropdown(dynamic selectedBillYear) { + var dates = >[]; if (selectedBillYear != null) { DatePeriod ytd; var fromDate = DateFormats.getFormattedDateToDateTime( @@ -409,17 +528,86 @@ class ReportsProvider with ChangeNotifier { for (var i = 0; i < months.length; i++) { var prevMonth = months[i].startDate; - Map r = {"code": prevMonth, "name": "${ApplicationLocalizations.of(navigatorKey.currentContext!) - .translate((Constants.MONTHS[prevMonth.month - 1])) + - " - " + - prevMonth.year.toString()}"}; + Map r = { + "code": prevMonth, + "name": + "${ApplicationLocalizations.of(navigatorKey.currentContext!).translate((Constants.MONTHS[prevMonth.month - 1])) + " - " + prevMonth.year.toString()}" + }; dates.add(r); } } if (dates.length > 0) { return dates; } - return >[]; + return >[]; + } + + Future getLeadgerReport({ + bool download = false, + int offset = 1, + int limit = 10, + }) async { + try { + var commonProvider = Provider.of( + navigatorKey.currentContext!, + listen: false); + + if (selectedBillYear == null) { + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + } + Map params = { + 'tenantId': commonProvider.userDetails!.selectedtenant!.code, + 'offset': '${offset - 1}', + 'limit': '${download ? -1 : limit}', + 'consumercode': consumerCode, + 'year': selectedBillYear.financialYear, + }; + var response = await ReportsRepo().fetchLedgerReport(params); + if (response != null) { + ledgerReport = response; + if (download) { + generateExcel( + leadgerHeaderList + .map((e) => + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') + .toList(), + getLedgerData(ledgerReport!, isExcel: true) + .map>( + (e) => e.tableRow.map((e) => e.label).toList()) + .toList() ?? + [], + title: + 'LedgerReport_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillYear.toString().replaceAll('/', '_')}', + optionalData: [ + 'Ledger Report', + '$selectedBillYear', + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(commonProvider.userDetails!.selectedtenant!.code!)}', + '${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}', + 'Downloaded On ${DateFormats.timeStampToDate(DateTime.now().millisecondsSinceEpoch, format: 'dd/MMM/yyyy')}' + ]); + } else { + if (ledgerReport != null && ledgerReport!.isNotEmpty) { + this.limit = limit; + this.offset = offset; + this.genericTableData = + BillsTableData(leadgerHeaderList, getLedgerData(ledgerReport!)); + } + } + + streamController.add(response); + callNotifier(); + } else { + streamController.add('error'); + throw Exception('API Error'); + } + callNotifier(); + } catch (e, s) { + ledgerReport = []; + ErrorHandler().allExceptionsHandler(navigatorKey.currentContext!, e, s); + streamController.addError('error'); + callNotifier(); + } } Future getDemandReport( @@ -432,7 +620,8 @@ class ReportsProvider with ChangeNotifier { navigatorKey.currentContext!, listen: false); if (selectedBillPeriod == null) { - throw Exception('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); } Map params = { 'tenantId': commonProvider.userDetails!.selectedtenant!.code, @@ -498,7 +687,8 @@ class ReportsProvider with ChangeNotifier { navigatorKey.currentContext!, listen: false); if (selectedBillPeriod == null) { - throw Exception('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); } Map params = { 'tenantId': commonProvider.userDetails!.selectedtenant!.code, @@ -556,15 +746,16 @@ class ReportsProvider with ChangeNotifier { Future getInactiveConsumerReport( {bool download = false, - int offset = 1, - int limit = 10, - String sortOrder = "ASC"}) async { + int offset = 1, + int limit = 10, + String sortOrder = "ASC"}) async { try { var commonProvider = Provider.of( navigatorKey.currentContext!, listen: false); if (selectedBillPeriod == null) { - throw Exception('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); } Map params = { 'tenantId': commonProvider.userDetails!.selectedtenant!.code, @@ -581,15 +772,15 @@ class ReportsProvider with ChangeNotifier { generateExcel( inactiveConsumerHeaderList .map((e) => - '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') .toList(), getInactiveConsumersData(inactiveconsumers!, isExcel: true) - .map>( - (e) => e.tableRow.map((e) => e.label).toList()) - .toList() ?? + .map>( + (e) => e.tableRow.map((e) => e.label).toList()) + .toList() ?? [], title: - 'InactiveConsumers_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', + 'InactiveConsumers_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', optionalData: [ 'Inactive Consumer Report', '$selectedBillPeriod', @@ -601,8 +792,8 @@ class ReportsProvider with ChangeNotifier { if (inactiveconsumers != null && inactiveconsumers!.isNotEmpty) { this.limit = limit; this.offset = offset; - this.genericTableData = BillsTableData( - inactiveConsumerHeaderList, getInactiveConsumersData(inactiveconsumers!)); + this.genericTableData = BillsTableData(inactiveConsumerHeaderList, + getInactiveConsumersData(inactiveconsumers!)); } } streamController.add(response); @@ -619,17 +810,19 @@ class ReportsProvider with ChangeNotifier { callNotifier(); } } + Future getExpenseBillReport( {bool download = false, - int offset = 1, - int limit = 10, - String sortOrder = "ASC"}) async { + int offset = 1, + int limit = 10, + String sortOrder = "ASC"}) async { try { var commonProvider = Provider.of( navigatorKey.currentContext!, listen: false); if (selectedBillPeriod == null) { - throw Exception('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); } Map params = { 'tenantId': commonProvider.userDetails!.selectedtenant!.code, @@ -646,15 +839,15 @@ class ReportsProvider with ChangeNotifier { generateExcel( expenseBillReportHeaderList .map((e) => - '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') .toList(), getExpenseBillReportData(expenseBillReportData!, isExcel: true) - .map>( - (e) => e.tableRow.map((e) => e.label).toList()) - .toList() ?? + .map>( + (e) => e.tableRow.map((e) => e.label).toList()) + .toList() ?? [], title: - 'ExpenseBillReport_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', + 'ExpenseBillReport_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', optionalData: [ 'Expense Bill Report', '$selectedBillPeriod', @@ -663,11 +856,12 @@ class ReportsProvider with ChangeNotifier { 'Downloaded On ${DateFormats.timeStampToDate(DateTime.now().millisecondsSinceEpoch, format: 'dd/MMM/yyyy')}' ]); } else { - if (expenseBillReportData != null && expenseBillReportData!.isNotEmpty) { + if (expenseBillReportData != null && + expenseBillReportData!.isNotEmpty) { this.limit = limit; this.offset = offset; - this.genericTableData = BillsTableData( - expenseBillReportHeaderList, getExpenseBillReportData(expenseBillReportData!)); + this.genericTableData = BillsTableData(expenseBillReportHeaderList, + getExpenseBillReportData(expenseBillReportData!)); } } streamController.add(response); @@ -676,8 +870,7 @@ class ReportsProvider with ChangeNotifier { streamController.add('error'); throw Exception('API Error'); } - } - catch (e, s) { + } catch (e, s) { ErrorHandler().allExceptionsHandler(navigatorKey.currentContext!, e, s); streamController.addError('error'); callNotifier(); @@ -686,15 +879,16 @@ class ReportsProvider with ChangeNotifier { Future getVendorReport( {bool download = false, - int offset = 1, - int limit = 10, - String sortOrder = "ASC"}) async { + int offset = 1, + int limit = 10, + String sortOrder = "ASC"}) async { try { var commonProvider = Provider.of( navigatorKey.currentContext!, listen: false); if (selectedBillPeriod == null) { - throw Exception('${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); + throw Exception( + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.SELECT_BILLING_CYCLE)}'); } Map params = { 'tenantId': commonProvider.userDetails!.selectedtenant!.code, @@ -711,15 +905,15 @@ class ReportsProvider with ChangeNotifier { generateExcel( vendorReportHeaderList .map((e) => - '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(e.label)}') .toList(), getVendorReportData(vendorReportData!, isExcel: true) - .map>( - (e) => e.tableRow.map((e) => e.label).toList()) - .toList() ?? + .map>( + (e) => e.tableRow.map((e) => e.label).toList()) + .toList() ?? [], title: - 'VendorReport_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', + 'VendorReport_${commonProvider.userDetails?.selectedtenant?.code?.substring(3)}_${selectedBillPeriod.toString().replaceAll('/', '_')}', optionalData: [ 'Vendor Report', '$selectedBillPeriod', @@ -741,8 +935,7 @@ class ReportsProvider with ChangeNotifier { streamController.add('error'); throw Exception('API Error'); } - } - catch (e, s) { + } catch (e, s) { ErrorHandler().allExceptionsHandler(navigatorKey.currentContext!, e, s); streamController.addError('error'); callNotifier(); @@ -760,7 +953,8 @@ class ReportsProvider with ChangeNotifier { //Create a Excel document. //Creating a workbook. - headers.insert(0, '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.S_NO)}'); + headers.insert(0, + '${ApplicationLocalizations.of(navigatorKey.currentContext!).translate(i18.common.S_NO)}'); final Workbook workbook = Workbook(); //Accessing via index final Worksheet sheet = workbook.worksheets[0]; @@ -775,20 +969,39 @@ class ReportsProvider with ChangeNotifier { sheet.getRangeByName('A1:D1').columnWidth = 32.5; sheet.getRangeByName('A1:D1').cellStyle.hAlign = HAlignType.center; } else { - sheet.getRangeByName('A1:A${tableData.length+1}').columnWidth = 12.5; - sheet.getRangeByName('A1:A${tableData.length+1}').cellStyle.hAlign = HAlignType.center; - sheet.getRangeByName('A1:A${tableData.length+1}').autoFit(); - sheet.getRangeByName('B1:${CommonMethods.getAlphabetsWithKeyValue()[optionalData.length+1].label}1').columnWidth = 32.5; - sheet.getRangeByName('B1:${CommonMethods.getAlphabetsWithKeyValue()[optionalData.length+1].label}1').cellStyle.hAlign = HAlignType.center; - sheet.getRangeByName('B2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length+1].label}2').columnWidth = 32.5; - sheet.getRangeByName('A2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length+1].label}2').cellStyle.hAlign = HAlignType.center; - sheet.getRangeByName('A2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length+1].label}2').cellStyle.bold = true; + sheet.getRangeByName('A1:A${tableData.length + 1}').columnWidth = 12.5; + sheet.getRangeByName('A1:A${tableData.length + 1}').cellStyle.hAlign = + HAlignType.center; + sheet.getRangeByName('A1:A${tableData.length + 1}').autoFit(); + sheet + .getRangeByName( + 'B1:${CommonMethods.getAlphabetsWithKeyValue()[optionalData.length + 1].label}1') + .columnWidth = 32.5; + sheet + .getRangeByName( + 'B1:${CommonMethods.getAlphabetsWithKeyValue()[optionalData.length + 1].label}1') + .cellStyle + .hAlign = HAlignType.center; + sheet + .getRangeByName( + 'B2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length + 1].label}2') + .columnWidth = 32.5; + sheet + .getRangeByName( + 'A2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length + 1].label}2') + .cellStyle + .hAlign = HAlignType.center; + sheet + .getRangeByName( + 'A2:${CommonMethods.getAlphabetsWithKeyValue()[headers.length + 1].label}2') + .cellStyle + .bold = true; dataStartRow = 3; headersStartRow = 2; for (int i = 0; i < optionalData.length; i++) { sheet .getRangeByName( - '${CommonMethods.getAlphabetsWithKeyValue()[i+1].label}1') + '${CommonMethods.getAlphabetsWithKeyValue()[i + 1].label}1') .setText( optionalData[CommonMethods.getAlphabetsWithKeyValue()[i].key]); } @@ -803,15 +1016,15 @@ class ReportsProvider with ChangeNotifier { for (int i = dataStartRow; i < tableData.length + dataStartRow; i++) { for (int j = 0; j < headers.length; j++) { - if(j==0){ + if (j == 0) { sheet .getRangeByName( - '${CommonMethods.getAlphabetsWithKeyValue()[j].label}$i') - .setText('${i - dataStartRow+1}'); - }else{ + '${CommonMethods.getAlphabetsWithKeyValue()[j].label}$i') + .setText('${i - dataStartRow + 1}'); + } else { sheet .getRangeByName( - '${CommonMethods.getAlphabetsWithKeyValue()[j].label}$i') + '${CommonMethods.getAlphabetsWithKeyValue()[j].label}$i') .setText(tableData[i - dataStartRow][j - 1]); } sheet @@ -835,6 +1048,7 @@ class ReportsProvider with ChangeNotifier { //Save and launch the file. await saveAndLaunchFile(bytes, '$title.xlsx'); } + Future getWaterConnectionsCount() async { try { var commonProvider = Provider.of( diff --git a/frontend/mgramseva/lib/repository/reports_repo.dart b/frontend/mgramseva/lib/repository/reports_repo.dart index cc6559857..ec8cce202 100644 --- a/frontend/mgramseva/lib/repository/reports_repo.dart +++ b/frontend/mgramseva/lib/repository/reports_repo.dart @@ -1,4 +1,8 @@ +import 'dart:convert'; +import 'dart:developer'; + import 'package:mgramseva/model/reports/expense_bill_report_data.dart'; +import 'package:mgramseva/model/reports/leadger_report.dart'; import 'package:mgramseva/model/reports/vendor_report_data.dart'; import 'package:mgramseva/services/urls.dart'; import 'package:mgramseva/services/base_service.dart'; @@ -51,6 +55,45 @@ class ReportsRepo extends BaseService{ return billreports; } + Future?> fetchLedgerReport(Map params, + [String? token]) async { + var commonProvider = Provider.of( + navigatorKey.currentContext!, + listen: false); + List? ledgerReports; + final requestInfo = RequestInfo( + APIConstants.API_MODULE_NAME, + APIConstants.API_VERSION, + APIConstants.API_TS, + '_get', + APIConstants.API_DID, + APIConstants.API_KEY, + APIConstants.API_MESSAGE_ID, + commonProvider.userDetails?.accessToken, + commonProvider.userDetails?.userRequest?.toJson()); + var res = await makeRequest( + url: Url.LEDGER_REPORT, + queryParameters: params, + body: { + "RequestInfo":requestInfo + }, + method: RequestType.POST); + + if (res != null && res['ledgerReport'] != null) { + try { + ledgerReports = []; + res['ledgerReport'].forEach((val){ + ledgerReports?.add(LedgerData.fromJson(val)); + }); + } catch (e) { + print(e); + ledgerReports = null; + } + } + return ledgerReports; + } + + Future?> fetchCollectionReport(Map params, [String? token]) async { var commonProvider = Provider.of( diff --git a/frontend/mgramseva/lib/routers/routers.dart b/frontend/mgramseva/lib/routers/routers.dart index 9ef5818d0..c2d1c0c61 100644 --- a/frontend/mgramseva/lib/routers/routers.dart +++ b/frontend/mgramseva/lib/routers/routers.dart @@ -83,6 +83,7 @@ class Routes { static const String NOTIFICATIONS = '/home/notifications'; static const String REPORTS = '/home/reports'; + static const String LEDGER_REPORTS = '/home/leadger/reports'; static const String PRIVACY_POLICY = '/privacy'; static const String TERMS_OF_USE = '/terms'; static const String PRIVACY_POLICY_S = '/privacy/'; diff --git a/frontend/mgramseva/lib/routing.dart b/frontend/mgramseva/lib/routing.dart index 08b7fb3c3..f76c6bad1 100644 --- a/frontend/mgramseva/lib/routing.dart +++ b/frontend/mgramseva/lib/routing.dart @@ -24,6 +24,7 @@ import 'package:mgramseva/screeens/notifications/notification_screen.dart'; import 'package:mgramseva/screeens/password_success/password_success.dart'; import 'package:mgramseva/screeens/privacy_and_terms/PrivacyAndTerms.dart'; import 'package:mgramseva/screeens/profile/edit_profile.dart'; +import 'package:mgramseva/screeens/leadger_report/ledger_report.dart'; import 'package:mgramseva/screeens/reports/reports.dart'; import 'package:mgramseva/screeens/reset_password/reset_password.dart'; import 'package:mgramseva/screeens/reset_password/update_password.dart'; @@ -370,6 +371,14 @@ class Routing { return MaterialPageRoute( builder: (_) => Reports(), settings: RouteSettings(name: Routes.REPORTS)); + case Routes.LEDGER_REPORTS: + return MaterialPageRoute( + builder: (_) => LeadgerReport( + waterConnection: settings.arguments != null + ? (settings.arguments as Map)['waterconnections'] + as WaterConnection + : null), + settings: RouteSettings(name: Routes.LEDGER_REPORTS)); case Routes.PRIVACY_POLICY: bool args = settings.arguments==null?false:settings.arguments as bool; return MaterialPageRoute( diff --git a/frontend/mgramseva/lib/screeens/household_detail/household_detail.dart b/frontend/mgramseva/lib/screeens/household_detail/household_detail.dart index 92192c34d..613be4081 100644 --- a/frontend/mgramseva/lib/screeens/household_detail/household_detail.dart +++ b/frontend/mgramseva/lib/screeens/household_detail/household_detail.dart @@ -28,7 +28,6 @@ class HouseholdDetail extends StatefulWidget { final String? mode; final String? status; final WaterConnection? waterConnection; - HouseholdDetail( {Key? key, this.id, this.mode, this.status, this.waterConnection}); @override diff --git a/frontend/mgramseva/lib/screeens/leadger_report/leadger_view.dart b/frontend/mgramseva/lib/screeens/leadger_report/leadger_view.dart new file mode 100644 index 000000000..0df722dcb --- /dev/null +++ b/frontend/mgramseva/lib/screeens/leadger_report/leadger_view.dart @@ -0,0 +1,121 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../providers/reports_provider.dart'; +import '../../utils/localization/application_localizations.dart'; + +import 'package:mgramseva/utils/constants/i18_key_constants.dart'; + +import '../../utils/notifiers.dart'; +import '../../utils/testing_keys/testing_keys.dart'; +import '../../widgets/button.dart'; + +class LeadgerReportView extends StatefulWidget { + final Function onViewClick; + + LeadgerReportView({Key? key, required this.onViewClick}) : super(key: key); + + @override + State createState() { + return _LeadgerReportView(); + } +} + +class _LeadgerReportView extends State + with SingleTickerProviderStateMixin { + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, constraints) { + final isWideScreen = constraints.maxWidth > 700; + final containerMargin = isWideScreen + ? const EdgeInsets.only(top: 5.0, bottom: 5, right: 20, left: 10) + : const EdgeInsets.symmetric(vertical: 5.0, horizontal: 8); + return Consumer(builder: (_, reportProvider, child) { + return Container( + margin: containerMargin, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox( + height: 30, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: constraints.maxWidth > 344 + ? constraints.maxWidth / 2.5 + : constraints.maxWidth / 3, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "1. ", + style: TextStyle( + fontSize: 14, fontWeight: FontWeight.w700), + ), + Expanded( + child: Text( + ApplicationLocalizations.of(context) + .translate(i18.dashboard.LEDGER_REPORTS), + maxLines: 3, + style: TextStyle( + fontSize: 14, fontWeight: FontWeight.w700), + ), + ), + ], + ), + ), + Row( + children: [ + Container( + width: 50, + child: Button( + ApplicationLocalizations.of(context) + .translate(i18.common.VIEW), + () { + if (reportProvider.selectedBillYear == null) { + Notifiers.getToastMessage( + context, + '${ApplicationLocalizations.of(context).translate(i18.common.SELECT_BILLING_CYCLE)}', + 'ERROR'); + } else { + reportProvider.clearTableData(); + reportProvider.getLeadgerReport(); + widget.onViewClick( + true, i18.dashboard.LEDGER_REPORTS); + } + }, + key: Keys.billReport.LEDGER_REPORT_VIEW_BUTTON, + ), + ), + SizedBox( + width: 10, + ), + TextButton.icon( + onPressed: () { + if (reportProvider.selectedBillYear == null) { + Notifiers.getToastMessage( + context, + '${ApplicationLocalizations.of(context).translate(i18.common.SELECT_BILLING_CYCLE)}', + 'ERROR'); + } else { + reportProvider.getLeadgerReport(download: true); + } + }, + icon: Icon(Icons.download_sharp), + label: Text(ApplicationLocalizations.of(context) + .translate(i18.common.CORE_DOWNLOAD))), + ], + ), + ], + ), + ], + ), + ); + }); + }); + } +} diff --git a/frontend/mgramseva/lib/screeens/leadger_report/ledger_report.dart b/frontend/mgramseva/lib/screeens/leadger_report/ledger_report.dart new file mode 100644 index 000000000..4eaf8c29f --- /dev/null +++ b/frontend/mgramseva/lib/screeens/leadger_report/ledger_report.dart @@ -0,0 +1,251 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:mgramseva/model/connection/water_connection.dart'; +import 'package:mgramseva/routers/routers.dart'; +import 'package:mgramseva/screeens/leadger_report/leadger_view.dart'; +import 'package:mgramseva/screeens/reports/expense_bill_report.dart'; +import 'package:mgramseva/screeens/reports/inactive_consumer_report.dart'; +import 'package:mgramseva/screeens/reports/leadger_table.dart'; +import 'package:mgramseva/screeens/reports/vendor_report.dart'; +import 'package:mgramseva/screeens/reports/view_table.dart'; +import 'package:mgramseva/widgets/sub_label.dart'; +import 'package:provider/provider.dart'; + +import '../../providers/reports_provider.dart'; +import '../../utils/global_variables.dart'; +import '../../utils/localization/application_localizations.dart'; +import '../../utils/testing_keys/testing_keys.dart'; +import '../../widgets/custom_app_bar.dart'; +import '../../widgets/drawer_wrapper.dart'; +import 'package:mgramseva/utils/constants/i18_key_constants.dart'; +import '../../widgets/footer.dart'; +import '../../widgets/home_back.dart'; +import '../../widgets/label_text.dart'; +import '../../widgets/select_field_builder.dart'; +import '../../widgets/side_bar.dart'; +import '../reports/bill_report.dart'; +import '../reports/collection_report.dart'; + +class LeadgerReport extends StatefulWidget { + final WaterConnection? waterConnection; + LeadgerReport({Key? key, this.waterConnection}) : super(key: key); + + @override + State createState() { + return _LeadgerReport(); + } +} + +class _LeadgerReport extends State + with SingleTickerProviderStateMixin { + ScrollController scrollController = ScrollController(); + var takeScreenShot = false; + bool viewTable = false; + String tableTitle = 'Table Data'; + + @override + void dispose() { + var reportsProvider = Provider.of( + navigatorKey.currentContext!, + listen: false); + reportsProvider.clearBillingSelection(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => afterViewBuild()); + } + + afterViewBuild() { + var reportsProvider = Provider.of( + navigatorKey.currentContext!, + listen: false); + if (widget.waterConnection == null) { + Navigator.pushNamed(context, Routes.HOUSEHOLD_REGISTER, arguments: {}); + } + reportsProvider.getFinancialYearList(); + reportsProvider.clearBillingSelection(); + reportsProvider.clearBuildTableData(); + reportsProvider.clearTableData(); + Future.delayed(Duration(milliseconds: 500), () async { + reportsProvider.updateConsumerCode(widget.waterConnection?.connectionNo); + var selectedItem = reportsProvider + .getFinancialYearListDropdown(reportsProvider.billingYearList); + reportsProvider.updateSelectedBillYear(selectedItem.first); + reportsProvider.getLeadgerReport(); + showTable(true, i18.dashboard.LEDGER_REPORTS); + }); + } + + showTable(bool status, String title) { + setState(() { + viewTable = status; + tableTitle = title; + }); + } + + backButtonCallback() { + var reportProvider = Provider.of( + navigatorKey.currentContext!, + listen: false); + if (viewTable == true) { + viewTable = false; + reportProvider.clearBuildTableData(); + } else if (viewTable == false) { + reportProvider.clearBuildTableData(); + Navigator.pop(context); + } + } + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + appBar: CustomAppBar(), + drawer: DrawerWrapper( + Drawer(child: SideBar()), + ), + backgroundColor: Color.fromRGBO(238, 238, 238, 1), + body: LayoutBuilder( + builder: (context, constraints) => Container( + alignment: Alignment.center, + margin: constraints.maxWidth < 760 + ? null + : EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width / 25), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + color: Color.fromRGBO(238, 238, 238, 1), + margin: constraints.maxWidth < 760 + ? null + : EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width / 95), + height: constraints.maxHeight, + child: SingleChildScrollView( + controller: scrollController, + child: viewTable + ? Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HomeBack( + callback: () { + setState(() { + viewTable = false; + }); + }, + ), + LeadgerTable( + tableTitle: tableTitle, + scrollController: scrollController, + waterConnection: widget.waterConnection, + ), + ], + )) + : Column( + children: [ + HomeBack(), + Card( + margin: EdgeInsets.only(bottom: 2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0.0), + ), + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + LabelText(i18.dashboard.LEDGER_REPORTS), + ])), + SizedBox( + height: 30, + ), + Card( + margin: EdgeInsets.only(bottom: 2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + ), + child: Padding( + padding: const EdgeInsets.only( + top: 15, bottom: 20.0), + child: Column( + children: [ + Consumer( + builder: (_, reportProvider, child) { + return Container( + child: Column( + children: [ + SelectFieldBuilder( + i18.demandGenerate + .BILLING_YEAR_LABEL, + reportProvider.selectedBillYear, + '', + '', + reportProvider.onChangeOfBillYear, + reportProvider + .getFinancialYearListDropdown( + reportProvider + .billingYearList), + true, + readOnly: false, + controller: reportProvider + .billingyearCtrl, + key: Keys.billReport + .BILL_REPORT_BILLING_YEAR, + itemAsString: (i) => + "${ApplicationLocalizations.of(context).translate(i.financialYear)}", + ), + ], + ), + ); + }), + ], + ), + ), + ), + SizedBox( + height: 30, + ), + Card( + margin: EdgeInsets.only(top: 15, bottom: 2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), + ), + child: Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Column( + children: [ + Consumer( + builder: (_, reportProvider, child) { + return SubLabelText( + "${i18.common.LEDGER_CUSTOMER_NAME} : ${widget.waterConnection?.connectionHolders?.first.name}"); + }), + Consumer( + builder: (_, reportProvider, child) { + return SubLabelText( + "${i18.common.LEDGER_CONN_ID} : ${widget.waterConnection?.connectionNo}"); + }), + LeadgerReportView(onViewClick: showTable), + ], + ), + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Footer()) + ], + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/mgramseva/lib/screeens/reports/leadger_table.dart b/frontend/mgramseva/lib/screeens/reports/leadger_table.dart new file mode 100644 index 000000000..49d1e6a90 --- /dev/null +++ b/frontend/mgramseva/lib/screeens/reports/leadger_table.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:mgramseva/model/connection/water_connection.dart'; +import 'package:mgramseva/utils/constants/i18_key_constants.dart'; +import 'package:provider/provider.dart'; +import '../../providers/reports_provider.dart'; +import '../../utils/localization/application_localizations.dart'; +import '../../widgets/label_text.dart'; +import '../../widgets/pagination.dart'; +import '../../widgets/sub_label.dart'; +import 'generic_report_table.dart'; + +class LeadgerTable extends StatelessWidget { + final ScrollController scrollController; + final String tableTitle; + final WaterConnection? waterConnection; + LeadgerTable( + {required this.tableTitle, + required this.scrollController, + this.waterConnection}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, constraints) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Card( + margin: EdgeInsets.only(bottom: 2), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0.0), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + LabelText( + '${ApplicationLocalizations.of(context).translate(tableTitle)}'), + Consumer( + builder: (_, reportProvider, child) { + return SubLabelText( + "${i18.common.LEDGER_CUSTOMER_NAME} : ${waterConnection?.connectionHolders?.first.name}"); + }), + Consumer( + builder: (_, reportProvider, child) { + if (constraints.maxWidth < 760) { + return Column( + children: [ + SubLabelText( + "${i18.common.LEDGER_CONN_ID} : ${waterConnection?.connectionNo}"), + SubLabelText( + "${i18.common.LEDGER_OLD_CONN_ID} : ${waterConnection?.oldConnectionNo}"), + ], + ); + } else { + return Row( + children: [ + SubLabelText( + "${i18.common.LEDGER_CONN_ID} : ${waterConnection?.connectionNo}"), + SubLabelText( + "${i18.common.LEDGER_OLD_CONN_ID} : ${waterConnection?.oldConnectionNo}"), + ], + ); + } + }), + ])), + SizedBox( + height: 30, + ), + Container( + child: + Consumer(builder: (_, reportProvider, child) { + var width = constraints.maxWidth < 760 + ? 115.0 + : (constraints.maxWidth / 6); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GenericReportTable( + reportProvider.genericTableData, + scrollController: scrollController, + ), + Container( + width: width * + reportProvider + .genericTableData.tableHeaders.length + + 2, + child: Visibility( + visible: + reportProvider.genericTableData.tableData.isNotEmpty, + child: Pagination( + limit: reportProvider.limit, + offSet: reportProvider.offset, + callBack: (pageResponse) => + reportProvider.onChangeOfPageLimit( + pageResponse, tableTitle, context), + isTotalCountVisible: false, + totalCount: + reportProvider.genericTableData.tableData.length, + ), + ), + ) + ], + ); + }), + ), + ], + ); + }); + } +} diff --git a/frontend/mgramseva/lib/services/mdms.dart b/frontend/mgramseva/lib/services/mdms.dart index e344c48b7..be33a8177 100644 --- a/frontend/mgramseva/lib/services/mdms.dart +++ b/frontend/mgramseva/lib/services/mdms.dart @@ -194,4 +194,4 @@ Map getTenantFinancialYearList(String tenantId) { ] } }; -} \ No newline at end of file +} diff --git a/frontend/mgramseva/lib/services/urls.dart b/frontend/mgramseva/lib/services/urls.dart index 5fbee2fd2..009b296d4 100644 --- a/frontend/mgramseva/lib/services/urls.dart +++ b/frontend/mgramseva/lib/services/urls.dart @@ -91,6 +91,7 @@ class Url { 'adapter-master-data/project/v1/_search'; ///Reports + static const String LEDGER_REPORT = 'ws-services/wc/ledger-report'; static const String BILL_REPORT = 'ws-services/wc/_billReport'; static const String COLLECTION_REPORT = 'ws-services/wc/_collectionReport'; static const String INACTIVE_CONSUMER_REPORT = diff --git a/frontend/mgramseva/lib/utils/constants.dart b/frontend/mgramseva/lib/utils/constants.dart index ee062d867..f33bdd7c1 100644 --- a/frontend/mgramseva/lib/utils/constants.dart +++ b/frontend/mgramseva/lib/utils/constants.dart @@ -104,6 +104,11 @@ class Constants { (i18.dashboard.CORE_REPORTS), Icons.assessment, Routes.REPORTS, {}), + // HomeItem( + // "LEDGER_REPORTS", + // (i18.dashboard.LEDGER_REPORTS), + // Icons.table_chart_rounded, + // Routes.LEDGER_REPORTS, {}), ]; static List SERVICECATEGORY = [ diff --git a/frontend/mgramseva/lib/utils/constants/i18_key_constants.dart b/frontend/mgramseva/lib/utils/constants/i18_key_constants.dart index 5f6445386..4e429a44e 100644 --- a/frontend/mgramseva/lib/utils/constants/i18_key_constants.dart +++ b/frontend/mgramseva/lib/utils/constants/i18_key_constants.dart @@ -186,6 +186,25 @@ class Common { String get FILE_SIZE => 'FILE_SIZE'; String get CHOOSE_AN_ACTION => 'CHOOSE_AN_ACTION'; + // Leadger + String get LEDGER_MONTH => 'LEDGER_MONTH'; + String get LEDGER_DEMAND_GENERATION_DATE => 'LEDGER_DEMAND_GENERATION_DATE'; + String get LEDGER_MONTHLY_CHARGE => 'LEDGER_MONTHLY_CHARGE'; + String get LEDGER_PREV_MONTH_BALANCE => 'LEDGER_PREV_MONTH_BALANCE'; + String get LEDGER_TOTAL_DUE => 'LEDGER_TOTAL_DUE'; + String get LEDGER_DUE_DATE_PAYMENT => 'LEDGER_DUE_DATE_PAYMENT'; + String get LEDGER_DATE => 'LEDGER_DATE'; + String get LEDGER_RECIPET_NO => 'LEDGER_RECIPET_NO'; + String get LEDGER_AMOUNT => 'LEDGER_AMOUNT'; + String get LEDGER_BALANCE => 'LEDGER_BALANCE'; + String get LEDGER_PENALTY_APPLIED_ON_DATE => 'LEDGER_PENALTY_APPLIED_ON_DATE'; + String get LEDGER_PENALTY => 'LEDGER_PENALTY'; + String get LEDGER_BALANCE_FOR_THE_MONH => 'LEDGER_BALANCE_FOR_THE_MONH'; + String get LEDGER_CUSTOMER_NAME => 'LEDGER_CUSTOMER_NAME'; + String get LEDGER_CONN_ID => 'LEDGER_CONN_ID'; + String get LEDGER_OLD_CONN_ID => 'LEDGER_OLD_CONN_ID'; + // Leadger + ///Months String get JAN => 'JAN'; String get FEB => 'FEB '; @@ -715,6 +734,7 @@ class _DashBoard { 'CORE_GPWSC_DETAILS_AND_RATE_INFO'; String get GPWSC_DETAILS => 'GPWSC_DETAILS'; String get CORE_REPORTS => 'CORE_REPORTS'; + String get LEDGER_REPORTS => 'LEDGER_REPORTS'; String get BILL_REPORT => 'BILL_REPORT'; String get COLLECTION_REPORT => 'COLLECTION_REPORT'; String get VENDOR_REPORT => 'VENDOR_REPORT'; diff --git a/frontend/mgramseva/lib/utils/date_formats.dart b/frontend/mgramseva/lib/utils/date_formats.dart index ef1844984..ae751def0 100644 --- a/frontend/mgramseva/lib/utils/date_formats.dart +++ b/frontend/mgramseva/lib/utils/date_formats.dart @@ -43,6 +43,17 @@ class DateFormats { } } + static String leadgerTimeStampToDate(int? timeInMillis, {String? format}) { + if (timeInMillis == null || timeInMillis == 0) return '-'; + try { + var date = DateTime.fromMillisecondsSinceEpoch(timeInMillis); + return DateFormat('dd-MMM-yyyy').format(date); + + } catch (e) { + return ''; + } +} + static String getTime(String date) { if (date.trim().isEmpty) return ''; try { diff --git a/frontend/mgramseva/lib/utils/models.dart b/frontend/mgramseva/lib/utils/models.dart index 210843c1d..2d2e30f9a 100644 --- a/frontend/mgramseva/lib/utils/models.dart +++ b/frontend/mgramseva/lib/utils/models.dart @@ -78,7 +78,8 @@ class TableData { final TextStyle? style; final String? apiKey; ValueChanged? callBack; - TableData(this.label, {this.style, this.callBack, this.apiKey}); + ValueChanged? iconButtonCallBack; + TableData(this.label, {this.style, this.callBack,this. iconButtonCallBack, this.apiKey}); } class SortBy { diff --git a/frontend/mgramseva/lib/utils/testing_keys/testing_keys.dart b/frontend/mgramseva/lib/utils/testing_keys/testing_keys.dart index 1d46ec94c..4f247a43a 100644 --- a/frontend/mgramseva/lib/utils/testing_keys/testing_keys.dart +++ b/frontend/mgramseva/lib/utils/testing_keys/testing_keys.dart @@ -135,6 +135,7 @@ class HouseholdKeys { class BillReportKeys { const BillReportKeys(); Key get BILL_REPORT_VIEW_BUTTON => Key("bill_report_view_button"); + Key get LEDGER_REPORT_VIEW_BUTTON => Key("bill_report_view_button"); Key get BILL_REPORT_DOWNLOAD_BUTTON => Key("bill_report_download_button"); Key get COLLECTION_REPORT_VIEW_BUTTON => Key("collection_report_view_button"); Key get INACTIVE_CONSUMER_REPORT_VIEW_BUTTON => diff --git a/frontend/mgramseva/lib/widgets/select_field_builder.dart b/frontend/mgramseva/lib/widgets/select_field_builder.dart index d7b74773d..f64556daa 100644 --- a/frontend/mgramseva/lib/widgets/select_field_builder.dart +++ b/frontend/mgramseva/lib/widgets/select_field_builder.dart @@ -159,6 +159,7 @@ class SelectFieldBuilderState extends State { return DropdownSearch( key: widget.suggestionKey, selectedItem: widget.value, + itemAsString: widget.itemAsString, items: widget.options, onChanged: widget.widget, diff --git a/frontend/micro-ui/web/.babelrc b/frontend/micro-ui/web/.babelrc index 5f90443d1..10bdb6405 100644 --- a/frontend/micro-ui/web/.babelrc +++ b/frontend/micro-ui/web/.babelrc @@ -1,5 +1,9 @@ { - "presets": [ - "@babel/preset-env","@babel/preset-react" - ] - } \ No newline at end of file + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ], + "plugins": [ + "@babel/plugin-proposal-optional-chaining" + ] +} \ No newline at end of file diff --git a/frontend/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js b/frontend/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js index 4addde2b4..07152552d 100644 --- a/frontend/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js +++ b/frontend/micro-ui/web/micro-ui-internals/example/src/UICustomizations.js @@ -8,11 +8,19 @@ var Digit = window.Digit || {}; function anonymizeHalfString(input) { - // Calculate the midpoint of the string - const midpoint = Math.ceil(input.length / 2); - - // Replace the first 50% of the string with asterisks - const anonymized = "*".repeat(midpoint) + input.substring(midpoint); + // Initialize an empty string to store the anonymized output + let anonymized = ""; + // Loop through each character in the input string + for (let i = 0; i < input.length; i++) { + // Check if the index (i) is even (0, 2, 4, ...) + if (i % 2 === 0) { + // Append the original character (keep it) + anonymized += input[i]; + } else { + // Append an asterisk to mask the alternate character + anonymized += "*"; + } + } return anonymized; } diff --git a/frontend/micro-ui/web/micro-ui-internals/package.json b/frontend/micro-ui/web/micro-ui-internals/package.json index 2f6b4f69d..f273694bb 100644 --- a/frontend/micro-ui/web/micro-ui-internals/package.json +++ b/frontend/micro-ui/web/micro-ui-internals/package.json @@ -16,8 +16,8 @@ "node": ">=14" }, "scripts": { - "start": "SKIP_PREFLIGHT_CHECK=true run-s build start:dev", - "sprint": "SKIP_PREFLIGHT_CHECK=true run-s start:script", + "start": "SKIP_PREFLIGHT_CHECK=true run-s build start:dev", + "sprint": "SKIP_PREFLIGHT_CHECK=true run-s start:script", "start:dev": "run-p dev:**", "start:script": "./scripts/create.sh", "dev:css": "cd packages/css && yarn start", diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss b/frontend/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss index 5aad56dd9..759978759 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss +++ b/frontend/micro-ui/web/micro-ui-internals/packages/css/src/pages/employee/index.scss @@ -350,6 +350,47 @@ } } +.dropdown-user .dropbtn{ + color: white; + font-size: 1rem; + margin: 10px; + background-color: #efefef00; +} +.dropdown-user { + position: relative; /* Make the dropdown relative to its container */ + display: inline-block; +} + +.dropdown-user-overlay { + position: absolute; /* Position the overlay absolutely relative to the dropdown */ + top: 100%; /* Position the overlay below the button */ + left: 0; /* Align the overlay to the left of the button */ + background-color: #f1f1f1; /* Set background color */ + min-width: 160px; /* Set minimum width */ + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); /* Add shadow */ + z-index: 1; /* Set z-index to display on top of other elements */ + display: none; /* Hide by default */ +} + +.dropdown-user-content { + padding: 0; /* Remove default padding from ul */ + list-style: none; /* Remove default list style */ +} + +.dropdown-user-content li { + border-bottom: solid 1px !important; + border-color: black !important; + padding: 12px 12px; /* Add padding to list items */ +} +.dropdown-user-link { + text-decoration: none !important; /* Remove underline from links inside list items */ +} + +.dropdown-user:hover .dropdown-user-overlay { + display: block; /* Show overlay on hover */ +} + + .RightMostTopBarOptions { @apply flex; .EventNotificationWrapper { @@ -369,6 +410,9 @@ fill: theme(colors.white); } } + display: flex; + justify-content: center; + align-items: center; } @media (min-width: 640px) { @@ -477,8 +521,24 @@ .hamburger-span { display: none; } + .city{ + height: 48px !important; + width: 48px !important; + padding: 0px !important; + } + } + } + + .hambuger-back-wrapper .city{ + object-fit: scale-down !important; + border-radius: 5px !important; + padding: 1px 15px !important; + } + + + } @screen dt { diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/elements/MDMS.js b/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/elements/MDMS.js index c7d1037a8..cca16d144 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/elements/MDMS.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/elements/MDMS.js @@ -63,6 +63,25 @@ const initRequestBody = (tenantId) => ({ ], }, }); +const initRequestBodyWithOutTenent = (tenantId) => ({ + MdmsCriteria: { + tenantId, + moduleDetails: [ + { + moduleName: "common-masters", + masterDetails: [{ name: "Department" }, { name: "Designation" }, { name: "StateInfo" }, { name: "wfSlaConfig" }, { name: "uiHomePage" }], + }, + { + moduleName: "tenant", + masterDetails: [{ name: "citymodule" }], + }, + { + moduleName: "DIGIT-UI", + masterDetails: [{ name: "ApiCachingSettings" }], + }, + ], + }, +}); const getCriteria = (tenantId, moduleDetails) => { return { @@ -1033,24 +1052,24 @@ const GetSlumLocalityMapping = (MdmsRes, tenantId) => MdmsRes["FSM"].Slum.filter((type) => type.active).reduce((prev, curr) => { return prev[curr.locality] ? { - ...prev, - [curr.locality]: [ - ...prev[curr.locality], - { - ...curr, - i18nKey: `${tenantId.toUpperCase().replace(".", "_")}_${curr.locality}_${curr.code}`, - }, - ], - } + ...prev, + [curr.locality]: [ + ...prev[curr.locality], + { + ...curr, + i18nKey: `${tenantId.toUpperCase().replace(".", "_")}_${curr.locality}_${curr.code}`, + }, + ], + } : { - ...prev, - [curr.locality]: [ - { - ...curr, - i18nKey: `${tenantId.toUpperCase().replace(".", "_")}_${curr.locality}_${curr.code}`, - }, - ], - }; + ...prev, + [curr.locality]: [ + { + ...curr, + i18nKey: `${tenantId.toUpperCase().replace(".", "_")}_${curr.locality}_${curr.code}`, + }, + ], + }; }, {}); const GetPropertyOwnerShipCategory = (MdmsRes) => @@ -1478,6 +1497,14 @@ export const MdmsService = { useCache: true, params: { tenantId: stateCode }, }), + initWithOutTenent: (stateCode) => + ServiceRequest({ + serviceName: "mdmsInit", + url: Urls.MDMS, + data: initRequestBodyWithOutTenent(stateCode), + useCache: true, + params: { tenantId: stateCode }, + }), call: (tenantId, details) => { return new Promise((resolve, reject) => debouncedCall( diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/molecules/Store/service.js b/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/molecules/Store/service.js index 6debb8dae..11df81db2 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/molecules/Store/service.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/libraries/src/services/molecules/Store/service.js @@ -58,6 +58,7 @@ export const StoreService = { const { MdmsRes } = await MdmsService.init(stateCode); const stateInfo = MdmsRes["common-masters"]?.StateInfo?.[0] || {}; const uiHomePage = MdmsRes["common-masters"]?.uiHomePage?.[0] || {}; + const localities = {}; const revenue_localities = {}; const initData = { @@ -80,22 +81,12 @@ export const StoreService = { initData.selectedLanguage = Digit.SessionStorage.get("locale") || initData?.languages[2] ? initData?.languages[2]?.value : initData?.languages[1]?.value; - ApiCacheService.saveSetting(MdmsRes["DIGIT-UI"]?.ApiCachingSettings); - - const moduleTenants = initData?.modules - .map((module) => module.tenants) - .flat() - .reduce((unique, ele) => (unique.find((item) => item.code === ele.code) ? unique : [...unique, ele]), []); initData.tenants = MdmsRes?.tenant?.tenants - // ?.filter((x) => x.pgrEnabled) .map((tenant) => ({ i18nKey: `TENANT_TENANTS_${tenant.code.replace(".", "_").toUpperCase()}`, ...tenant, })); - // .filter((item) => !!moduleTenants.find((mt) => mt.code === item.code)) - // .map((tenant) => ({ i18nKey: `TENANT_TENANTS_${tenant.code.replace(".", "_").toUpperCase()}`, ...tenant })); - await LocalizationService.getLocale({ modules: [`rainmaker-common`], locale: initData.selectedLanguage, diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/App.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/App.js index ab2535630..000cc725a 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/App.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/App.js @@ -3,7 +3,7 @@ import { Redirect, Route, Switch, useHistory, useLocation } from "react-router-d import CitizenApp from "./pages/citizen"; import EmployeeApp from "./pages/employee"; -export const DigitApp = ({ stateCode, modules, appTenants, logoUrl, initData ,defaultLanding="citizen"}) => { +export const DigitApp = ({ stateCode, modules, appTenants, logoUrl, initData, defaultLanding = "citizen" }) => { const history = useHistory(); const { pathname } = useLocation(); const innerWidth = window.innerWidth; @@ -11,7 +11,7 @@ export const DigitApp = ({ stateCode, modules, appTenants, logoUrl, initData ,de const userDetails = Digit.UserService.getUser(); const { data: storeData } = Digit.Hooks.useStore.getInitData(); const { stateInfo } = storeData || {}; - + const DSO = Digit.UserService.hasAccess(["FSM_DSO"]); let CITIZEN = userDetails?.info?.type === "CITIZEN" || !window.location.pathname.split("/").includes("employee") ? true : false; diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/Module.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/Module.js index 95a29d987..ca0d3d6c7 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/Module.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/Module.js @@ -11,7 +11,7 @@ import { useState } from "react"; import ErrorBoundary from "./components/ErrorBoundaries"; import getStore from "./redux/store"; -const DigitUIWrapper = ({ stateCode, enabledModules, moduleReducers,defaultLanding }) => { +const DigitUIWrapper = ({ stateCode, enabledModules, moduleReducers, defaultLanding }) => { const { isLoading, data: initData } = Digit.Hooks.useInitStore(stateCode, enabledModules); if (isLoading) { return ; @@ -36,7 +36,7 @@ const DigitUIWrapper = ({ stateCode, enabledModules, moduleReducers,defaultLandi ); }; -export const DigitUI = ({ stateCode, registry, enabledModules, moduleReducers ,defaultLanding}) => { +export const DigitUI = ({ stateCode, registry, enabledModules, moduleReducers, defaultLanding }) => { const [privacy, setPrivacy] = useState(Digit.Utils.getPrivacyObject() || {}); const userType = Digit.UserService.getType(); const queryClient = new QueryClient({ @@ -98,7 +98,7 @@ export const DigitUI = ({ stateCode, registry, enabledModules, moduleReducers ,d }, }} > - + diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/components/ChangeCity.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/components/ChangeCity.js index c41abeb61..a52ec9415 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/components/ChangeCity.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/core/src/components/ChangeCity.js @@ -10,30 +10,24 @@ const stringReplaceAll = (str = "", searcher = "", replaceWith = "") => { return str; }; - - const ChangeCity = (prop) => { const [dropDownData, setDropDownData] = useState({ label: `TENANT_TENANTS_${stringReplaceAll(Digit.SessionStorage.get("Employee.tenantId"), ".", "_")?.toUpperCase()}`, value: Digit.SessionStorage.get("Employee.tenantId"), }); const [selectCityData, setSelectCityData] = useState([]); - const [selectedCity, setSelectedCity] = useState([]); //selectedCities?.[0]?.value const history = useHistory(); const isDropdown = prop.dropdown || false; let selectedCities = []; - const uuids = [prop.userDetails?.info?.uuid]; - const { data: userData, isUserDataLoading } = Digit.Hooks.useUserSearch(Digit.ULBService.getStateId(), { uuid: uuids }, {}); - // setSelectedCity(userData?.data?.user[0]?.roles) - - - const { data: data = {}, isLoading } = + const uuids = [prop.userDetails?.info?.uuid]; + const { data: userData, isUserDataLoading } = Digit.Hooks.useUserSearch(Digit.ULBService.getStateId(), { uuid: uuids }, {}); + const { data: mdmsData = {}, isLoading: isMdmsLoading } = Digit.Hooks.hrms.useHrmsMDMS(Digit.ULBService.getCurrentTenantId(), "egov-hrms", "HRMSRolesandDesignation") || {}; const handleChangeCity = (city) => { const loggedInData = Digit.SessionStorage.get("citizen.userRequestObject"); - const filteredRoles = Digit.SessionStorage.get("citizen.userRequestObject")?.info?.roles?.filter((role) => role.tenantId === city.value); + const filteredRoles = loggedInData?.info?.roles?.filter((role) => role.tenantId === city.value); if (filteredRoles?.length > 0) { loggedInData.info.roles = filteredRoles; loggedInData.info.tenantId = city?.value; @@ -50,39 +44,40 @@ const ChangeCity = (prop) => { }; useEffect(() => { - const userloggedValues = Digit.SessionStorage.get("citizen.userRequestObject"); - let teantsArray = [],filteredArray = []; - userData?.user[0].roles?.forEach((role) => teantsArray.push(role.tenantId)); - let unique = teantsArray.filter((item, i, ar) => ar.indexOf(item) === i); - unique?.forEach((uniCode) => { + const tenantId = Digit.SessionStorage.get("Employee.tenantId"); + + if (!tenantId || !mdmsData?.MdmsRes?.["tenant"]["tenants"] || isUserDataLoading || isMdmsLoading) { + return; + } + + const tenantIds = userData?.user[0].roles?.map((role) => role.tenantId); + + const filteredArray = mdmsData.MdmsRes["tenant"]["tenants"].filter((item) => { + if (item.code !== "pb") { // Exclude "pb" tenants + return tenantIds.includes(item.code); + } else { + return item.code === tenantId; // Include "pb" tenants matching tenantId + } + }).map((item) => ({ + label: item.code !== "pb" + ? `${prop?.t(Digit.Utils.locale.convertToLocale(item?.divisionCode, "EGOV_LOCATION_DIVISION"))} - ${prop?.t( + `TENANT_TENANTS_${stringReplaceAll(item.code, ".", "_")?.toUpperCase()}` + )}` + : `TENANT_TENANTS_${stringReplaceAll(item.code, ".", "_")?.toUpperCase()}`, + value: item.code, + })); - data?.MdmsRes?.["tenant"]["tenants"]?.map((items) => { - if (items?.code !== "pb" && items?.code === uniCode) { - filteredArray.push({ - label: `${prop?.t(Digit.Utils.locale.convertToLocale(items?.divisionCode, "EGOV_LOCATION_DIVISION"))} - ${prop?.t( - `TENANT_TENANTS_${stringReplaceAll(uniCode, ".", "_")?.toUpperCase()}` - )}`, - value: uniCode, - }); - } else if (items?.code === "pb" && items?.code === uniCode) { - filteredArray.push({ - label: `TENANT_TENANTS_${stringReplaceAll(uniCode, ".", "_")?.toUpperCase()}`, - value: uniCode, - }); - } - }); - }); - selectedCities = filteredArray?.filter((select) => select.value == Digit.SessionStorage.get("Employee.tenantId")); setSelectCityData(filteredArray); + selectedCities = filteredArray.filter((select) => select.value === tenantId); - }, [dropDownData, data?.MdmsRes]); + }, [dropDownData, mdmsData?.MdmsRes, userData, isUserDataLoading, isMdmsLoading]); return (
0 ? selectCityData : [{ label: "Loading...", value: "" }]} selected={dropDownData} optionKey={"label"} select={handleChangeCity} @@ -90,7 +85,6 @@ const ChangeCity = (prop) => { />
); - }; -export default ChangeCity; \ No newline at end of file +export default ChangeCity; diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/Module.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/Module.js index 614e1ec81..563a39ca6 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/Module.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/Module.js @@ -8,6 +8,7 @@ import HRBanner from "./components/pageComponents/Banner"; import SelectDateofBirthEmployment from "./components/pageComponents/EmployeeDOB"; import SelectEmployeePhoneNumber from "./components/pageComponents/EmployeePhoneNumber"; import Jurisdictions from "./components/pageComponents/jurisdiction"; +import SelectUserTypeAndDesignation from "./components/pageComponents/SelectUserTypeAndDesignation"; import SelectDateofEmployment from "./components/pageComponents/SelectDateofEmployment"; import SelectEmployeeEmailId from "./components/pageComponents/SelectEmailId"; import SelectEmployeeCorrespondenceAddress from "./components/pageComponents/SelectEmployeeCorrespondenceAddress"; @@ -44,6 +45,7 @@ const componentsToRegister = { SelectEmployeeName, SelectEmployeeId, Jurisdictions, + SelectUserTypeAndDesignation, Assignments, ActionModal, HRBanner, diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/InboxFilter.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/InboxFilter.js index 00b059fd8..1e6ae1ebf 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/InboxFilter.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/InboxFilter.js @@ -136,7 +136,8 @@ const Filter = ({ searchParams, onFilterChange, onSearch, removeParam, ...props const roleCodesToFilter = ["HRMS_ADMIN", "DIV_ADMIN", "MDMS_ADMIN", "LOC_ADMIN", "SYSTEM"]; // Use the filter method to extract roles with the specified codes const roles = data?.MdmsRes?.["ws-services-masters"]?.WSServiceRoles?.filter((role) => { - return !roleCodesToFilter.includes(role.code); + return !roleCodesToFilter.includes(role.code) && + (role?.name === "Secretary" || role?.name === "Sarpanch" || role?.name === "Revenue Collector"); })?.map((role) => { return { code: role.code, name: role?.name ? role?.name : " ", i18text: "ACCESSCONTROL_ROLES_ROLES_" + role.code }; }); diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/Modal/EmployeeAppliaction.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/Modal/EmployeeAppliaction.js index c49e4de32..0148f4bef 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/Modal/EmployeeAppliaction.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/Modal/EmployeeAppliaction.js @@ -58,7 +58,7 @@ export const configEmployeeApplication = ({ t, action, selectFile, uploadedFile, ), }, - + { label: t("HR_REMARKS"), type: "text", diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/MultiSelectDropdown.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/MultiSelectDropdown.js index 87a3fcee4..ad1472599 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/MultiSelectDropdown.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/MultiSelectDropdown.js @@ -2,19 +2,19 @@ import React, { useEffect, useReducer, useRef, useState } from "react"; import { ArrowDown, CheckSvg } from "@egovernments/digit-ui-react-components"; import { useTranslation } from "react-i18next"; -const MultiSelectDropdown = ({ options, optionsKey, selected = [], onSelect, defaultLabel = "", defaultUnit = "",BlockNumber=1,isOBPSMultiple=false,props={},isPropsNeeded=false,ServerStyle={}, isSurvey=false,placeholder, disable=false,config}) => { +const MultiSelectDropdown = ({ options, optionsKey, selected = [], onSelect, defaultLabel = "", defaultUnit = "", BlockNumber = 1, isOBPSMultiple = false, props = {}, isPropsNeeded = false, ServerStyle = {}, isSurvey = false, placeholder, disable = false, config }) => { const [active, setActive] = useState(false); const [searchQuery, setSearchQuery] = useState(); const [optionIndex, setOptionIndex] = useState(-1); const dropdownRef = useRef(); const { t } = useTranslation(); - function reducer(state, action){ - switch(action.type){ + function reducer(state, action) { + switch (action.type) { case "ADD_TO_SELECTED_EVENT_QUEUE": - return [...state, {[optionsKey]: action.payload?.[1]?.[optionsKey], propsData: action.payload} ] + return [...state, { [optionsKey]: action.payload?.[1]?.[optionsKey], propsData: action.payload }] case "REMOVE_FROM_SELECTED_EVENT_QUEUE": - const newState = state.filter( e => e?.[optionsKey] !== action.payload?.[1]?.[optionsKey]) + const newState = state.filter(e => e?.[optionsKey] !== action.payload?.[1]?.[optionsKey]) onSelect(newState.map((e) => e.propsData), props); return newState case "REPLACE_COMPLETE_STATE": @@ -25,115 +25,115 @@ const MultiSelectDropdown = ({ options, optionsKey, selected = [], onSelect, def } useEffect(() => { - dispatch({type: "REPLACE_COMPLETE_STATE", payload: fnToSelectOptionThroughProvidedSelection(selected) }) - },[selected?.length, selected?.[0]?.code]) + dispatch({ type: "REPLACE_COMPLETE_STATE", payload: fnToSelectOptionThroughProvidedSelection(selected) }) + }, [selected?.length, selected?.[0]?.code]) - function fnToSelectOptionThroughProvidedSelection(selected){ - return selected?.map( e => ({[optionsKey]: e?.[optionsKey], propsData: [null, e]})) + function fnToSelectOptionThroughProvidedSelection(selected) { + return selected?.map(e => ({ [optionsKey]: e?.[optionsKey], propsData: [null, e] })) } const [alreadyQueuedSelectedState, dispatch] = useReducer(reducer, selected, fnToSelectOptionThroughProvidedSelection) - - useEffect(()=> { - if(!active){ - onSelect(alreadyQueuedSelectedState?.map( e => e.propsData), props) + + useEffect(() => { + if (!active) { + onSelect(alreadyQueuedSelectedState?.map(e => e.propsData), props) } - },[active]) + }, [active]) - function handleOutsideClickAndSubmitSimultaneously(){ + function handleOutsideClickAndSubmitSimultaneously() { setActive(false) } - Digit.Hooks.useClickOutside(dropdownRef, handleOutsideClickAndSubmitSimultaneously , active, {capture: true} ); + Digit.Hooks.useClickOutside(dropdownRef, handleOutsideClickAndSubmitSimultaneously, active, { capture: true }); const filtOptns = - searchQuery?.length > 0 ? options.filter((option) => t(option[optionsKey]&&typeof option[optionsKey]=="string" && option[optionsKey].toUpperCase()).toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0) : options; - + searchQuery?.length > 0 ? options.filter((option) => t(option[optionsKey] && typeof option[optionsKey] == "string" && option[optionsKey].toUpperCase()).toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0) : options; + function onSearch(e) { setSearchQuery(e.target.value); } - function onSelectToAddToQueue(...props){ + function onSelectToAddToQueue(...props) { const isChecked = arguments[0].target.checked - isChecked ? dispatch({type: "ADD_TO_SELECTED_EVENT_QUEUE", payload: arguments }) : dispatch({type: "REMOVE_FROM_SELECTED_EVENT_QUEUE", payload: arguments }) + isChecked ? dispatch({ type: "ADD_TO_SELECTED_EVENT_QUEUE", payload: arguments }) : dispatch({ type: "REMOVE_FROM_SELECTED_EVENT_QUEUE", payload: arguments }) } -/* Custom function to scroll and select in the dropdowns while using key up and down */ - const keyChange = (e) => { + /* Custom function to scroll and select in the dropdowns while using key up and down */ + const keyChange = (e) => { if (e.key == "ArrowDown") { - setOptionIndex(state =>state+1== filtOptns.length?0:state+1); - if(optionIndex+1== filtOptns.length){ - e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(0,0) - }else{ - optionIndex>2&& e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0,45) + setOptionIndex(state => state + 1 == filtOptns.length ? 0 : state + 1); + if (optionIndex + 1 == filtOptns.length) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(0, 0) + } else { + optionIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, 45) } e.preventDefault(); } else if (e.key == "ArrowUp") { - setOptionIndex(state => state!==0? state - 1: filtOptns.length-1); - if(optionIndex===0){ - e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(100000,100000) - }else{ - optionIndex>2&&e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0,-45) - } + setOptionIndex(state => state !== 0 ? state - 1 : filtOptns.length - 1); + if (optionIndex === 0) { + e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollTo?.(100000, 100000) + } else { + optionIndex > 2 && e?.target?.parentElement?.parentElement?.children?.namedItem("jk-dropdown-unique")?.scrollBy?.(0, -45) + } e.preventDefault(); - }else if(e.key=="Enter"){ - onSelectToAddToQueue(e,filtOptns[optionIndex]); - } + } else if (e.key == "Enter") { + onSelectToAddToQueue(e, filtOptns[optionIndex]); + } } const MenuItem = ({ option, index }) => ( -
+
selectedOption[optionsKey] === option[optionsKey]) ? true : false} - onChange={(e) => isPropsNeeded?onSelectToAddToQueue(e, option,props):isOBPSMultiple?onSelectToAddToQueue(e, option,BlockNumber):onSelectToAddToQueue(e, option)} - style={{minWidth: "24px", width: "100%"}} + onChange={(e) => isPropsNeeded ? onSelectToAddToQueue(e, option, props) : isOBPSMultiple ? onSelectToAddToQueue(e, option, BlockNumber) : onSelectToAddToQueue(e, option)} + style={{ minWidth: "24px", width: "100%" }} disabled={option.isDisabled || false} />
- +

{t(option[optionsKey]&&typeof option[optionsKey]=="string" && option[optionsKey])}

+ opacity: 1, + backgroundColor: "rgba(238, 238, 238, var(--bg-opacity))" + } : {}} >{t(option[optionsKey] && typeof option[optionsKey] == "string" && option[optionsKey])}

); const Menu = () => { const filteredOptions = - searchQuery?.length > 0 ? options.filter((option) => t(option[optionsKey]&&typeof option[optionsKey]=="string" && option[optionsKey].toUpperCase()).toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0) : options; + searchQuery?.length > 0 ? options.filter((option) => t(option[optionsKey] && typeof option[optionsKey] == "string" && option[optionsKey].toUpperCase()).toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0) : options; return filteredOptions?.map((option, index) => ); }; return (
-
-
- setActive(true)} value={searchQuery} onChange={onSearch} placeholder={t(placeholder)} /> -
-

{alreadyQueuedSelectedState.length > 0 ? `${isSurvey? alreadyQueuedSelectedState?.filter((ob) => ob?.i18nKey !== undefined).length : alreadyQueuedSelectedState.length} ${defaultUnit}` : defaultLabel}

- +
+
+ setActive(true)} value={searchQuery} onChange={onSearch} placeholder={t(placeholder)} /> +
+

{alreadyQueuedSelectedState.length > 0 ? `${isSurvey ? alreadyQueuedSelectedState?.filter((ob) => ob?.i18nKey !== undefined).length : alreadyQueuedSelectedState.length} ${defaultUnit}` : defaultLabel}

+ +
+ {active ? ( +
+ +
+ ) : null} +
- {active ? ( -
- -
- ) : null} - -
- {config?.isDropdownWithChip ?
- {alreadyQueuedSelectedState.length > 0 && - alreadyQueuedSelectedState.map((value, index) => { - return onSelectToAddToQueue(e, value,props) - : (e) => onSelectToAddToQueue(e, value) - } />; - })} -
: null} + {config?.isDropdownWithChip ?
+ {alreadyQueuedSelectedState.length > 0 && + alreadyQueuedSelectedState.map((value, index) => { + return onSelectToAddToQueue(e, value, props) + : (e) => onSelectToAddToQueue(e, value) + } />; + })} +
: null}
); }; diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserForm.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserForm.js index 9e1a3a999..5fddd2542 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserForm.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserForm.js @@ -92,7 +92,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles { level: "code", value: 7, optionsKey: "name", isMandatory: false }, ]); const [tree, setTree] = useState(null); - const [rolesOptions,setRolesOptions] = useState(null) + const [rolesOptions, setRolesOptions] = useState(null) // const [zones,setZones] = useState([]) // const [circles,setCircles] = useState([]) // const [divisions,setDivisions] = useState([]) @@ -150,7 +150,11 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles const filteredResult = filterKeys(result, requiredKeys); const resultInTree = buildTree(filteredResult, hierarchy); const excludeCodes = ["HRMS_ADMIN", "LOC_ADMIN", "MDMS_ADMIN", "EMPLOYEE", "SYSTEM"]; - setRolesOptions(data?.MdmsRes?.["ws-services-masters"]?.["WSServiceRoles"]?.filter(row => !excludeCodes.includes(row?.code))) + setRolesOptions(data?.MdmsRes?.["ws-services-masters"]?.["WSServiceRoles"]?.filter(row => !excludeCodes.includes(row?.code) + && + (row?.name === "Secretary" || row?.name === "Sarpanch" || row?.name === "Revenue Collector" || row?.name === "DIVISION ADMIN") + )) + //updating to state roles as requested // setRolesOptions([ // // { @@ -178,7 +182,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles // name: "MDMS Admin", // description: "Mdms admin", // }, - + // ]) setTree(resultInTree); return result; @@ -211,7 +215,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles "sectionCode": "", "code": "", "roles": [] - }, + }, }); const formData = watch(); @@ -225,7 +229,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles "sectionCode": "", "code": "", "roles": [] - }); + }); setUniqueRoles(null); setUniqueTenants(null); @@ -260,7 +264,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles return; // Exit the loop early } }); - + if (areMandatoryFieldsNotFilled) { setShowToast({ warning: true, label: t("ES_COMMON_MIN_SEARCH_CRITERIA_MSG") }); setTimeout(closeToast, 5000); @@ -268,7 +272,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles } //checking roles - if(data?.roles?.length === 0 || !data?.roles){ + if (data?.roles?.length === 0 || !data?.roles) { setShowToast({ warning: true, label: t("ES_COMMON_MIN_SEARCH_CRITERIA_MSG") }); setTimeout(closeToast, 5000); return; @@ -298,7 +302,7 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles //this is the list of tenants under the current subtree const listOfUniqueTenants = getUniqueLeafCodes(currentLevel); setUniqueTenants(() => listOfUniqueTenants); - setUniqueRoles(() => data?.roles?.filter(row=>row.code)?.map(role=> role.code)); + setUniqueRoles(() => data?.roles?.filter(row => row.code)?.map(role => role.code)); }; const optionsForHierarchy = (level, value) => { @@ -326,9 +330,8 @@ const SearchUserForm = ({ uniqueTenants, setUniqueTenants, roles, setUniqueRoles const renderHierarchyFields = useMemo(() => { return hierarchy.map(({ level, optionsKey, isMandatory, ...rest }, idx) => ( - {`${t(Digit.Utils.locale.getTransformedLocale(`HR_SU_${level}`))} ${ - isMandatory ? "*" : "" - }`} + {`${t(Digit.Utils.locale.getTransformedLocale(`HR_SU_${level}`))} ${isMandatory ? "*" : "" + }`} (
) diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserResults.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserResults.js index 0d9529dd0..425b368e1 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserResults.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/SearchUserResults.js @@ -1,9 +1,9 @@ import React from 'react' import { useTranslation } from "react-i18next"; -import { Table,Loader,Card } from "@egovernments/digit-ui-react-components"; +import { Table, Loader, Card } from "@egovernments/digit-ui-react-components"; import { Link } from "react-router-dom"; -const SearchUserResults = ({isLoading,data,...props}) => { +const SearchUserResults = ({ isLoading, data, ...props }) => { const { t } = useTranslation(); const GetCell = (value) => {t(value)}; const GetSlaCell = (value) => { @@ -21,6 +21,8 @@ const SearchUserResults = ({isLoading,data,...props}) => { disableSortBy: false, accessor: "code", Cell: ({ row }) => { + console.log(row, "ROW"); + return ( {row.original.code} @@ -37,6 +39,22 @@ const SearchUserResults = ({isLoading,data,...props}) => { return GetCell(`${row.original?.user?.name}`); }, }, + { + Header: t("HR_USER_DEPARTMENT"), + disableSortBy: false, + accessor: "department", + Cell: ({ row }) => { + return GetCell(`${row.original?.assignments[0]?.department}`); + }, + }, + { + Header: t("HR_USER_DESIGNATION"), + disableSortBy: false, + accessor: "designation", + Cell: ({ row }) => { + return GetCell(`${row.original?.assignments[0]?.designation}`); + }, + }, { Header: t("HR_USER_ID_LABEL"), disableSortBy: false, @@ -53,6 +71,7 @@ const SearchUserResults = ({isLoading,data,...props}) => { return GetSlaCell(`${row.original?.isActive ? "ACTIVE" : "INACTIVE"}`); }, }, + { Header: t("HR_SU_TENANT"), disableSortBy: false, @@ -84,39 +103,39 @@ const SearchUserResults = ({isLoading,data,...props}) => { } else if (data?.length > 0) { result = ( { - return { - style: { - maxWidth: cellInfo.column.Header == t("HR_EMP_ID_LABEL") ? "150px" : "", - padding: "20px 18px", - fontSize: "16px", - minWidth: "150px", - }, - }; - }} - // onNextPage={onNextPage} - // onPrevPage={onPrevPage} - // currentPage={currentPage} - totalRecords={data ? data.length : 0} - // onPageSizeChange={onPageSizeChange} - // pageSizeLimit={pageSizeLimit} - // onSort={onSort} - // sortParams={sortParams} - // disableSort={disableSort} - autoSort={true} - manualPagination={false} + t={t} + data={data} + columns={columns} + getCellProps={(cellInfo) => { + return { + style: { + maxWidth: cellInfo.column.Header == t("HR_EMP_ID_LABEL") ? "150px" : "", + padding: "20px 18px", + fontSize: "16px", + minWidth: "150px", + }, + }; + }} + // onNextPage={onNextPage} + // onPrevPage={onPrevPage} + // currentPage={currentPage} + totalRecords={data ? data.length : 0} + // onPageSizeChange={onPageSizeChange} + // pageSizeLimit={pageSizeLimit} + // onSort={onSort} + // sortParams={sortParams} + // disableSort={disableSort} + autoSort={true} + manualPagination={false} /> ); } - return ( -
- {result} -
- ) + return ( +
+ {result} +
+ ) } export default SearchUserResults \ No newline at end of file diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/config/config.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/config/config.js index 527cfae45..4d9398e1c 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/config/config.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/config/config.js @@ -26,6 +26,13 @@ export const newConfig = [ key: "SelectEmployeeEmailId", withoutLabel: true, }, + { + type: "component", + isMandatory: true, + component: "SelectUserTypeAndDesignation", + key: "SelectUserTypeAndDesignation", + withoutLabel: true, + }, ], }, { diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/hrmscard.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/hrmscard.js index 455ddb85b..a3e960151 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/hrmscard.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/hrmscard.js @@ -78,6 +78,7 @@ const HRMSCard = () => { { label: t("HR_SEARCH_USER"), link: `/${window?.contextPath}/employee/hrms/search-user`, + roles:["DIV_ADMIN","STATE_ADMIN"] }, { label: t("HR_HOME_SEARCH_RESULTS_HEADING"), diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/inbox/search.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/inbox/search.js index 801c8e6e1..d5562d3d9 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/inbox/search.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/inbox/search.js @@ -58,7 +58,7 @@ const SearchApplication = ({ onSearch, type, onClose, searchFields, searchParams )}
- + {searchFields ?.filter((e) => true) ?.map((input, index) => ( @@ -73,7 +73,7 @@ const SearchApplication = ({ onSearch, type, onClose, searchFields, searchParams ) : null} -
+ ) : ( } @@ -85,32 +85,8 @@ const SearchApplication = ({ onSearch, type, onClose, searchFields, searchParams ))} - {/* Updated Search & Clear All Button */} -
-
- {type === "desktop" && !mobileView && ( - - {clearAll()} - - )} - {type === "desktop" && !mobileView && ( - - )} -
- - {/*Don't Remove : Chance of Updated Search & Clear All Button*/} - {/*
+
{type === "desktop" && !mobileView && ( {clearAll()} @@ -124,7 +100,7 @@ const SearchApplication = ({ onSearch, type, onClose, searchFields, searchParams submit /> )} -
*/} +
{(type === "mobile" || mobileView) && ( diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/SelectUserTypeAndDesignation.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/SelectUserTypeAndDesignation.js new file mode 100644 index 000000000..972f01175 --- /dev/null +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/SelectUserTypeAndDesignation.js @@ -0,0 +1,502 @@ +import { CardLabel, Dropdown, LabelFieldPair, Loader, RemoveableTag } from "@egovernments/digit-ui-react-components"; +import React, { useEffect, useState } from "react"; +import cleanup from "../Utils/cleanup"; +import MultiSelectDropdown from "./Multiselect"; +import { useParams } from "react-router-dom"; + +const makeDefaultValues = (sessionFormData) => { + return sessionFormData?.Jurisdictions?.map((ele, index) => { + return { + key: index, + hierarchy: { + code: ele?.hierarchy, + name: ele?.hierarchy, + }, + boundaryType: { label: ele?.boundaryType, i18text: ele.boundaryType ? `EGOV_LOCATION_BOUNDARYTYPE_${ele.boundaryType?.toUpperCase()}` : null }, + boundary: { code: ele?.boundary }, + divisionBoundary: ele?.divisionBoundary, + division: ele?.division, + designation: ele?.designation, + roles: ele?.roles, + department: ele?.department, + designation: ele?.designation + + + }; + }); +}; + +const SelectUserTypeAndDesignation = ({ t, config, onSelect, userType, formData }) => { + const tenantId = Digit.ULBService.getCurrentTenantId(); + const [inactiveJurisdictions, setInactiveJurisdictions] = useState([]); + const { data: data = {}, isLoading } = Digit.Hooks.hrms.useHrmsMDMS(tenantId, "egov-hrms", "HRMSRolesandDesignation") || {}; + const { id: employeeId } = useParams(); + const isupdate = Digit.SessionStorage.get("isupdate"); + const userDetails = Digit.UserService.getUser(); + const uuids = [userDetails?.info?.uuid]; + const { data: userData, isUserDataLoading } = Digit.Hooks.useUserSearch(Digit.ULBService.getStateId(), { uuid: uuids }, {}); + const employeeCreateSession = Digit.Hooks.useSessionStorage("NEW_EMPLOYEE_CREATE", {}); + const [sessionFormData, setSessionFormData, clearSessionFormData] = employeeCreateSession; + const isEdit = window.location.href?.includes("hrms/edit"); + const STATE_ADMIN = Digit.UserService.hasAccess(["STATE_ADMIN"]); + const [Boundary, selectboundary] = useState([]); + const [jurisdictions, setjurisdictions] = useState( + !isEdit && sessionFormData?.Jurisdictions?.length > 0 + ? makeDefaultValues(sessionFormData) + : formData?.Jurisdictions || [ + { + id: undefined, + key: 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: {}, + divisionBoundary: [], + roles: [], + department: {}, + designation: {} + }, + ] + ); + + + + const [userTypeDesignation, setUserTypeDesignation] = useState( + !isEdit && sessionFormData?.Jurisdictions?.length > 0 + ? makeDefaultValues(sessionFormData) + : formData?.Jurisdictions || [ + { + id: undefined, + key: 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: {}, + department: {}, + designation: {}, + divisionBoundary: [], + roles: [], + }, + ] + ); + const [jurisdictionsData, setJuristictionsData] = useState([]); + let hierarchylist = []; + // const hierarchyData = data?.MdmsRes?.["egov-location"]["TenantBoundary"].filter((ele) => ele?.hierarchyType?.code == "REVENUE")[0]?.hierarchyType; + // hierarchylist.push(hierarchyData); + + // User Details + const { isLoadingDesignation, isError, error, data: responseData, ...rest } = Digit.Hooks.hrms.useHRMSSearch({ codes: employeeId }, tenantId, null, isupdate); + + + + let divisions = []; + divisions = data?.MdmsRes?.["tenant"]["tenants"] + ?.filter((items) => items?.divisionCode) + ?.map((item) => { + return { + code: item.divisionCode, + name: item.divisionName, + i18text: Digit.Utils.locale.getCityLocale(item.divisionCode), + }; + }); + const uniqueDivisions = divisions?.reduce((unique, obj) => { + const isDuplicate = unique.some((item) => item.id === obj.id && item.name === obj.name); + if (!isDuplicate) { + unique.push(obj); + } + return unique; + }, []); + + useEffect(() => { + let cities = userData?.user[0]?.roles?.map((role) => role.tenantId)?.filter((value, index, array) => array.indexOf(value) === index); + + selectboundary( + data?.MdmsRes?.tenant?.tenants + ?.filter((city) => city.code != Digit.ULBService.getStateId() && cities?.includes(city.code)) + ?.map((city) => { + return { ...city, i18text: Digit.Utils.locale.getCityLocale(city.code) }; + }) + ); + }, [data, userData]); + + useEffect(() => { + let jurisdictionData = jurisdictions?.map((jurisdiction) => { + let res = { + id: jurisdiction?.id, + hierarchy: jurisdiction?.boundary?.code, + boundaryType: "City", + boundary: jurisdiction?.boundary?.code, + tenantId: STATE_ADMIN ? jurisdiction?.divisionBoundary && jurisdiction?.divisionBoundary[0]?.code : jurisdiction?.boundary?.code, + auditDetails: jurisdiction?.auditDetails, + division: jurisdiction?.division, + department: jurisdiction?.department, + designation: jurisdiction?.designation + }; + res = cleanup(res); + if (jurisdiction?.roles) { + res["roles"] = jurisdiction?.roles.map((ele) => { + delete ele.description; + return ele; + }); + } + if (jurisdiction?.divisionBoundary) { + res["divisionBoundary"] = jurisdiction?.divisionBoundary; + } + if (isEdit && STATE_ADMIN) { + data?.MdmsRes?.["tenant"]["tenants"]?.map((items) => { + if (items?.code === jurisdiction?.boundary?.code) { + res["division"] = { + code: items?.divisionCode, + i18text: Digit.Utils.locale.convertToLocale(items?.divisionCode, "EGOV_LOCATION_DIVISION"), + }; + res["divisionBoundary"] = [ + { + name: items.name, + code: items.code, + i18text: Digit.Utils.locale.getCityLocale(items.code), + }, + ]; + } + }); + } + return res; + }); + if (isEdit && STATE_ADMIN) { + let divisionData = []; + if (isEdit && jurisdictionData.length > 0) { + jurisdictionData?.map((jurisdiction) => { + if (jurisdiction?.divisionBoundary && jurisdiction?.divisionBoundary?.length > 0 && divisionData.length === 0) { + divisionData.push(jurisdiction); + } else if (divisionData.length > 0) { + if (divisionData[divisionData.length - 1]?.division?.code !== jurisdiction?.division?.code) { + divisionData.push(jurisdiction); + } + } + }); + } + + let finalData = []; + divisionData && + divisionData?.length > 0 && + divisionData?.map((data, index) => { + let divisionBoundarydata = []; + jurisdictionData?.map((jurisdiction) => { + if (data?.division?.code === jurisdiction?.division?.code) { + if (divisionBoundarydata?.length === 0) { + jurisdiction?.divisionBoundary[0] !== undefined && divisionBoundarydata.push(jurisdiction?.divisionBoundary[0]); + } else if (divisionBoundarydata?.length > 0) { + if (divisionBoundarydata[divisionBoundarydata?.length - 1]?.code !== jurisdiction?.divisionBoundary[0]) { + jurisdiction?.divisionBoundary[0] !== undefined && divisionBoundarydata.push(jurisdiction?.divisionBoundary[0]); + } + } + } + }); + let obj = { + ...data, + key: index, + divisionBoundary: divisionBoundarydata, + }; + finalData.push(obj); + }); + + jurisdictionData = finalData; + } + setJuristictionsData(jurisdictionData); + onSelect( + config.key, + [...jurisdictionData, ...inactiveJurisdictions].filter((value) => Object.keys(value).length !== 0) + ); + + }, [jurisdictions, data?.MdmsRes]); + + const reviseIndexKeys = () => { + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + }; + + function filterJurisdictions(unit, jurisdictions) { + const divisionBoundaryCodes = new Set(unit.divisionBoundary.map(item => item.code)); + return jurisdictions.filter(jurisdiction => { + return !divisionBoundaryCodes.has(jurisdiction.boundary.code); + }); + } + const handleRemoveUnit = (unit) => { + if (STATE_ADMIN) { + if (!isEdit) { + setjurisdictions(jurisdictions.filter( + (element) => element.key !== unit.key + )); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } + else { + setJuristictionsData(jurisdictionsData.filter( + (element) => element.key !== unit.key + )); + let filterJurisdictionsItems = filterJurisdictions(unit, jurisdictions); + setjurisdictions(filterJurisdictionsItems); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } + if (FormData.errors?.Jurisdictions?.type == unit.key) { + clearErrors("Jurisdictions"); + } + reviseIndexKeys(); + } + else { + if (unit.id) { + let res = { + id: unit?.id, + hierarchy: unit?.hierarchy?.code, + boundaryType: unit?.boundaryType?.label, + boundary: unit?.boundary?.code, + division: unit?.division?.code, + tenantId: unit?.boundary?.code, + auditDetails: unit?.auditDetails, + isdeleted: true, + isActive: false, + }; + res = cleanup(res); + if (unit?.roles) { + res["roles"] = unit?.roles.map((ele) => { + delete ele.description; + return ele; + }); + } + setInactiveJurisdictions([...inactiveJurisdictions, res]); + } + setJuristictionsData((pre) => pre.filter((el) => el.key !== unit.key)); + setjurisdictions((prev) => prev.filter((el) => el.key !== unit.key)); + if (FormData.errors?.Jurisdictions?.type == unit.key) { + clearErrors("Jurisdictions"); + } + + reviseIndexKeys(); + + } + + }; + let boundaryTypeoption = []; + const [focusIndex, setFocusIndex] = useState(-1); + + + + function getroledata() { + if (STATE_ADMIN) { + // Specify the role codes you want to filter + const roleCodesToFilter = ["HRMS_ADMIN", "EMPLOYEE", "DIV_ADMIN"]; + // Use the filter method to extract roles with the specified codes + return data?.MdmsRes?.["ws-services-masters"]["WSServiceRoles"] + .filter((role) => { + return roleCodesToFilter.includes(role.code); + }) + .map((role) => { + return { code: role.code, name: role?.name ? role?.name : " ", i18text: "ACCESSCONTROL_ROLES_ROLES_" + role.code }; + }); + } else { + // Specify the role codes you want to filter + const roleCodesToFilter = ["HRMS_ADMIN", "DIV_ADMIN", "MDMS_ADMIN", "LOC_ADMIN", "SYSTEM"]; + // Use the filter method to extract roles with the specified codes + return data?.MdmsRes?.["ws-services-masters"].WSServiceRoles?.filter((role) => { + return !roleCodesToFilter.includes(role.code); + })?.map((role) => { + return { code: role.code, name: role?.name ? role?.name : " ", i18text: "ACCESSCONTROL_ROLES_ROLES_" + role.code }; + }); + } + } + + function getdesignationdata() { + + return data?.MdmsRes?.["common-masters"]?.Designation?.map((ele) => { + ele["i18key"] = t("COMMON_MASTERS_DESIGNATION_" + ele.code); + return ele; + }); + } + function getUserTypes() { + return data?.MdmsRes?.["common-masters"]?.Department?.map((ele) => { + ele["i18key"] = t("COMMON_MASTERS_DEPARTMENT" + ele.code); + return ele; + }); + } + + if (isLoading && isUserDataLoading && isLoadingDesignation) { + return ; + } + + return ( +
+ +
+ ); +}; + +function Jurisdiction({ + t, + formData, + data, + userDetails, + jurisdiction, + jurisdictions, + setjurisdictions, + setJuristictionsData, + jurisdictionsData, + onSelect, + config, + handleRemoveUnit, + hierarchylist, + divisions, + getroledata, + roleoption, + index, + Boundary, + getdesignationdata, + getUserTypes, + responseData +}) { + // console.log(responseData?.Employees[0]?.assignments[0]?.department, "responseData"); + // console.log(responseData?.Employees[0]?.assignments[0]?.designation, "responseData"); + + const [BoundaryType, selectBoundaryType] = useState([]); + const [divisionBoundary, setDivisionBoundary] = useState([]); + const [designationList, setDesignationList] = useState([]); + const [depamentValue, setDepamentValue] = useState(""); + const [designationValue, setDesignationValue] = useState(""); + + const [Division, setDivision] = useState([]); + const STATE_ADMIN = Digit.UserService.hasAccess(["STATE_ADMIN"]); + let isMobile = window.Digit.Utils.browser.isMobile(); + const isEdit = window.location.href?.includes("hrms/edit"); + let defaultjurisdiction = () => { + let currentTenant = Digit.ULBService.getCurrentTenantId(); + let defaultjurisdiction; + Boundary?.map((ele) => { + if (ele.code === currentTenant) { + defaultjurisdiction = ele; + } + }) + return defaultjurisdiction; + } + useEffect(() => { + + if (responseData != null && depamentValue == "" && isEdit) { + getUserTypes?.forEach((ele) => { + if (ele.code === responseData?.Employees[0]?.assignments[0]?.department) { + setDepamentValue(ele); + const filteredItems = getdesignationdata.filter(val => val.department.includes(ele.code)); + setDesignationList(filteredItems); + setjurisdictions((pre) => pre.map((item) => (item.key == jurisdiction.key ? { ...item, department: ele } : item))); + // setDesignationValue(filteredItems[0]); + // setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, designation: filteredItems[0] } : item))); + } + }); + } + },); + + useEffect(() => { + if (responseData != null) { + getdesignationdata?.forEach((ele) => { + if (ele.code === responseData?.Employees[0]?.assignments[0]?.designation) { + setDesignationValue(ele); + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, designation: ele } : item))); + } + }); + } + }, [depamentValue]); + useEffect(() => { + setDivision( + divisions?.map((item) => { + return { ...item, i18text: Digit.Utils.locale.convertToLocale(item.code, "EGOV_LOCATION_DIVISION") }; + }) + ); + }, [divisions]); + + const tenant = Digit.ULBService.getCurrentTenantId(); + + useEffect(() => { + if (Boundary?.length > 0) { + selectedboundary(Boundary?.filter((ele) => ele.code == jurisdiction?.boundary?.code)[0]); + } + }, [Boundary]); + + const selectedboundary = (value) => { + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, boundary: value } : item))); + }; + const selectDepartment = (value) => { + setDesignationList([]); + setjurisdictions((pre) => pre.map((item) => (item.key == jurisdiction.key ? { ...item, department: value } : item))); + const filteredItems = getdesignationdata.filter(val => val.department.includes(value.code)); + setDesignationList(filteredItems); + setDesignationValue(filteredItems[0]); + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, designation: filteredItems[0] } : item))); + }; + const selectDesignation = (value) => { + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, designation: value } : item))); + + }; + + return ( +
+ { + !STATE_ADMIN && ( +
+
+ + + {`${t("HR_COMMON_DEPARTMENT")} * `} + + + +
+
+ + + {`${t("HR_COMMON_USER_DESIGNATION")} * `} + + + +
+
) + } +
+ ); +} + +export default SelectUserTypeAndDesignation; + diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/assignment.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/assignment.js index 92abd194a..e1bc15ea3 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/assignment.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/assignment.js @@ -216,6 +216,7 @@ function Assignment({ const ValidateDatePickers = (value) => { assignments; }; + console.log(assignment,"assignment"); return (
diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js index 0a4290de8..15ad7adbb 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/components/pageComponents/jurisdiction.js @@ -33,21 +33,23 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { const isEdit = window.location.href?.includes("hrms/edit"); const STATE_ADMIN = Digit.UserService.hasAccess(["STATE_ADMIN"]); const [Boundary, selectboundary] = useState([]); + const [subDivisionList, selectSubDivisionList] = useState([]); + const [sectionList, selectSectionListList] = useState([]); const [jurisdictions, setjurisdictions] = useState( !isEdit && sessionFormData?.Jurisdictions?.length > 0 ? makeDefaultValues(sessionFormData) : formData?.Jurisdictions || [ - { - id: undefined, - key: 1, - hierarchy: null, - boundaryType: null, - boundary: null, - division: {}, - divisionBoundary: [], - roles: [], - }, - ] + { + id: undefined, + key: 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: {}, + divisionBoundary: [], + roles: [], + }, + ] ); const [jurisdictionsData, setJuristictionsData] = useState([]); let hierarchylist = []; @@ -55,6 +57,8 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { // hierarchylist.push(hierarchyData); let divisions = []; + let subDivisionsItems = []; + let sectionItems = []; divisions = data?.MdmsRes?.["tenant"]["tenants"] ?.filter((items) => items?.divisionCode) ?.map((item) => { @@ -64,6 +68,25 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { i18text: Digit.Utils.locale.getCityLocale(item.divisionCode), }; }); + subDivisionsItems = data?.MdmsRes?.["tenant"]["tenants"] + ?.filter((items) => items?.subDivisionCode) + ?.map((item) => { + return { + code: item.subDivisionCode, + name: item.subDivisionName, + i18text: Digit.Utils.locale.getCityLocale(item.subDivisionCode), + }; + }); + + const uniqueSubDivisionsItems = subDivisionsItems?.reduce((unique, obj) => { + const isDuplicate = unique.some((item) => item.id === obj.id && item.name === obj.name); + if (!isDuplicate) { + unique.push(obj); + } + return unique; + }, []); + + const uniqueDivisions = divisions?.reduce((unique, obj) => { const isDuplicate = unique.some((item) => item.id === obj.id && item.name === obj.name); if (!isDuplicate) { @@ -82,6 +105,11 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { return { ...city, i18text: Digit.Utils.locale.getCityLocale(city.code) }; }) ); + if (uniqueSubDivisionsItems != null) { + selectSubDivisionList(uniqueSubDivisionsItems); + + } + // selectSectionListList }, [data, userData]); useEffect(() => { @@ -169,44 +197,96 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { config.key, [...jurisdictionData, ...inactiveJurisdictions].filter((value) => Object.keys(value).length !== 0) ); - + }, [jurisdictions, data?.MdmsRes]); - // useEffect(() => { - // setJuristictionsData(formData?.Jurisdictions); - // }, [formData?.Jurisdictions, jurisdictions]); const reviseIndexKeys = () => { setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); }; const handleAddUnit = () => { - setjurisdictions((prev) => [ - ...prev, - { - key: prev.length + 1, - hierarchy: null, - boundaryType: null, - boundary: null, - division: null, - divisionBoundary: [], - roles: [], - }, - ]); + if (STATE_ADMIN) { + if (!isEdit) { + setjurisdictions((prev) => [ + ...prev, + { + key: prev.length + 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: null, + divisionBoundary: [], + roles: [], + }, + ]); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } else { + setJuristictionsData((prev) => [ + ...prev, + { + key: prev.length + 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: null, + divisionBoundary: [], + roles: [], + }, + ]); + setJuristictionsData((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } + + } else { + setjurisdictions((prev) => [ + ...prev, + { + key: prev.length + 1, + hierarchy: null, + boundaryType: null, + boundary: null, + division: null, + divisionBoundary: [], + roles: [], + }, + ]); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + + } + + + }; + + function filterJurisdictions(unit, jurisdictions) { + const divisionBoundaryCodes = new Set(unit.divisionBoundary.map(item => item.code)); + return jurisdictions.filter(jurisdiction => { + return !divisionBoundaryCodes.has(jurisdiction.boundary.code); + }); + } const handleRemoveUnit = (unit) => { - if(STATE_ADMIN){ - const updatedJurisdictionsData = jurisdictionsData.filter( - (element) => element.key !== unit.key - ); - setJuristictionsData(updatedJurisdictionsData); - setjurisdictions(updatedJurisdictionsData) + if (STATE_ADMIN) { + if (!isEdit) { + setjurisdictions(jurisdictions.filter( + (element) => element.key !== unit.key + )); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } + else { + setJuristictionsData(jurisdictionsData.filter( + (element) => element.key !== unit.key + )); + let filterJurisdictionsItems = filterJurisdictions(unit, jurisdictions); + setjurisdictions(filterJurisdictionsItems); + setjurisdictions((prev) => prev.map((unit, index) => ({ ...unit, key: index }))); + } if (FormData.errors?.Jurisdictions?.type == unit.key) { clearErrors("Jurisdictions"); } reviseIndexKeys(); - } - else{ + + + else { if (unit.id) { let res = { id: unit?.id, @@ -233,7 +313,7 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { if (FormData.errors?.Jurisdictions?.type == unit.key) { clearErrors("Jurisdictions"); } - + reviseIndexKeys(); } @@ -261,12 +341,14 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { const roleCodesToFilter = ["HRMS_ADMIN", "DIV_ADMIN", "MDMS_ADMIN", "LOC_ADMIN", "SYSTEM"]; // Use the filter method to extract roles with the specified codes return data?.MdmsRes?.["ws-services-masters"].WSServiceRoles?.filter((role) => { - return !roleCodesToFilter.includes(role.code); + return !roleCodesToFilter.includes(role.code) && + (role?.name === "Secretary" || role?.name === "Sarpanch" || role?.name === "Revenue Collector"); })?.map((role) => { return { code: role.code, name: role?.name ? role?.name : " ", i18text: "ACCESSCONTROL_ROLES_ROLES_" + role.code }; }); } } + if (isLoading && isUserDataLoading) { return ; } @@ -322,6 +404,10 @@ const Jurisdictions = ({ t, config, onSelect, userType, formData }) => { getroledata={getroledata} handleRemoveUnit={handleRemoveUnit} Boundary={Boundary} + // SUBDIVISION & SECTION + subDivisionList={subDivisionList} + sectionList={sectionList} + // SUBDIVISION & SECTION /> )) )} @@ -351,24 +437,29 @@ function Jurisdiction({ roleoption, index, Boundary, + // SUBDIVISION + subDivisionList, + sectionList, + // SUBDIVISION }) { const [BoundaryType, selectBoundaryType] = useState([]); // const [Boundary, selectboundary] = useState([]); const [divisionBoundary, setDivisionBoundary] = useState([]); + const [sectionDataList, setSectionDataList] = useState([]); const [Division, setDivision] = useState([]); const STATE_ADMIN = Digit.UserService.hasAccess(["STATE_ADMIN"]); let isMobile = window.Digit.Utils.browser.isMobile(); const isEdit = window.location.href?.includes("hrms/edit"); - let defaultjurisdiction = () =>{ + let defaultjurisdiction = () => { let currentTenant = Digit.ULBService.getCurrentTenantId(); let defaultjurisdiction; - Boundary?.map((ele)=>{ - if (ele.code === currentTenant){ + Boundary?.map((ele) => { + if (ele.code === currentTenant) { defaultjurisdiction = ele; } }) return defaultjurisdiction; - } + } useEffect(() => { setDivision( @@ -397,6 +488,33 @@ function Jurisdiction({ setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, boundary: value } : item))); }; + + const selectSubDivisionList = (value) => { + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, subDivision: value } : item))); + + var sections = data?.MdmsRes?.tenant?.tenants + ?.filter((division) => division.subDivisionCode === value.code) + ?.map((division) => { + return { + code: division.sectionCode, + name: division.sectionName, + i18text: Digit.Utils.locale.getCityLocale(division.sectionCode) + }; + }); + const uniqueSections = sections?.reduce((unique, obj) => { + const isDuplicate = unique.some((item) => item.code === obj.code && item.name === obj.name); + if (!isDuplicate) { + unique.push(obj); + } + return unique; + }, []); + setSectionDataList(uniqueSections); + }; + + const selectSectionList = (value) => { + setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, section: value } : item))); + }; + const selectDivision = (value) => { // Extract projects using array methods const project = data?.MdmsRes?.["tenant"]["tenants"].filter((obj) => obj.divisionCode === value.code); @@ -470,7 +588,7 @@ function Jurisdiction({ [...data].filter((value) => Object.keys(value).length !== 0) ); setjurisdictions((pre) => pre.map((item) => (item.key === jurisdiction.key ? { ...item, roles: res } : item))); - selectedboundary(jurisdiction?.boundary?jurisdiction?.boundary:defaultjurisdiction()); + selectedboundary(jurisdiction?.boundary ? jurisdiction?.boundary : defaultjurisdiction()); }; const selectDivisionBoundary = (e) => { @@ -597,7 +715,33 @@ function Jurisdiction({
) : ( + // subDivision + {/* {!STATE_ADMIN && + {`${t("HR_SUB_DIVISION_LABEL")} * `} + + } + {/* Section */} + {/* {!STATE_ADMIN && + {`${t("HR_SUB_DIVISION_LABEL")} * `} + + } */} {`${t("HR_BOUNDARY_LABEL")} * `} { } }, [mobileNumber]); + let defaultValues = { tenantId: tenantId, employeeStatus: "EMPLOYED", @@ -70,6 +71,11 @@ const EditForm = ({ tenantId, data }) => { name: `COMMON_GENDER_${data?.user?.gender}`, }, }, + SelectUserTypeAndDesignation: { + department: data?.assignments[0]?.department, + designation: data?.assignments[0]?.designation + }, + SelectDateofBirthEmployment: { dob: convertEpochToDate(data?.user?.dob) }, Jurisdictions: data?.jurisdictions?.map((ele, index) => { @@ -132,6 +138,7 @@ const EditForm = ({ tenantId, data }) => { } const onFormValueChange = (setValue = true, formData) => { + let isValid = false; if (formData?.SelectEmployeePhoneNumber?.mobileNumber) { setMobileNumber(formData?.SelectEmployeePhoneNumber?.mobileNumber); } else { @@ -146,24 +153,32 @@ const EditForm = ({ tenantId, data }) => { } else { if (!STATE_ADMIN) { key?.roles?.length > 0 && setcheck(true); + if (formData?.SelectUserTypeAndDesignation[0] && formData?.SelectUserTypeAndDesignation[0]?.department != undefined && formData?.SelectUserTypeAndDesignation[0]?.designation != undefined) { + isValid = true; + } + else { + isValid = false; + } } else if (STATE_ADMIN) { setcheck(true); + isValid = false; } } } - + if ( formData?.SelectEmployeeGender?.gender.code && - formData?.SelectEmployeeName?.employeeName && - formData?.SelectEmployeePhoneNumber?.mobileNumber && - STATE_ADMIN ? - (formData?.Jurisdictions?.length && !formData?.Jurisdictions.some(juris => juris?.division == undefined || juris?.divisionBoundary?.length === 0 ) ) - :formData?.Jurisdictions?.length && formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.roles?.length === 0 ) - && - checkfield && - phonecheck && - checkMailNameNum(formData)&& - hasUniqueTenantIds(formData?.Jurisdictions) + formData?.SelectEmployeeName?.employeeName && + formData?.SelectEmployeePhoneNumber?.mobileNumber && + STATE_ADMIN ? + (formData?.Jurisdictions?.length && !formData?.Jurisdictions.some(juris => juris?.division == undefined || juris?.divisionBoundary?.length === 0)) + : formData?.Jurisdictions?.length && formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.roles?.length === 0) + && + isValid && + checkfield && + phonecheck && + checkMailNameNum(formData) && + hasUniqueTenantIds(formData?.Jurisdictions) ) { setSubmitValve(true); } else { @@ -286,7 +301,16 @@ const EditForm = ({ tenantId, data }) => { } let requestdata = Object.assign({}, data); roles = [].concat.apply([], roles); - requestdata.assignments = input?.Assignments ? input?.Assignments : data?.assignments; + // console.log(input?.SelectUserTypeAndDesignation, "input?.Assignments"); + // console.log(data?.assignments, "data?.assignments"); + // console.log(input, "INPUT"); + + let dataAssignments = data?.assignments; + dataAssignments[0].department = input.SelectUserTypeAndDesignation[0]?.department?.code; + dataAssignments[0].designation = input.SelectUserTypeAndDesignation[0]?.designation?.code; + + + requestdata.assignments = input?.Assignments ? input?.Assignments : dataAssignments; requestdata.dateOfAppointment = Date.parse(input?.SelectDateofEmployment?.dateOfAppointment); requestdata.code = input?.SelectEmployeeId?.code ? input?.SelectEmployeeId?.code : data?.code; requestdata.jurisdictions = jurisdictions; diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/EmployeeDetails.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/EmployeeDetails.js index 44d54f83a..bf886caa0 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/EmployeeDetails.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/EmployeeDetails.js @@ -42,6 +42,8 @@ const Details = () => { } }); }); + // console.log(data, "data"); + useEffect(() => { setMutationHappened(false); clearSuccessData(); @@ -63,7 +65,7 @@ const Details = () => { window.open(documentLink, "_blank"); }; - const submitAction = (data) => {}; + const submitAction = (data) => { }; useEffect(() => { switch (selectedAction) { @@ -115,6 +117,14 @@ const Details = () => { + + {data?.Employees?.[0]?.isActive == false ? ( @@ -129,8 +139,8 @@ const Details = () => { text={ t( "EGOV_HRMS_DEACTIVATIONREASON_" + - data?.Employees?.[0]?.deactivationDetails?.sort((a, b) => new Date(a.effectiveFrom) - new Date(b.effectiveFrom))[0] - .reasonForDeactivation + data?.Employees?.[0]?.deactivationDetails?.sort((a, b) => new Date(a.effectiveFrom) - new Date(b.effectiveFrom))[0] + .reasonForDeactivation ) || "NA" } /> @@ -173,41 +183,41 @@ const Details = () => { {data?.Employees?.[0]?.jurisdictions?.length > 0 ? data?.Employees?.[0]?.jurisdictions?.map((element, index) => { - return ( - -
- {" "} - {t("HR_JURISDICTION")} {index + 1} -
- {STATE_ADMIN ? ( - - ) : null} - - {!STATE_ADMIN ? ( - ele.tenantId == element?.boundary) - ?.map((ele) => t(`ACCESSCONTROL_ROLES_ROLES_` + ele?.code))} - /> - ) : null} -
- ); - }) + return ( + +
+ {" "} + {t("HR_JURISDICTION")} {index + 1} +
+ {STATE_ADMIN ? ( + + ) : null} + + {!STATE_ADMIN ? ( + ele.tenantId == element?.boundary) + ?.map((ele) => t(`ACCESSCONTROL_ROLES_ROLES_` + ele?.code))} + /> + ) : null} +
+ ); + }) : null}
diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/Inbox.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/Inbox.js index 15e18f175..88b1395d0 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/Inbox.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/Inbox.js @@ -29,9 +29,9 @@ const Inbox = ({ parentRoute, businessService = "HRMS", initialStates = {}, filt let roles = STATE_ADMIN ? { roles: "DIV_ADMIN", isStateLevelSearch: true } : { - roles: "SYSTEM, GP_ADMIN, COLLECTION_OPERATOR, PROFILE_UPDATE, DASHBOAD_VIEWER, SARPANCH, REVENUE_COLLECTOR, SECRETARY", - isStateLevelSearch: false, - }; + roles: "SYSTEM, GP_ADMIN, COLLECTION_OPERATOR, PROFILE_UPDATE, DASHBOAD_VIEWER, SARPANCH, REVENUE_COLLECTOR, SECRETARY", + isStateLevelSearch: false, + }; let requestBody = { criteria: { @@ -51,9 +51,9 @@ const Inbox = ({ parentRoute, businessService = "HRMS", initialStates = {}, filt const checkRoles = requestBody.criteria.roles[0] !== "DIV_ADMIN"; const { data: divisionData, ...rests } = Digit.Hooks.hrms.useHRMSEmployeeSearch(requestBody, isupdate, { - enabled: !STATE_ADMIN ? false : (STATE_ADMIN && searchParams?.hasOwnProperty("isActive")) || searchParams?.hasOwnProperty("tenantIds") ? true : false, + enabled: !STATE_ADMIN ? false : (STATE_ADMIN && searchParams?.hasOwnProperty("isActive")) || searchParams?.hasOwnProperty("tenantIds") ? true : false, }); - + if (searchParams?.hasOwnProperty("roles")) { @@ -75,7 +75,7 @@ const Inbox = ({ parentRoute, businessService = "HRMS", initialStates = {}, filt // setTotalReacords(res?.EmployeCount?.totalEmployee); }, [res]); - useEffect(() => {}, [hookLoading, rest]); + useEffect(() => { }, [hookLoading, rest]); useEffect(() => { setPageOffset(0); @@ -124,10 +124,10 @@ const Inbox = ({ parentRoute, businessService = "HRMS", initialStates = {}, filt const getSearchFields = () => { return [ - // { - // label: t("HR_NAME_LABEL"), - // name: "names", - // }, + { + label: t("HR_NAME_LABEL"), + name: "name", + }, { label: t("HR_MOB_NO_LABEL"), name: "phone", diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/SearchUser.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/SearchUser.js index ead17dcfd..68bcb3a5d 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/SearchUser.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/SearchUser.js @@ -1,4 +1,4 @@ -import React,{useState,useEffect} from 'react' +import React, { useState, useEffect } from 'react' import SearchUserForm from '../components/SearchUserForm' import SearchUserResults from '../components/SearchUserResults'; import { Header } from '@egovernments/digit-ui-react-components' @@ -6,18 +6,18 @@ import { useTranslation } from "react-i18next"; const SearchUser = () => { - const {t} = useTranslation() - const [uniqueTenants,setUniqueTenants] = useState(null) - const [roles,setUniqueRoles] = useState(null) + const { t } = useTranslation() + const [uniqueTenants, setUniqueTenants] = useState(null) + const [roles, setUniqueRoles] = useState(null) const requestCriteriaForEmployeeSearch = { url: "/egov-hrms/employees/_searchListOfEmployee", params: {}, body: { - criteria:{ - tenantIds:uniqueTenants, - roles:roles, - type:"EMPLOYEE" + criteria: { + tenantIds: uniqueTenants, + roles: roles, + type: "EMPLOYEE" } }, config: { @@ -25,13 +25,14 @@ const SearchUser = () => { select: (data) => { return data?.Employees }, - + }, - changeQueryName:{uniqueTenants,roles} + changeQueryName: { uniqueTenants, roles } }; const { isLoading, data, revalidate, isFetching, error } = Digit.Hooks.useCustomAPIHook(requestCriteriaForEmployeeSearch); - + + return (
@@ -39,8 +40,8 @@ const SearchUser = () => {
{t("HR_SU")}
-
- +
+
) diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/createEmployee.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/createEmployee.js index 411ae2229..b72018d4d 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/createEmployee.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/hrms/src/pages/createEmployee.js @@ -104,6 +104,7 @@ const CreateEmployee = () => { } const onFormValueChange = (setValue = true, formData) => { + let isValid = false; if (!_.isEqual(sessionFormData, formData)) { setSessionFormData({ ...sessionFormData, ...formData }); } @@ -119,27 +120,48 @@ const CreateEmployee = () => { break; } else { if (!STATE_ADMIN) { + if (formData?.SelectUserTypeAndDesignation[0] && formData?.SelectUserTypeAndDesignation[0]?.department != undefined && formData?.SelectUserTypeAndDesignation[0]?.designation != undefined) { + isValid = true; + } + else { + isValid = false; + } + key?.roles?.length > 0 && setcheck(true); } else if (STATE_ADMIN) { setcheck(true); + isValid = false; } } } + // console.log(formData. + // SelectUserTypeAndDesignation[0].department != undefined + // , "formData"); + // console.log(formData. + // SelectUserTypeAndDesignation[0].designation != undefined + // , "formData"); + console.log(isValid, "isValid"); + if ( + + formData?.SelectEmployeeGender?.gender.code && - formData?.SelectEmployeeName?.employeeName && - formData?.SelectEmployeePhoneNumber?.mobileNumber && - formData?.Jurisdictions?.length && - STATE_ADMIN ? - (formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.division == undefined || juris?.divisionBoundary?.length === 0 ) ) - - :formData?.Jurisdictions?.length && formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.roles?.length === 0 ) - && - checkfield && - phonecheck && - checkMailNameNum(formData) && - hasUniqueTenantIds(formData?.Jurisdictions) + formData?.SelectEmployeeName?.employeeName && + formData?.SelectEmployeePhoneNumber?.mobileNumber && + formData?.Jurisdictions?.length && + STATE_ADMIN ? + (formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.division == undefined || juris?.divisionBoundary?.length === 0)) + + : formData?.Jurisdictions?.length && formData?.Jurisdictions.length && !formData?.Jurisdictions.some(juris => juris?.roles?.length === 0) && + + isValid && + + checkfield && + phonecheck && + checkMailNameNum(formData) && + hasUniqueTenantIds(formData?.Jurisdictions) + ) { setSubmitValve(true); } else { @@ -152,6 +174,7 @@ const CreateEmployee = () => { }; const onSubmit = (data) => { + if (!STATE_ADMIN && data.Jurisdictions?.filter((juris) => juris.tenantId == tenantId).length == 0) { setShowToast({ key: true, label: "ERR_BASE_TENANT_MANDATORY" }); closeToast(); @@ -260,6 +283,7 @@ const CreateEmployee = () => { code: "EMPLOYEE", tenantId: "pb", }); + const mappedroles = [].concat.apply([], roles); let dateOfAppointment = new Date(); dateOfAppointment.setDate(dateOfAppointment.getDate() - 1); @@ -267,7 +291,6 @@ const CreateEmployee = () => { { tenantId: tenantId, employeeStatus: "EMPLOYED", - code: data?.SelectEmployeeId?.code ? data?.SelectEmployeeId?.code : undefined, dateOfAppointment: dateOfAppointment.getTime(), employeeType: hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.employeeType, @@ -276,10 +299,11 @@ const CreateEmployee = () => { { fromDate: new Date().getTime(), isCurrentAssignment: hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.isCurrentAssignment, - department: hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.department, + department: !STATE_ADMIN ? data?.SelectUserTypeAndDesignation[0]?.department?.code : + hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.department, designation: STATE_ADMIN ? hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.designation?.filter((x) => x?.isStateUser)[0]?.code - : hrmsData?.["egov-hrms"]?.HRMSConfig[0]?.designation?.filter((x) => !x?.isStateUser)[0]?.code, + : data?.SelectUserTypeAndDesignation[0]?.designation?.code, }, ], user: { @@ -317,6 +341,7 @@ const CreateEmployee = () => { if (isLoading) { return ; } + const config = mdmsData?.config ? mdmsData.config : newConfig; return (
diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/components/OpenView.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/components/OpenView.js index baafe512d..0c3b1daa7 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/components/OpenView.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/components/OpenView.js @@ -5,11 +5,20 @@ import { makePayment } from "../utils/payGov"; import $ from "jquery"; function anonymizeHalfString(input) { - // Calculate the midpoint of the string - const midpoint = Math.ceil(input.length / 2); + // Initialize an empty string to store the anonymized output + let anonymized = ""; - // Replace the first 50% of the string with asterisks - const anonymized = "*".repeat(midpoint) + input.substring(midpoint); + // Loop through each character in the input string + for (let i = 0; i < input.length; i++) { + // Check if the index (i) is even (0, 2, 4, ...) + if (i % 2 === 0) { + // Append the original character (keep it) + anonymized += input[i]; + } else { + // Append an asterisk to mask the alternate character + anonymized += "*"; + } + } return anonymized; } @@ -38,7 +47,7 @@ const OpenView = () => { const requestCriteriaForConnectionSearch = { url: "/ws-services/wc/_search?", - params: { tenantId:queryParams.tenantId,businessService:queryParams.businessService, connectionNumber: queryParams.consumerCode,isOpenPaymentSearch:true }, + params: { tenantId: queryParams.tenantId, businessService: queryParams.businessService, connectionNumber: queryParams.consumerCode, isOpenPaymentSearch: true }, body: {}, options: { userService: false, @@ -57,7 +66,7 @@ const OpenView = () => { const requestCriteriaForPayments = { url: "/collection-services/payments/WS/_search", - params: {consumerCodes:queryParams.consumerCode,tenantId:queryParams.tenantId,businessService:queryParams.businessService}, + params: { consumerCodes: queryParams.consumerCode, tenantId: queryParams.tenantId, businessService: queryParams.businessService }, body: {}, options: { userService: false, @@ -78,10 +87,41 @@ const OpenView = () => { }, }; - const { isLoading: isLoadingPayments, data: payments, isFetching: isFetchingPayments, error: isErrorPayments } = Digit.Hooks.useCustomAPIHook( - requestCriteriaForPayments + const requestCriteriaForOnlineTransactions = { + url: "/pg-service/transaction/v1/_search", + params: { consumerCode: queryParams.consumerCode, tenantId: queryParams.tenantId, businessService: queryParams.businessService }, + body: {}, + options: { + userService: false, + auth: false, + }, + config: { + enabled: !!queryParams.consumerCode && !!queryParams.tenantId, + select: (data) => { + const onlineTransactions = data?.Transaction; + + if (!onlineTransactions) { + return null; // Handle undefined or null data gracefully + } + + // Sort onlineTransactions in descending order by createdTime + onlineTransactions.sort((a, b) => b.auditDetails.createdTime - a.auditDetails.createdTime); + + // Return the desired number of latest transactions (up to 5) + return onlineTransactions.slice(0, Math.min(onlineTransactions.length, 5)); + }, + }, + }; + + const { isLoading: isLoadingTransactions, data: onlineTransactions, isFetching: isFetchingTransactions, error: isErrorTransactions } = Digit.Hooks.useCustomAPIHook( + requestCriteriaForOnlineTransactions ); + // const { isLoading: isLoadingPayments, data: payments, isFetching: isFetchingPayments, error: isErrorPayments } = Digit.Hooks.useCustomAPIHook( + // requestCriteriaForPayments + // ); + + const arrears = bill?.billDetails ?.sort((a, b) => b.fromPeriod - a.fromPeriod) @@ -198,10 +238,41 @@ const OpenView = () => { } }; - if (isLoading || isLoadingPayments || isLoadingConnection) { + if (isLoading || isLoadingTransactions || isLoadingConnection) { return ; } + + function convertEpochToDateString(epochTime) { + const date = new Date(epochTime); + + // Extract components + const day = date.getDate(); + const month = date.getMonth() + 1; // Months are zero-indexed + const year = date.getFullYear(); + let hours = date.getHours(); + const minutes = date.getMinutes(); + const seconds = date.getSeconds(); + + // Determine AM/PM + const ampm = hours >= 12 ? 'PM' : 'AM'; + + // Convert to 12-hour format + hours = hours % 12; + hours = hours ? hours : 12; // the hour '0' should be '12' + + // Pad minutes and seconds with leading zeros + const minutesPadded = minutes < 10 ? '0' + minutes : minutes; + const secondsPadded = seconds < 10 ? '0' + seconds : seconds; + + // Format date and time + const formattedDate = `${day} July ${year} at ${hours}:${minutesPadded}:${secondsPadded} ${ampm}`; + + return formattedDate; + } + + + return ( <>
@@ -255,18 +326,19 @@ const OpenView = () => { /> )} + + + + +
+ {t("ES_PAYMENT_DETAILS_HEADER")} +
+ + + + {bill ? ( <> - {/* - */} { )} - {payments && ( + {onlineTransactions && (
{t("OP_CONSUMER_RECEIPTS")}
)} - {payments && - payments.map((payment) => { - return ( - - - - - - {/* */} - - - ); - })} + {onlineTransactions && onlineTransactions.map((item) => { + return ( + + + + + + + + + + + ); + }) + } {/* {displayMenu ? : null} */} - + {showToast && ( { + let link; + Object.keys(row).map((key) => { + if (key === "MASTERS_WAGESEEKER_ID") + link = `/${window.contextPath}/employee/masters/view-wageseeker?tenantId=${tenantId}&wageseekerId=${row[key]}`; + }); + return link; + }, additionalCustomizations: (row, key, column, value, t, searchResult) => { switch (key) { diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/pages/citizen/index.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/pages/citizen/index.js index afd0a64f9..3dfd31f61 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/pages/citizen/index.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/payment/src/pages/citizen/index.js @@ -15,10 +15,13 @@ const CitizenApp = ({ path }) => { return ( -
+ margin: "0 auto", + marginTop:"2rem", + }} + > {!excludeBackBtn?.some(url => location.pathname.includes(url)) && {t("CS_COMMON_BACK")}}
In Open Payment Module
} /> diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/Inbox.js b/frontend/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/Inbox.js index 66a4903fd..5eebc3cf6 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/Inbox.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/modules/pgr/src/pages/employee/Inbox.js @@ -41,6 +41,7 @@ const Inbox = () => { }; const onSearch = (params = "") => { + setSearchParams({ ...searchParams, search: params }); }; diff --git a/frontend/micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/TopBar.js b/frontend/micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/TopBar.js index c26314496..0abdaeeee 100644 --- a/frontend/micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/TopBar.js +++ b/frontend/micro-ui/web/micro-ui-internals/packages/react-components/src/atoms/TopBar.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import PropTypes from "prop-types"; import Hamburger from "./Hamburger"; import { NotificationBell } from "./svgindex"; -import { useLocation } from "react-router-dom"; +import { useLocation, Link } from "react-router-dom"; import BackButton from "./BackButton"; const TopBar = ({ @@ -20,6 +20,11 @@ const TopBar = ({ hideNotificationIconOnSomeUrlsWhenNotLoggedIn, changeLanguage, }) => { + const [isOpen, setIsOpen] = useState(false); + + const handleClick = () => { + setIsOpen(!isOpen); + }; const { pathname } = useLocation(); // const showHaburgerorBackButton = () => { @@ -29,23 +34,65 @@ const TopBar = ({ // return ; // } // }; + + + const url = window.location.pathname; // Get the current URL pathname + const isPaymentPath = url.includes('/payment/'); // Check for payment path + + const paymentlogoUrl = isPaymentPath + ? window?.globalConfigs?.getConfig?.("LOGO_URL") // Show payment logo if path matches + : logoUrl; + console.log(isPaymentPath, "isPaymentPath"); return (
-
- {isMobile && } +
+ {isMobile && !isPaymentPath && } -

{cityOfCitizenShownBesideLogo}

+ {isPaymentPath && } + {!isPaymentPath &&

{cityOfCitizenShownBesideLogo}

}
- {!hideNotificationIconOnSomeUrlsWhenNotLoggedIn ? changeLanguage : null} - {!hideNotificationIconOnSomeUrlsWhenNotLoggedIn ? ( + +
+ + {isOpen && ( +
+
    +
  • + Admin Login +
  • +
  • + Employee Login +
  • +
+
+ )} +
+ + {!hideNotificationIconOnSomeUrlsWhenNotLoggedIn || isPaymentPath ? changeLanguage : null} + + {/* {!hideNotificationIconOnSomeUrlsWhenNotLoggedIn ? (
{notificationCountLoaded && notificationCount ? ( @@ -54,7 +101,11 @@ const TopBar = ({ ) : null}
- ) : null} + ) : null} */} +
+ +
+
diff --git a/frontend/micro-ui/web/webpack.config.js b/frontend/micro-ui/web/webpack.config.js index 32f5b82a8..da189d9d2 100644 --- a/frontend/micro-ui/web/webpack.config.js +++ b/frontend/micro-ui/web/webpack.config.js @@ -12,7 +12,13 @@ module.exports = { { test: /\.(js)$/, exclude: /node_modules/, - use: ["babel-loader"], + use: { + loader: "babel-loader", + options: { + presets: ["@babel/preset-env", "@babel/preset-react"], + plugins: ["@babel/plugin-proposal-optional-chaining"] + } + } }, { test: /\.css$/i, diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/WaterDaoImpl.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/WaterDaoImpl.java index 84f89fff7..0ba3d13be 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/WaterDaoImpl.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/WaterDaoImpl.java @@ -1,6 +1,10 @@ package org.egov.waterconnection.repository; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -36,6 +40,7 @@ import org.egov.waterconnection.web.models.WaterConnection; import org.egov.waterconnection.web.models.WaterConnectionRequest; import org.egov.waterconnection.web.models.WaterConnectionResponse; +import org.egov.waterconnection.web.models.collection.Payment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.JdbcTemplate; @@ -50,6 +55,8 @@ public class WaterDaoImpl implements WaterDao { @Autowired + private LedgerReportRowMapper ledgerReportRowMapper; + @Autowired private DemandNotGeneratedRowMapper demandNotGeneratedRowMapper; @Autowired @@ -669,17 +676,70 @@ public List getInactiveConsumerReport(Long monthStar return inactiveConsumerReportList; } - public List getConsumersByPreviousMeterReading(Long previousMeterReading, String tenantId) - { - StringBuilder query=new StringBuilder(wsQueryBuilder.DEMAND_NOT_GENERATED_QUERY); + public List getConsumersByPreviousMeterReading(Long previousMeterReading, String tenantId) { + StringBuilder query = new StringBuilder(wsQueryBuilder.DEMAND_NOT_GENERATED_QUERY); - List preparedStatement=new ArrayList<>(); + List preparedStatement = new ArrayList<>(); preparedStatement.add(tenantId); preparedStatement.add(previousMeterReading); preparedStatement.add(tenantId); - log.info("Query for consumer demand not generated "+ query +" prepared statement "+ preparedStatement); - List consumersDemandNotGeneratedList=jdbcTemplate.query(query.toString(),preparedStatement.toArray(),demandNotGeneratedRowMapper); + log.info("Query for consumer demand not generated " + query + " prepared statement " + preparedStatement); + List consumersDemandNotGeneratedList = jdbcTemplate.query(query.toString(), preparedStatement.toArray(), demandNotGeneratedRowMapper); return consumersDemandNotGeneratedList; } + + public List> getLedgerReport(String consumercode, String tenantId, Integer offset, Integer limit, String year,RequestInfoWrapper requestInfoWrapper) { + String[] years = year.split("-"); + if (years.length != 2) { + throw new IllegalArgumentException("Invalid fiscal year format"); + } + int startYear = Integer.parseInt(years[0]); + int endYear = Integer.parseInt(years[1]); + + LocalDate startDate = LocalDate.of(startYear, 4, 1); + LocalDate endDate = LocalDate.of(startYear + 1, 3, 31); + + Long startDateTime = LocalDateTime.of(startDate.getYear(), startDate.getMonth(), startDate.getDayOfMonth(), 0, 0, 0) + .atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + Long endDateTime = LocalDateTime.of(endDate, LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + + StringBuilder query = new StringBuilder(wsQueryBuilder.LEDGER_REPORT_QUERY); + + List preparedStatement = new ArrayList<>(); + preparedStatement.add(consumercode); + preparedStatement.add(tenantId); + preparedStatement.add(startDateTime); + preparedStatement.add(endDateTime); + + Integer newlimit = wsConfiguration.getDefaultLimit(); + Integer newoffset = wsConfiguration.getDefaultOffset(); + if (limit == null && offset == null) + newlimit = wsConfiguration.getMaxLimit(); + if (limit != null && limit <= wsConfiguration.getMaxLimit()) + newlimit = limit; + if (limit != null && limit >= wsConfiguration.getMaxLimit()) + newlimit = wsConfiguration.getMaxLimit(); + + if (offset != null) + newoffset = offset; + + if (newlimit > 0) { + query.append(" offset ? limit ? ;"); + preparedStatement.add(newoffset); + preparedStatement.add(newlimit); + } + + log.info("Query of ledger report:" + query + "and prepared statement" + preparedStatement); + ledgerReportRowMapper.setTenantId(tenantId); + ledgerReportRowMapper.setRequestInfo(requestInfoWrapper); + ledgerReportRowMapper.setStartYear(startYear); + ledgerReportRowMapper.setEndYear(endYear); + ledgerReportRowMapper.setConsumerCode(consumercode); + List> ledgerReportList= jdbcTemplate.query(query.toString(), preparedStatement.toArray(), ledgerReportRowMapper); + int fromIndex = Math.min(newoffset, ledgerReportList.size()); + int toIndex = Math.min(fromIndex + newlimit, ledgerReportList.size()); + return ledgerReportList.subList(fromIndex, toIndex); +// return ledgerReportList; + } } diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/FuzzySearchQueryBuilder.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/FuzzySearchQueryBuilder.java index db159acd0..3d60fb1f4 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/FuzzySearchQueryBuilder.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/FuzzySearchQueryBuilder.java @@ -110,6 +110,7 @@ public String getFuzzySearchQuery(SearchCriteria criteria, List ids){ } finalQuery = mapper.writeValueAsString(node); + log.info("final query is"+finalQuery); } catch (Exception e){ diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/WsQueryBuilder.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/WsQueryBuilder.java index 2fbe61322..7b9799011 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/WsQueryBuilder.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/builder/WsQueryBuilder.java @@ -194,7 +194,26 @@ public class WsQueryBuilder { "(select distinct consumercode from egbs_demand_v1 d inner join egbs_demanddetail_v1 dd on dd.demandid = d.id " + "where dd.taxheadcode='10101' and d.status ='ACTIVE' and d.businessservice='WS' and " + "d.tenantid=?) order by connectionno;"; - + + public static final String LEDGER_REPORT_QUERY = "SELECT connectionholder.userid as uuid,conn.connectionno as connectionNo,conn.oldconnectionno," + + "dem.taxperiodfrom as startdate,dem.taxperiodto as enddate," + + "dem.createdtime as demandGenerationDate," + + "dd.taxheadcode as code,dd.taxamount as taxamount " + + "FROM eg_ws_connection conn INNER JOIN eg_ws_connectionholder connectionholder " + + "ON connectionholder.connectionid = conn.id " + + "INNER JOIN egbs_demand_v1 dem ON dem.consumercode = conn.connectionno INNER JOIN " + + "egbs_demanddetail_v1 dd ON dd.demandid = dem.id " + + "WHERE dem.consumercode = ? AND conn.tenantId = ? AND dem.status = 'ACTIVE' " + + "AND taxperiodfrom>=? AND taxperiodto<=? "+ + "ORDER BY startdate"; + + public static final String TAX_AMOUNT_QUERY="SELECT SUM(taxamount) FROM egbs_demanddetail_v1 WHERE " + + "demandid IN (SELECT id FROM egbs_demand_v1 WHERE consumercode = ? AND taxperiodto < ? AND status='ACTIVE');"; + + public static final String TOTAL_AMOUNT_PAID_QUERY="SELECT SUM(totalamountpaid) FROM egcl_payment WHERE " + + "id IN (SELECT paymentid FROM egcl_paymentdetail WHERE billid IN " + + "(SELECT billid FROM egbs_billdetail_v1 WHERE consumercode = ?)) AND createdtime < ? AND paymentstatus!='CANCELLED';"; + /** * * @param criteria The WaterCriteria diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/rowmapper/LedgerReportRowMapper.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/rowmapper/LedgerReportRowMapper.java new file mode 100644 index 000000000..a95dd13b8 --- /dev/null +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/repository/rowmapper/LedgerReportRowMapper.java @@ -0,0 +1,255 @@ +package org.egov.waterconnection.repository.rowmapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.models.auth.In; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.egov.waterconnection.repository.ServiceRequestRepository; +import org.egov.waterconnection.repository.builder.WsQueryBuilder; +import org.egov.waterconnection.util.WaterServicesUtil; +import org.egov.waterconnection.web.models.*; +import org.egov.waterconnection.web.models.collection.Payment; +import org.egov.waterconnection.web.models.collection.PaymentResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.Instant; +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.time.temporal.ChronoUnit; + + +@Slf4j +@Component +@Setter +public class LedgerReportRowMapper implements ResultSetExtractor>> { + + @Autowired + private WaterServicesUtil waterServiceUtil; + + @Autowired + private ObjectMapper mapper; + + @Autowired + private ServiceRequestRepository serviceRequestRepository; + + @Autowired + private JdbcTemplate jdbcTemplate; + + @Autowired + private WsQueryBuilder wsQueryBuilder; + + String tenantId; + RequestInfoWrapper requestInfoWrapper; + Integer startYear; + Integer endYear; + String consumerCode; + + public void setRequestInfo(RequestInfoWrapper requestInfoWrapper) { + this.requestInfoWrapper = requestInfoWrapper; + } + + @Override + public List> extractData(ResultSet resultSet) throws SQLException, DataAccessException { + List> monthlyRecordsList = new ArrayList<>(); + Map ledgerReports = new HashMap<>(); + YearMonth startMonth = YearMonth.of(startYear, 4); + YearMonth endMonth; + YearMonth now = YearMonth.now(); + + if (startYear == now.getYear() || (startYear == now.getYear() - 1 && now.getMonthValue() <= 3)) { + endMonth = now; + } else { + endMonth = YearMonth.of(startYear + 1, 3); + } + + YearMonth currentMonth = startMonth; + + while (!currentMonth.isAfter(endMonth)) { + String monthAndYear = currentMonth.format(DateTimeFormatter.ofPattern("MMMM yyyy")); + LocalDate startOfMonth = currentMonth.atDay(1); + Long epochTime = startOfMonth.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(); + LedgerReport ledgerReport = new LedgerReport(); + ledgerReport.setDemand(new DemandLedgerReport()); + ledgerReport.getDemand().setMonthAndYear(monthAndYear); + ledgerReport.getDemand().setConnectionNo(consumerCode); + BigDecimal taxAmountResult = getMonthlyTaxAmount(epochTime, consumerCode); + BigDecimal totalAmountPaidResult = getMonthlyTotalAmountPaid(epochTime, consumerCode); + ledgerReport.getDemand().setArrears(taxAmountResult.subtract(totalAmountPaidResult)); + log.info("Arrers are "+ledgerReport.getDemand().getArrears()+" and monthandYear"+ ledgerReport.getDemand().getMonthAndYear()); + ledgerReports.put(monthAndYear, ledgerReport); + currentMonth = currentMonth.plusMonths(1); + } + while (resultSet.next()) { + Long dateLong = resultSet.getLong("enddate"); + LocalDate date = Instant.ofEpochMilli(dateLong).atZone(ZoneId.systemDefault()).toLocalDate(); + String monthAndYear = date.format(DateTimeFormatter.ofPattern("MMMM yyyy")); + + String code = resultSet.getString("code"); + + BigDecimal taxamount = resultSet.getBigDecimal("taxamount"); + + Long demandGenerationDateLong = resultSet.getLong("demandgenerationdate"); + LocalDate demandGenerationDateLocal = Instant.ofEpochMilli(demandGenerationDateLong).atZone(ZoneId.systemDefault()).toLocalDate(); + + LedgerReport ledgerReport = ledgerReports.get(monthAndYear); + + if (ledgerReport.getPayment() == null) { + ledgerReport.setPayment(new ArrayList<>()); + } + +// if (code.equals("10102")) { +// ledgerReport.getDemand().setArrears(taxamount != null ? taxamount : BigDecimal.ZERO); +// ledgerReport.getDemand().setMonthAndYear(monthAndYear); +// } else + BigDecimal arrers_Penalty=BigDecimal.ZERO; + if(code.equalsIgnoreCase("10201")) + { + arrers_Penalty=taxamount; + } + if(code.equalsIgnoreCase("WS_Round_Off")) + { + ledgerReport.getDemand().setTaxamount(ledgerReport.getDemand().getTaxamount().add(taxamount)); + } + if (code.equalsIgnoreCase("WS_TIME_PENALTY")) { + ledgerReport.getDemand().setPenalty(taxamount != null ? taxamount : BigDecimal.ZERO); + BigDecimal amount = ledgerReport.getDemand().getTaxamount() != null ? ledgerReport.getDemand().getTaxamount() : BigDecimal.ZERO; + ledgerReport.getDemand().setTotalForCurrentMonth((taxamount != null ? taxamount : BigDecimal.ZERO).add(amount)); + } else if (code.equalsIgnoreCase("10101")) { + ledgerReport.getDemand().setMonthAndYear(monthAndYear); + ledgerReport.getDemand().setDemandGenerationDate(demandGenerationDateLong); + ledgerReport.getDemand().setTaxamount(ledgerReport.getDemand().getTaxamount().add(taxamount)); + ledgerReport.getDemand().setTotalForCurrentMonth(ledgerReport.getDemand().getTaxamount().add(ledgerReport.getDemand().getPenalty() != null ? ledgerReport.getDemand().getPenalty() : BigDecimal.ZERO)); + long dueDateMillis = demandGenerationDateLocal.plus(10, ChronoUnit.DAYS).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(); + long penaltyAppliedDateMillis = demandGenerationDateLocal.plus(11, ChronoUnit.DAYS).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(); + ledgerReport.getDemand().setDueDate(dueDateMillis); + ledgerReport.getDemand().setPenaltyAppliedDate(penaltyAppliedDateMillis); +// ledgerReport.getDemand().setTotal_due_amount(ledgerReport.getDemand().getTotalForCurrentMonth().add(ledgerReport.getDemand().getArrears())); + } + ledgerReport.getDemand().setTotal_due_amount(ledgerReport.getDemand().getTotalForCurrentMonth().add(ledgerReport.getDemand().getArrears() != null ? ledgerReport.getDemand().getArrears() : BigDecimal.ZERO)); + ledgerReport.getDemand().setConnectionNo(resultSet.getString("connectionno")); + ledgerReport.getDemand().setOldConnectionNo(resultSet.getString("oldconnectionno")); + ledgerReport.getDemand().setUserId(resultSet.getString("uuid")); + log.info("Data inserted into map " + ledgerReport.toString()); + ledgerReports.put(monthAndYear, ledgerReport); + } + for (Map.Entry entry : ledgerReports.entrySet()) { + Map record = new HashMap<>(); + record.put(entry.getKey(), entry.getValue()); + monthlyRecordsList.add(record); + } + log.info("ledger report list" + monthlyRecordsList); + if (!monthlyRecordsList.isEmpty()) { + addPaymentToLedger(monthlyRecordsList); + } + monthlyRecordsList.sort(new Comparator>() { + @Override + public int compare(Map o1, Map o2) { + String monthAndYear1 = (String) o1.keySet().iterator().next(); + String monthAndYear2 = (String) o2.keySet().iterator().next(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM yyyy", Locale.ENGLISH); + YearMonth yearMonth1 = YearMonth.parse(monthAndYear1, formatter); + YearMonth yearMonth2 = YearMonth.parse(monthAndYear2, formatter); + + return yearMonth1.compareTo(yearMonth2); + } + }); + return monthlyRecordsList; + } + + public List addPaymentDetails(String consumerCode) { + if(consumerCode==null) + return null; + String service = "WS"; + StringBuilder URL = waterServiceUtil.getcollectionURL(); + URL.append(service).append("/_search").append("?").append("consumerCodes=").append(consumerCode) + .append("&").append("tenantId=").append(tenantId); + Object response = serviceRequestRepository.fetchResult(URL, requestInfoWrapper); + log.info("line 226 response " + response.toString()); + PaymentResponse paymentResponse = mapper.convertValue(response, PaymentResponse.class); + return paymentResponse.getPayments(); + } + + private void addPaymentToLedger(List> monthlyRecordList) { + for (Map record : monthlyRecordList) { + LedgerReport ledgerReport = (LedgerReport) record.values().iterator().next(); + if (ledgerReport.getDemand() == null) { + log.info("DemandLedgerReport is null for LedgerReport: {}", ledgerReport); + } + String consumerCode = ledgerReport.getDemand().getConnectionNo(); + log.info("consumer code is " + consumerCode); + List payments = addPaymentDetails(consumerCode); + boolean paymentMatched = false; + if(payments!=null) + { + BigDecimal totalPaymentInMonth=BigDecimal.ZERO; + BigDecimal totalBalanceLeftInMonth=BigDecimal.ZERO; + for (Payment payment : payments) { + Long transactionDateLong = payment.getTransactionDate(); + LocalDate transactionDate = Instant.ofEpochMilli(transactionDateLong).atZone(ZoneId.systemDefault()).toLocalDate(); + String transactionMonthAndYear = transactionDate.format(DateTimeFormatter.ofPattern("MMMM yyyy")); + if (ledgerReport.getDemand().getMonthAndYear().equals(transactionMonthAndYear)) { + PaymentLedgerReport paymentLedgerReport = new PaymentLedgerReport(); + paymentLedgerReport.setCollectionDate(transactionDateLong); + paymentLedgerReport.setReceiptNo(payment.getPaymentDetails().get(0).getReceiptNumber()); + paymentLedgerReport.setPaid(payment.getTotalAmountPaid()); + paymentLedgerReport.setBalanceLeft(payment.getTotalDue().subtract(paymentLedgerReport.getPaid())); + totalPaymentInMonth=totalPaymentInMonth.add(payment.getTotalAmountPaid()); + totalBalanceLeftInMonth=totalBalanceLeftInMonth.add(payment.getTotalDue()); + if (ledgerReport.getPayment() == null) { + ledgerReport.setPayment(new ArrayList<>()); + } + ledgerReport.getPayment().add(paymentLedgerReport); + paymentMatched = true; + } + } + ledgerReport.setTotalBalanceLeftInMonth(totalBalanceLeftInMonth); + ledgerReport.setTotalPaymentInMonth(totalPaymentInMonth); + } + if (!paymentMatched) { + PaymentLedgerReport defaultPaymentLedgerReport = new PaymentLedgerReport(); + defaultPaymentLedgerReport.setCollectionDate(null); + defaultPaymentLedgerReport.setReceiptNo("N/A"); + defaultPaymentLedgerReport.setPaid(BigDecimal.ZERO); + defaultPaymentLedgerReport.setBalanceLeft(ledgerReport.getDemand().getTotal_due_amount()); + + if (ledgerReport.getPayment() == null) { + ledgerReport.setPayment(new ArrayList<>()); + } + ledgerReport.getPayment().add(defaultPaymentLedgerReport); + } + } + } + + private BigDecimal getMonthlyTaxAmount(Long startDate, String consumerCode) { + StringBuilder taxAmountQuery = new StringBuilder(wsQueryBuilder.TAX_AMOUNT_QUERY); + List taxAmountParams = new ArrayList<>(); + taxAmountParams.add(consumerCode); + taxAmountParams.add(startDate); + BigDecimal ans = jdbcTemplate.queryForObject(taxAmountQuery.toString(), taxAmountParams.toArray(), BigDecimal.class); + if (ans != null) + return ans; + return BigDecimal.ZERO; + } + + private BigDecimal getMonthlyTotalAmountPaid(Long startDate, String consumerCode) { + StringBuilder totalAmountPaidQuery = new StringBuilder(wsQueryBuilder.TOTAL_AMOUNT_PAID_QUERY); + List totalAmountPaidParams = new ArrayList<>(); + totalAmountPaidParams.add(consumerCode); + totalAmountPaidParams.add(startDate); + BigDecimal ans = jdbcTemplate.queryForObject(totalAmountPaidQuery.toString(), totalAmountPaidParams.toArray(), BigDecimal.class); + if (ans != null) + return ans; + return BigDecimal.ZERO; + } +} diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterService.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterService.java index e4c9ed73b..0ab401e9c 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterService.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterService.java @@ -1,6 +1,7 @@ package org.egov.waterconnection.service; import java.util.List; +import java.util.Map; import javax.validation.Valid; @@ -54,4 +55,6 @@ List collectionReport(String paymentStartDate, String paym List inactiveConsumerReport(String monthStartDate,String monthEndDate,String tenantId, @Valid Integer offset, @Valid Integer limit, RequestInfo requestInfo); WaterConnectionResponse getConsumersWithDemandNotGenerated(String previousMeterReading, String tenantId,RequestInfo requestInfo); + + List> ledgerReport(String consumercode, String tenantId, Integer offset, Integer limit, String year,RequestInfoWrapper requestInfoWrapper); } diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterServiceImpl.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterServiceImpl.java index ba0803984..339ddd13c 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterServiceImpl.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/service/WaterServiceImpl.java @@ -8,6 +8,7 @@ import java.text.SimpleDateFormat; import java.time.*; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.Arrays; @@ -862,4 +863,11 @@ public WaterConnectionResponse getConsumersWithDemandNotGenerated(String previou SearchCriteria criteria=SearchCriteria.builder().connectionNoSet(connectionNo).tenantId(tenantId).build(); return search(criteria,requestInfo); } + + @Override + public List> ledgerReport(String consumercode, String tenantId, Integer offset, Integer limit, String year,RequestInfoWrapper requestInfoWrapper) + { + List> list = waterDaoImpl.getLedgerReport(consumercode, tenantId, offset, limit, year,requestInfoWrapper); + return list; + } } \ No newline at end of file diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/controller/WaterController.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/controller/WaterController.java index f4da10f1f..655cca28d 100644 --- a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/controller/WaterController.java +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/controller/WaterController.java @@ -1,6 +1,7 @@ package org.egov.waterconnection.web.controller; import java.util.List; +import java.util.Map; import javax.validation.Valid; @@ -244,4 +245,13 @@ public ResponseEntity getConsumersWithDemandNotGenerate return new ResponseEntity<>(response, HttpStatus.OK); } + @PostMapping("/ledger-report") + public ResponseEntity getLedgerReport(@Valid @RequestBody RequestInfoWrapper requestInfoWrapper, @RequestParam String consumercode, @RequestParam String tenantId, @RequestParam Integer offset, @RequestParam Integer limit, @RequestParam String year) { + List> list = waterService.ledgerReport(consumercode, tenantId, offset, limit, year,requestInfoWrapper); + LedgerReportResponse response = LedgerReportResponse.builder().ledgerReport(list). + responseInfo(responseInfoFactory.createResponseInfoFromRequestInfo(requestInfoWrapper.getRequestInfo(), true)). + tenantName(tenantId).financialYear(year).build(); + return new ResponseEntity<>(response, HttpStatus.OK); + } + } diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/DemandLedgerReport.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/DemandLedgerReport.java new file mode 100644 index 000000000..b84da9289 --- /dev/null +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/DemandLedgerReport.java @@ -0,0 +1,59 @@ +package org.egov.waterconnection.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DemandLedgerReport { + + @JsonProperty("consumerName") + private String consumerName = null; + + @JsonProperty("connectionNo") + private String connectionNo = null; + + @JsonProperty("oldConnectionNo") + private String oldConnectionNo = null; + + @JsonProperty("userId") + private String userId = null; + + @JsonProperty("month") + private String monthAndYear; + + @JsonProperty("demandGenerationDate") + private Long demandGenerationDate= 0L; + + @JsonProperty("code") + private String code = null; + + @JsonProperty("monthlyCharges") + private BigDecimal taxamount=BigDecimal.ZERO; + + @JsonProperty("penalty") + private BigDecimal penalty=BigDecimal.ZERO; + + @JsonProperty("totalForCurrentMonth") + private BigDecimal totalForCurrentMonth=BigDecimal.ZERO; + + @JsonProperty("previousMonthBalance") + private BigDecimal arrears=BigDecimal.ZERO; + + @JsonProperty("totalDues") + private BigDecimal total_due_amount=BigDecimal.ZERO; + + @JsonProperty("dueDateOfPayment") + private Long dueDate= 0L; + + @JsonProperty("penaltyAppliedOnDate") + private Long penaltyAppliedDate=0L; + +} diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReport.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReport.java new file mode 100644 index 000000000..720e7f2cb --- /dev/null +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReport.java @@ -0,0 +1,27 @@ +package org.egov.waterconnection.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class LedgerReport +{ + @JsonProperty("demand") + private DemandLedgerReport demand=null; + + @JsonProperty("payment") + private List payment=new ArrayList<>(); + + @JsonProperty("totalPaymentInMonth") + private BigDecimal totalPaymentInMonth=BigDecimal.ZERO; + + @JsonProperty("totalBalanceLeftInMonth") + private BigDecimal totalBalanceLeftInMonth=BigDecimal.ZERO; +} diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReportResponse.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReportResponse.java new file mode 100644 index 000000000..0d00ce4cd --- /dev/null +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/LedgerReportResponse.java @@ -0,0 +1,24 @@ +package org.egov.waterconnection.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import org.egov.common.contract.response.ResponseInfo; + +import java.util.List; +import java.util.Map; + +@Builder +public class LedgerReportResponse +{ + @JsonProperty("ledgerReport") + private List> ledgerReport; + + @JsonProperty("tenantName") + private String tenantName; + + @JsonProperty("financialYear") + private String financialYear; + + @JsonProperty("responseInfo") + private ResponseInfo responseInfo = null; +} diff --git a/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/PaymentLedgerReport.java b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/PaymentLedgerReport.java new file mode 100644 index 000000000..692bf7672 --- /dev/null +++ b/municipal-services/ws-services/src/main/java/org/egov/waterconnection/web/models/PaymentLedgerReport.java @@ -0,0 +1,28 @@ +package org.egov.waterconnection.web.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class PaymentLedgerReport +{ + @JsonProperty("paymentCollectionDate") + private Long collectionDate; + + @JsonProperty("receiptNo") + private String receiptNo=null; + + @JsonProperty("amountPaid") + private BigDecimal paid= BigDecimal.ZERO; + + @JsonProperty("balanceLeft") + private BigDecimal balanceLeft=BigDecimal.ZERO; +}