Java tutorial
/* * eGov SmartCity eGovernance suite aims to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) 2017 eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * Further, all user interfaces, including but not limited to citizen facing interfaces, * Urban Local Bodies interfaces, dashboards, mobile applications, of the program and any * derived works should carry eGovernments Foundation logo on the top right corner. * * For the logo, please refer http://egovernments.org/html/logo/egov_logo.png. * For any further queries on attribution, including queries on brand guidelines, * please contact contact@egovernments.org * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. * */ package org.egov.ptis.domain.service.property; import org.apache.commons.lang3.StringUtils; import org.egov.commons.CFinancialYear; import org.egov.commons.Installment; import org.egov.commons.entity.Source; import org.egov.demand.model.EgDemandDetails; import org.egov.eis.entity.Assignment; import org.egov.eis.service.AssignmentService; import org.egov.eis.service.PositionMasterService; import org.egov.infra.admin.master.entity.AppConfigValues; import org.egov.infra.admin.master.entity.Role; import org.egov.infra.admin.master.entity.User; import org.egov.infra.admin.master.service.AppConfigValueService; import org.egov.infra.admin.master.service.UserService; import org.egov.infra.config.core.ApplicationThreadLocals; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.notification.service.NotificationService; import org.egov.infra.persistence.entity.Address; import org.egov.infra.reporting.engine.ReportFormat; import org.egov.infra.reporting.engine.ReportOutput; import org.egov.infra.reporting.engine.ReportRequest; import org.egov.infra.reporting.engine.ReportService; import org.egov.infra.security.utils.SecurityUtils; import org.egov.infra.utils.ApplicationNumberGenerator; import org.egov.infra.utils.DateUtils; import org.egov.infra.workflow.entity.StateAware; import org.egov.infra.workflow.matrix.entity.WorkFlowMatrix; import org.egov.infra.workflow.service.SimpleWorkflowService; import org.egov.pims.commons.Position; import org.egov.ptis.client.bill.PTBillServiceImpl; import org.egov.ptis.client.util.PropertyTaxUtil; import org.egov.ptis.constants.PropertyTaxConstants; import org.egov.ptis.domain.dao.demand.PtDemandDao; import org.egov.ptis.domain.entity.demand.Ptdemand; import org.egov.ptis.domain.entity.enums.TransactionType; import org.egov.ptis.domain.entity.property.BasicProperty; import org.egov.ptis.domain.entity.property.BasicPropertyImpl; import org.egov.ptis.domain.entity.property.DocumentType; import org.egov.ptis.domain.entity.property.Property; import org.egov.ptis.domain.entity.property.PropertyID; import org.egov.ptis.domain.entity.property.PropertyOwnerInfo; import org.egov.ptis.domain.entity.property.VacancyRemission; import org.egov.ptis.domain.entity.property.VacancyRemissionApproval; import org.egov.ptis.domain.entity.property.VacancyRemissionDetails; import org.egov.ptis.domain.repository.vacancyremission.VacancyRemissionApprovalRepository; import org.egov.ptis.domain.repository.vacancyremission.VacancyRemissionRepository; import org.egov.ptis.service.utils.PropertyTaxCommonUtils; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.MessageSource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.ui.Model; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import static java.lang.Boolean.FALSE; import static org.egov.ptis.constants.PropertyTaxConstants.*; @Service @Transactional(readOnly = true) public class VacancyRemissionService { public static final String REJECTION_ACK_TEMPLATE = "vacancyRemission_rejectionAck"; private static final Logger LOG = LoggerFactory.getLogger(VacancyRemissionService.class); @Autowired private VacancyRemissionRepository vacancyRemissionRepository; @Autowired private VacancyRemissionApprovalRepository vacancyRemissionApprovalRepository; @Autowired private AssignmentService assignmentService; @Autowired private PositionMasterService positionMasterService; @Autowired private SecurityUtils securityUtils; @Autowired @Qualifier("workflowService") private SimpleWorkflowService<VacancyRemission> vacancyRemissionWorkflowService; @Autowired private PropertyTaxUtil propertyTaxUtil; @Autowired private PtDemandDao ptDemandDAO; @Autowired private PropertyService propertyService; @Autowired private ApplicationNumberGenerator applicationNumberGenerator; @Autowired @Qualifier("parentMessageSource") private MessageSource ptisMessageSource; @Autowired private NotificationService notificationService; @Autowired private PropertyTaxCommonUtils propertyTaxCommonUtils; @Autowired private ReportService reportService; @Autowired private UserService userService; @Autowired private AppConfigValueService appConfigValuesService; @Autowired private PTBillServiceImpl ptBillServiceImpl; public VacancyRemission getApprovedVacancyRemissionForProperty(final String upicNo) { return vacancyRemissionRepository.findByUpicNo(upicNo); } public VacancyRemission getLatestRejectAckGeneratedVacancyRemissionForProperty(final String upicNo) { VacancyRemission vacancyRemission = null; final List<VacancyRemission> rejectedRemissionList = vacancyRemissionRepository .findAllRejectionAckGeneratedForUpicNo(upicNo); if (!rejectedRemissionList.isEmpty()) vacancyRemission = rejectedRemissionList.get(0); return vacancyRemission; } public VacancyRemission getLatestSpecialNoticeGeneratedVacancyRemissionForProperty(final String upicNo) { VacancyRemission vacancyRemission = null; final List<VacancyRemission> approvedRemissionList = vacancyRemissionRepository .findAllSpecialNoticesGeneratedForUpicNo(upicNo); if (!approvedRemissionList.isEmpty()) vacancyRemission = approvedRemissionList.get(0); return vacancyRemission; } public VacancyRemission getVacancyRemissionById(final Long id) { return vacancyRemissionRepository.findOne(id); } public List<VacancyRemission> getAllVacancyRemissionByUpicNo(final String upicNo) { return vacancyRemissionRepository.getAllVacancyRemissionByUpicNo(upicNo); } public VacancyRemission getRejectedVacancyRemissionForProperty(final String upicNo) { return vacancyRemissionRepository.findRejectedByUpicNo(upicNo); } public VacancyRemission getVRUnderWFByUpicNo(final String upicNo) { return vacancyRemissionRepository.getVRUnderWorkflowByUpicNo(upicNo); } @Transactional public VacancyRemission saveVacancyRemission(final VacancyRemission vacancyRemission, Long approvalPosition, final String approvalComent, final String additionalRule, final String workFlowAction, final Boolean propertyByEmployee) { if (LOG.isDebugEnabled()) LOG.debug(" Create WorkFlow Transition Started ..."); final User user = securityUtils.getCurrentUser(); final DateTime currentDate = new DateTime(); Position pos = null; Assignment wfInitiator = null; String currentState; Assignment assignment; String approverDesignation = ""; String nextAction = null; String loggedInUserDesignation; loggedInUserDesignation = getLoggedInUserDesignation(vacancyRemission, user); String loggedInUserDesig = ""; List<Assignment> loggedInUserAssign; if (vacancyRemission.getState() != null) { loggedInUserAssign = assignmentService.getAssignmentByPositionAndUserAsOnDate( vacancyRemission.getCurrentState().getOwnerPosition().getId(), user.getId(), new Date()); loggedInUserDesig = !loggedInUserAssign.isEmpty() ? loggedInUserAssign.get(0).getDesignation().getName() : ""; } if (SOURCE_ONLINE.equalsIgnoreCase(vacancyRemission.getSource()) && ApplicationThreadLocals.getUserId() == null) ApplicationThreadLocals.setUserId(securityUtils.getCurrentUser().getId()); if (propertyService.isCitizenPortalUser(user) || !propertyByEmployee || ANONYMOUS_USER.equalsIgnoreCase(user.getName())) { currentState = "Created"; if (propertyService.isCscOperator(user)) { assignment = propertyService.getMappedAssignmentForCscOperator(vacancyRemission.getBasicProperty()); wfInitiator = assignment; } else { assignment = propertyService.getUserPositionByZone(vacancyRemission.getBasicProperty(), false); wfInitiator = assignment; } if (null != assignment) approvalPosition = assignment.getPosition().getId(); } else { currentState = null; if (null != approvalPosition && approvalPosition != 0) { assignment = assignmentService.getAssignmentsForPosition(approvalPosition, new Date()).get(0); assignment.getEmployee().getName().concat("~").concat(assignment.getPosition().getName()); approverDesignation = assignment.getDesignation().getName(); } } if (WFLOW_ACTION_STEP_FORWARD.equalsIgnoreCase(workFlowAction) && (vacancyRemission.getId() == null || ASSISTANT_DESIGNATIONS.contains(loggedInUserDesig)) && (COMMISSIONER_DESIGNATIONS.contains(approverDesignation))) { final String designation = approverDesignation.split(" ")[0]; nextAction = getWorkflowNextAction(designation); } if (vacancyRemission.getId() != null && (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT) || workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE))) wfInitiator = getWorkflowInitiator(vacancyRemission); else if (wfInitiator == null) wfInitiator = propertyTaxCommonUtils.getWorkflowInitiatorAssignment(user.getId()); if (StringUtils.isBlank(vacancyRemission.getApplicationNumber())) vacancyRemission.setApplicationNumber(applicationNumberGenerator.generate()); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE)) { if (wfInitiator.getPosition().equals(vacancyRemission.getState().getOwnerPosition())) { vacancyRemission.setStatus(VR_STATUS_REJECTION_ACK_GENERATED); vacancyRemission.transition().end().withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withDateInfo(currentDate.toDate()).withNextAction(null) .withOwner(vacancyRemission.getCurrentState().getOwnerPosition()); vacancyRemission.getBasicProperty().setUnderWorkflow(false); } } else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT)) { final String stateValue = VR_APP_STATUS_REJECTED; vacancyRemission.setStatus(VR_STATUS_REJECTED); vacancyRemission.transition().progressWithStateCopy() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withStateValue(stateValue).withDateInfo(currentDate.toDate()) .withOwner(wfInitiator.getPosition()).withNextAction("Application Rejected"); buildSMS(vacancyRemission, workFlowAction); } else { if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_FORWARD)) vacancyRemission.setStatus(VR_STATUS_WORKFLOW); else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)) vacancyRemission.setStatus(VR_STATUS_APPROVED); if (null != approvalPosition && approvalPosition != -1 && !approvalPosition.equals(Long.valueOf(0))) pos = positionMasterService.getPositionById(approvalPosition); WorkFlowMatrix wfmatrix; if (null == vacancyRemission.getState()) { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemission.getStateType(), null, null, additionalRule, currentState, null); if (propertyService.isCitizenPortalUser(securityUtils.getCurrentUser()) || !propertyByEmployee || ANONYMOUS_USER.equalsIgnoreCase(user.getName())) nextAction = WF_STATE_ASSISTANT_FORWARD_PENDING; vacancyRemission.transition().start().withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(new Date()).withOwner(pos).withNextAction(nextAction) .withNatureOfTask(NATURE_VACANCY_REMISSION) .withInitiator(wfInitiator != null ? wfInitiator.getPosition() : null); vacancyRemission.getBasicProperty().setUnderWorkflow(true); } else { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemission.getStateType(), null, null, additionalRule, vacancyRemission.getCurrentState().getValue(), vacancyRemission.getCurrentState().getNextAction(), null, loggedInUserDesignation); if (wfmatrix != null) if ("END".equalsIgnoreCase(wfmatrix.getNextAction())) vacancyRemission.transition().progressWithStateCopy() .withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(currentDate.toDate()).withNextAction(VR_STATUS_MONTHLY_UPDATE); else vacancyRemission.transition().progressWithStateCopy() .withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(currentDate.toDate()).withOwner(pos) .withNextAction(nextAction == null ? wfmatrix.getNextAction() : nextAction); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)) buildSMS(vacancyRemission, workFlowAction); } } propertyService.updateIndexes(vacancyRemission, APPLICATION_TYPE_VACANCY_REMISSION); if (Source.CITIZENPORTAL.toString().equalsIgnoreCase(vacancyRemission.getSource()) && propertyService.getPortalInbox(vacancyRemission.getApplicationNumber()) != null) { propertyService.updatePortal(vacancyRemission, APPLICATION_TYPE_VACANCY_REMISSION); } if (LOG.isDebugEnabled()) LOG.debug(" WorkFlow Transition Completed ..."); return vacancyRemissionRepository.save(vacancyRemission); } /** * Provides 50% rebate on the next installment taxes * * @param vacancyRemission * @param demandInstallment * @param effectiveInstallment */ private void updateDemandDetailsWithRebate(final VacancyRemission vacancyRemission, final Installment demandInstallment, final Installment effectiveInstallment) { final Set<Ptdemand> activePropPtDemandSet = vacancyRemission.getBasicProperty().getActiveProperty() .getPtDemandSet(); BigDecimal excess = BigDecimal.ZERO; final Set<String> demandReasons = new LinkedHashSet<>(Arrays.asList(DEMANDRSN_CODE_GENERAL_TAX, DEMANDRSN_CODE_VACANT_TAX, DEMANDRSN_CODE_EDUCATIONAL_TAX, DEMANDRSN_CODE_LIBRARY_CESS, DEMANDRSN_CODE_UNAUTHORIZED_PENALTY, DEMANDRSN_CODE_SCAVENGE_TAX, DEMANDRSN_CODE_WATER_TAX, DEMANDRSN_CODE_LIGHT_TAX, DEMANDRSN_CODE_DRAINAGE_TAX)); Ptdemand currPtDemand = getCurrentPTDemand(demandInstallment, activePropPtDemandSet); if (currPtDemand != null) { final Set<EgDemandDetails> effectiveInstDemandDetails = propertyService .getEgDemandDetailsSetByInstallment(currPtDemand.getEgDemandDetails()) .get(effectiveInstallment); for (final String demandReason : demandReasons) { final EgDemandDetails dmdDet = propertyService .getEgDemandDetailsForReason(effectiveInstDemandDetails, demandReason); if (dmdDet != null) { dmdDet.setAmount( dmdDet.getAmount().divide(new BigDecimal("2")).setScale(0, BigDecimal.ROUND_HALF_UP)); excess = adjustCollection(excess, dmdDet); } } EgDemandDetails advanceDemandDetails = propertyService .getEgDemandDetailsForReason(effectiveInstDemandDetails, ADVANCE_DMD_RSN_CODE); updateAdvance(currPtDemand, excess, advanceDemandDetails); ptDemandDAO.update(currPtDemand); } } private BigDecimal adjustCollection(BigDecimal excess, final EgDemandDetails dmdDet) { if (dmdDet.getAmtCollected().compareTo(dmdDet.getAmount()) > 0) { excess = excess.add(dmdDet.getAmtCollected().subtract(dmdDet.getAmount())); dmdDet.setAmtCollected(dmdDet.getAmount()); } else if (excess.compareTo(BigDecimal.ZERO) > 0) { excess = adjustExcessToCollection(excess, dmdDet); } return excess; } private BigDecimal adjustExcessToCollection(BigDecimal excess, final EgDemandDetails dmdDet) { if (excess.compareTo((dmdDet.getAmount().subtract(dmdDet.getAmtCollected()))) > 0) { excess = excess.subtract(dmdDet.getAmount().subtract(dmdDet.getAmtCollected())); dmdDet.setAmtCollected(dmdDet.getAmount()); } else { dmdDet.setAmtCollected(dmdDet.getAmtCollected().add(excess)); excess = BigDecimal.ZERO; } return excess; } private Ptdemand getCurrentPTDemand(final Installment demandInstallment, final Set<Ptdemand> activePropPtDemandSet) { Ptdemand currPtDemand = null; for (final Ptdemand ptDemand : activePropPtDemandSet) if (ptDemand.getIsHistory().equalsIgnoreCase("N") && ptDemand.getEgInstallmentMaster().equals(demandInstallment)) { currPtDemand = ptDemand; break; } return currPtDemand; } private void updateAdvance(Ptdemand currPtDemand, BigDecimal excess, EgDemandDetails advanceDemandDetails) { if (excess.compareTo(BigDecimal.ZERO) > 0) { EgDemandDetails newDtls; final Map<String, Installment> yearwiseInstMap = propertyTaxUtil.getInstallmentsForCurrYear(new Date()); final Installment installment = yearwiseInstMap.get(CURRENTYEAR_SECOND_HALF); if (advanceDemandDetails != null) advanceDemandDetails.setAmtCollected(advanceDemandDetails.getAmtCollected().add(excess)); else { newDtls = ptBillServiceImpl.insertDemandDetails(ADVANCE_DMD_RSN_CODE, excess, installment); currPtDemand.addEgDemandDetails(newDtls); } } } public void addModelAttributes(final Model model, final BasicProperty basicProperty) { final Property property = basicProperty.getActiveProperty(); model.addAttribute("property", property); final Ptdemand ptDemand = ptDemandDAO.getNonHistoryCurrDmdForProperty(property); if (ptDemand != null && ptDemand.getDmdCalculations() != null && ptDemand.getDmdCalculations().getAlv() != null) model.addAttribute("ARV", ptDemand.getDmdCalculations().getAlv()); else model.addAttribute("ARV", BigDecimal.ZERO); if (!basicProperty.getActiveProperty().getIsExemptedFromTax()) { try { // Based on the current installment, fetch tax details for the respective installment final Map<String, Map<String, BigDecimal>> demandCollMap = propertyTaxUtil .prepareDemandDetForView(property, propertyTaxCommonUtils.getCurrentInstallment()); final Map<String, BigDecimal> currentTaxDetails = propertyService .getCurrentTaxDetails(demandCollMap, new Date()); model.addAttribute("propertyTax", propertyTaxCommonUtils.getAggregateGenralTax(currentTaxDetails)); model.addAttribute("eduCess", currentTaxDetails.get(DEMANDRSN_STR_EDUCATIONAL_TAX) == null ? BigDecimal.ZERO : currentTaxDetails.get(DEMANDRSN_STR_EDUCATIONAL_TAX)); model.addAttribute("libraryCess", currentTaxDetails.get(DEMANDRSN_STR_LIBRARY_CESS) == null ? BigDecimal.ZERO : currentTaxDetails.get(DEMANDRSN_STR_LIBRARY_CESS)); model.addAttribute("currTax", currentTaxDetails.get(CURR_DMD_STR)); model.addAttribute("currTaxDue", currentTaxDetails.get(CURR_BAL_STR)); model.addAttribute("totalTax", currentTaxDetails.get(CURR_DMD_STR)); model.addAttribute("totalArrDue", currentTaxDetails.get(ARR_BAL_STR)); } catch (final Exception e) { LOG.error("Exception in addModelAttributes : ", e); throw new ApplicationRuntimeException("Exception in addModelAttributes : " + e); } model.addAttribute("propertyByEmployee", checkIfEmployee(getLoggedInUser())); } } public Boolean checkIfEmployee(final User user) { return !propertyService.isCitizenPortalUser(user) && propertyService.isEmployee(user) && !ANONYMOUS_USER.equalsIgnoreCase(user.getName()); } public String getInitiatorName(final VacancyRemission vacancyRemission) { String initiatorName; Assignment assignment; if (checkIfEmployee(vacancyRemission.getCreatedBy())) assignment = assignmentService.getPrimaryAssignmentForUser(vacancyRemission.getCreatedBy().getId()); else { if (vacancyRemission.getState().getInitiatorPosition() == null) assignment = assignmentService.getPrimaryAssignmentForPositon( vacancyRemission.getStateHistory().get(0).getOwnerPosition().getId()); else assignment = assignmentService .getPrimaryAssignmentForPositon(vacancyRemission.getState().getInitiatorPosition().getId()); } initiatorName = assignment.getEmployee().getName().concat("~").concat(assignment.getPosition().getName()); return initiatorName; } public Assignment getWorkflowInitiator(final VacancyRemission vacancyRemission) { Assignment wfInitiator; if (checkIfEmployee(vacancyRemission.getCreatedBy())) { if (vacancyRemission.getState() != null && vacancyRemission.getState().getInitiatorPosition() != null) wfInitiator = propertyTaxCommonUtils.getUserAssignmentByPassingPositionAndUser( vacancyRemission.getCreatedBy(), vacancyRemission.getState().getInitiatorPosition()); else wfInitiator = assignmentService .getPrimaryAssignmentForUser(vacancyRemission.getCreatedBy().getId()); } else if (!vacancyRemission.getStateHistory().isEmpty()) { if (vacancyRemission.getState().getInitiatorPosition() == null) wfInitiator = assignmentService.getPrimaryAssignmentForPositon( vacancyRemission.getStateHistory().get(0).getOwnerPosition().getId()); else wfInitiator = assignmentService .getPrimaryAssignmentForPositon(vacancyRemission.getState().getInitiatorPosition().getId()); } else wfInitiator = assignmentService .getPrimaryAssignmentForPositon(vacancyRemission.getState().getOwnerPosition().getId()); return wfInitiator; } @Transactional public void saveRemissionDetails(final VacancyRemission vacancyRemission) { vacancyRemissionRepository.save(vacancyRemission); } @Transactional public void rejectVacancyRemission(final VacancyRemission vacancyRemission, final String commnets, final HttpServletRequest request) { final User user = securityUtils.getCurrentUser(); Position wfInitiator; if (vacancyRemission != null) { wfInitiator = vacancyRemission.getState().getInitiatorPosition(); vacancyRemission.transition().progressWithStateCopy() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(commnets) .withStateValue(VR_APP_STATUS_REJECTED).withDateInfo(new Date()).withOwner(wfInitiator) .withNextAction("Generate Notice"); vacancyRemission.setStatus(VR_STATUS_REJECTED); buildSMS(vacancyRemission, "Reject"); } vacancyRemissionRepository.save(vacancyRemission); } public List<VacancyRemissionDetails> getMonthlyDetailsHistory(final VacancyRemission vacancyRemission) { List<VacancyRemissionDetails> historyList = new ArrayList<>(); if (!vacancyRemission.getVacancyRemissionDetails().isEmpty()) { historyList = vacancyRemission.getVacancyRemissionDetails(); Collections.reverse(historyList); } return historyList; } public VacancyRemissionApproval getVacancyRemissionApprovalById(final Long id) { return vacancyRemissionApprovalRepository.findOne(id); } @Transactional public void saveVacancyRemissionApproval(final VacancyRemissionApproval vacancyRemissionApproval, final Long approvalPosition, final String approvalComent, final String additionalRule, final String workFlowAction) { if (LOG.isDebugEnabled()) LOG.debug(" Create WorkFlow Transition Started ..."); final User user = securityUtils.getCurrentUser(); final DateTime currentDate = new DateTime(); Position pos = null; Assignment wfInitiator; Assignment assignment; String approverDesignation = ""; String nextAction = ""; List<Assignment> loggedInUserAssign; String loggedInUserDesignation = ""; wfInitiator = getInitiatorOnWFAction(vacancyRemissionApproval, workFlowAction); if (wfInitiator == null) wfInitiator = getWorkflowInitiatorAssignment(user.getId(), Arrays.asList(PropertyTaxConstants.REVENUE_INSPECTOR_DESGN)); if (null != approvalPosition && approvalPosition != 0) { assignment = assignmentService.getAssignmentsForPosition(approvalPosition, new Date()).get(0); approverDesignation = assignment.getDesignation().getName(); } if (vacancyRemissionApproval.getState() != null) { loggedInUserAssign = assignmentService.getAssignmentByPositionAndUserAsOnDate( vacancyRemissionApproval.getCurrentState().getOwnerPosition().getId(), user.getId(), new Date()); loggedInUserDesignation = !loggedInUserAssign.isEmpty() ? loggedInUserAssign.get(0).getDesignation().getName() : null; } if (WFLOW_ACTION_STEP_FORWARD.equalsIgnoreCase(workFlowAction) && (approverDesignation.equalsIgnoreCase(ASSISTANT_COMMISSIONER_DESIGN) || approverDesignation.equalsIgnoreCase(DEPUTY_COMMISSIONER_DESIGN) || approverDesignation.equalsIgnoreCase(ADDITIONAL_COMMISSIONER_DESIGN) || approverDesignation.equalsIgnoreCase(ZONAL_COMMISSIONER_DESIGN) || approverDesignation.equalsIgnoreCase(COMMISSIONER_DESGN))) if (vacancyRemissionApproval.getStatus().equals(VR_STATUS_APPROVED)) nextAction = WF_STATE_DIGITAL_SIGNATURE_PENDING; else { final String designation = approverDesignation.split(" ")[0]; nextAction = getApprovalAsNextAction(designation); } if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE)) { if (VR_STATUS_APPROVED.equalsIgnoreCase(vacancyRemissionApproval.getStatus())) { vacancyRemissionApproval.setStatus(VR_STATUS_NOTICE_GENERATED); vacancyRemissionApproval.transition().end() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withDateInfo(currentDate.toDate()).withNextAction(null) .withOwner(vacancyRemissionApproval.getCurrentState().getOwnerPosition()); } else { vacancyRemissionApproval.setStatus(VR_STATUS_REJECTION_ACK_GENERATED); vacancyRemissionApproval.transition().end() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withDateInfo(currentDate.toDate()).withNextAction(null) .withOwner(vacancyRemissionApproval.getCurrentState().getOwnerPosition()); } } else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT)) { if (wfInitiator != null) if (wfInitiator.getPosition() .equals(vacancyRemissionApproval.getCurrentState().getOwnerPosition())) { vacancyRemissionApproval.transition().end() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withDateInfo(currentDate.toDate()).withNextAction(null) .withOwner(vacancyRemissionApproval.getCurrentState().getOwnerPosition()); vacancyRemissionApproval.setStatus(VR_STATUS_REJECTED); vacancyRemissionApproval.getVacancyRemission().getBasicProperty().setUnderWorkflow(FALSE); } else { vacancyRemissionApproval.transition().progressWithStateCopy() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withStateValue(WF_STATE_REJECTED).withDateInfo(currentDate.toDate()) .withOwner(wfInitiator.getPosition()) .withNextAction(WF_STATE_UD_REVENUE_INSPECTOR_APPROVAL_PENDING) .withNatureOfTask(NATURE_VACANCY_REMISSION_APPROVAL); vacancyRemissionApproval.setStatus(VR_STATUS_REJECTED); } } else { if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_FORWARD) && vacancyRemissionApproval.getStatus() == null) vacancyRemissionApproval.setStatus(VR_STATUS_WORKFLOW); else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)) { vacancyRemissionApproval.setStatus(VR_STATUS_APPROVED); vacancyRemissionApproval.setIsApproved(true); vacancyRemissionApproval.setApprovalDate(new Date()); } if (WFLOW_ACTION_STEP_APPROVE.equalsIgnoreCase(workFlowAction)) pos = vacancyRemissionApproval.getCurrentState().getOwnerPosition(); else if (null != approvalPosition && approvalPosition != -1 && !approvalPosition.equals(Long.valueOf(0))) pos = positionMasterService.getPositionById(approvalPosition); WorkFlowMatrix wfmatrix; if (null == vacancyRemissionApproval.getState()) { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemissionApproval.getStateType(), null, null, additionalRule, null, null); vacancyRemissionApproval.transition().start() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withStateValue(wfmatrix.getNextState()).withDateInfo(new Date()).withOwner(pos) .withNextAction(wfmatrix.getNextAction()) .withNatureOfTask(NATURE_VACANCY_REMISSION_APPROVAL) .withInitiator(wfInitiator != null ? wfInitiator.getPosition() : null); } else if ("END".equalsIgnoreCase(vacancyRemissionApproval.getCurrentState().getNextAction())) vacancyRemissionApproval.transition().end() .withSenderName(user.getUsername() + "::" + user.getName()).withComments(approvalComent) .withDateInfo(currentDate.toDate()).withNextAction(null) .withOwner(vacancyRemissionApproval.getCurrentState().getOwnerPosition()); else { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemissionApproval.getStateType(), null, null, additionalRule, vacancyRemissionApproval.getCurrentState().getValue(), vacancyRemissionApproval.getCurrentState().getNextAction(), null, loggedInUserDesignation); vacancyRemissionApproval.transition().progress().withSenderName(user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(currentDate.toDate()).withOwner(pos) .withNextAction(StringUtils.isNotBlank(nextAction) ? nextAction : wfmatrix.getNextAction()) .withNatureOfTask(NATURE_VACANCY_REMISSION_APPROVAL); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)) wFApprove(vacancyRemissionApproval); } } propertyService.updateIndexes(vacancyRemissionApproval, APPLICATION_TYPE_VACANCY_REMISSION_APPROVAL); if (Source.CITIZENPORTAL.toString() .equalsIgnoreCase(vacancyRemissionApproval.getVacancyRemission().getSource()) && propertyService.getPortalInbox( vacancyRemissionApproval.getVacancyRemission().getApplicationNumber()) != null) { propertyService.updatePortal(vacancyRemissionApproval.getVacancyRemission(), APPLICATION_TYPE_VACANCY_REMISSION); } if (LOG.isDebugEnabled()) LOG.debug(" WorkFlow Transition Completed ..."); vacancyRemissionApprovalRepository.save(vacancyRemissionApproval); } private void wFApprove(final VacancyRemissionApproval vacancyRemissionApproval) { final Map<String, Installment> installmentMap = propertyTaxUtil.getInstallmentsForCurrYear(new Date()); final Installment installmentFirstHalf = installmentMap.get(CURRENTYEAR_FIRST_HALF); final Installment installmentSecondHalf = installmentMap.get(CURRENTYEAR_SECOND_HALF); /* * If VR is done in 1st half, provide 50% rebate on taxes of the 2nd half */ if (DateUtils.between(new Date(), installmentFirstHalf.getFromDate(), installmentFirstHalf.getToDate())) updateDemandDetailsWithRebate(vacancyRemissionApproval.getVacancyRemission(), installmentFirstHalf, installmentSecondHalf); } public User getLoggedInUser() { return securityUtils.getCurrentUser(); } public VacancyRemission saveVacancyRemission(final VacancyRemission vacancyRemission, final Long approvalPosition, final String approvalComent, final String additionalRule, final String workFlowAction, final Boolean propertyByEmployee, final HashMap<String, String> meesevaParams) { return saveVacancyRemission(vacancyRemission, approvalPosition, approvalComent, additionalRule, workFlowAction, propertyByEmployee); } public void buildSMS(final VacancyRemission vacancyRemission, final String workFlowAction) { for (final PropertyOwnerInfo ownerInfo : vacancyRemission.getBasicProperty().getPropertyOwnerInfo()) if (StringUtils.isNotBlank(ownerInfo.getOwner().getMobileNumber())) buildSms(vacancyRemission, ownerInfo.getOwner(), workFlowAction); } private void buildSms(final VacancyRemission vacancyRemission, final User user, final String workFlowAction) { final String assessmentNo = vacancyRemission.getBasicProperty().getUpicNo(); final String mobileNumber = user.getMobileNumber(); final String applicantName = user.getName(); String smsMsg = ""; if (workFlowAction.equals(WFLOW_ACTION_STEP_FORWARD)) { // to be enabled once acknowledgement feature is developed /* * smsMsg = messageSource.getMessage("vacancyremission.ack.sms", new String[] { applicantName, assessmentNo }, null); */ } else if (workFlowAction.equals(WFLOW_ACTION_STEP_REJECT)) smsMsg = ptisMessageSource.getMessage("vacancyremission.rejection.sms", new String[] { applicantName, assessmentNo, ApplicationThreadLocals.getMunicipalityName() }, null); else if (workFlowAction.equals(WFLOW_ACTION_STEP_APPROVE)) smsMsg = ptisMessageSource.getMessage("vacancyremission.approval.sms", new String[] { applicantName, assessmentNo, ApplicationThreadLocals.getMunicipalityName() }, null); if (StringUtils.isNotBlank(mobileNumber)) notificationService.sendSMS(mobileNumber, smsMsg); } public List<DocumentType> getDocuments(final TransactionType transactionType) { return propertyService.getDocumentTypesForTransactionType(transactionType); } public DocumentType getDocType(final String docname) { return vacancyRemissionRepository.findDocumentTypeByNameAndTransactionType(docname, TransactionType.VACANCYREMISSION); } public DocumentType getMUDocType(final String name) { return vacancyRemissionRepository.findDocumentTypeByNameAndTransactionType(name, TransactionType.VRMONTHLYUPDATE); } public ReportOutput generateReport(final VacancyRemission vacancyRemission, final HttpServletRequest request, final String approvedUser, final String noticeNo) { ReportOutput reportOutput = null; if (vacancyRemission != null) { reportOutput = reportService .createReport(generateVRReportRequest(vacancyRemission, noticeNo, request, approvedUser)); } return reportOutput; } public ReportRequest generateVRReportRequest(VacancyRemission vacancyRemission, String noticeNo, HttpServletRequest request, final String approvedUser) { ReportRequest reportInput = null; CFinancialYear financialYear; if (vacancyRemission != null) { final BasicPropertyImpl basicProperty = vacancyRemission.getBasicProperty(); final Map<String, Object> reportParams = new HashMap<>(); final SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); final String cityName = request.getSession().getAttribute("citymunicipalityname").toString(); final String cityGrade = request.getSession().getAttribute("cityGrade") != null ? request.getSession().getAttribute("cityGrade").toString() : null; Boolean isCorporation; if (StringUtils.isNoneBlank(cityGrade) && CITY_GRADE_CORPORATION.equalsIgnoreCase(cityGrade)) isCorporation = true; else isCorporation = false; final Address ownerAddress = basicProperty.getAddress(); final PropertyID propertyId = basicProperty.getPropertyID(); reportParams.put("isCorporation", isCorporation); reportParams.put("cityName", cityName); reportParams.put("userSignature", securityUtils.getCurrentUser().getSignature() != null ? new ByteArrayInputStream(securityUtils.getCurrentUser().getSignature()) : ""); reportParams.put("loggedInUsername", approvedUser); reportParams.put("approvedDate", formatter.format(vacancyRemission.getState().getCreatedDate())); reportParams.put("approverName", userService.getUserById(ApplicationThreadLocals.getUserId()).getName()); reportParams.put("applicationDate", formatter.format(vacancyRemission.getCreatedDate())); reportParams.put("currentDate", formatter.format(new Date())); reportParams.put("noticeNo", noticeNo); reportParams.put("ownerName", basicProperty.getFullOwnerName()); reportParams.put("houseNo", ownerAddress.getHouseNoBldgApt()); reportParams.put("assessmentNo", basicProperty.getUpicNo()); reportParams.put("locality", propertyId.getLocality().getName()); reportParams.put("vrFromDate", formatter.format(vacancyRemission.getVacancyFromDate())); reportParams.put("vrToDate", formatter.format(vacancyRemission.getVacancyToDate())); final int noOfMonths = DateUtils.noOfMonthsBetween(vacancyRemission.getVacancyFromDate(), new DateTime(vacancyRemission.getVacancyToDate()).plusDays(1).toDate()); reportParams.put("totalMonths", noOfMonths); final Map<String, BigDecimal> currentDemand = ptDemandDAO .getDemandCollMap(vacancyRemission.getBasicProperty().getProperty()); BigDecimal halfYearTax = currentDemand.get(CURR_SECONDHALF_DMD_STR); BigDecimal newTax = BigDecimal.ZERO; financialYear = propertyTaxUtil.getFinancialYearforDate(new Date()); final Map<String, Installment> installmentMap = propertyTaxUtil.getInstallmentsForCurrYear( vacancyRemission.getVacancyRemissionApproval().get(0).getApprovalDate()); final Installment installmentFirstHalf = installmentMap.get(CURRENTYEAR_FIRST_HALF); final Installment installmentSecondHalf = installmentMap.get(CURRENTYEAR_SECOND_HALF); Ptdemand currPtDemand = getCurrentPTDemand(installmentFirstHalf, vacancyRemission.getBasicProperty().getActiveProperty().getPtDemandSet()); if (isApprovedInFirstHalf(vacancyRemission, installmentFirstHalf)) { halfYearTax = currentDemand.get(CURR_FIRSTHALF_DMD_STR); newTax = getNewTax(currPtDemand, newTax, installmentFirstHalf); } else { newTax = getNewTax(currPtDemand, newTax, installmentSecondHalf); } reportParams.put("financialYear", financialYear.getFinYearRange()); reportParams.put("halfYearTax", halfYearTax.toString()); reportParams.put("newTax", newTax.toString()); reportInput = new ReportRequest(VR_SPECIALNOTICE_TEMPLATE, vacancyRemission, reportParams); } if (reportInput != null) { reportInput.setPrintDialogOnOpenReport(true); reportInput.setReportFormat(ReportFormat.PDF); } return reportInput; } private BigDecimal getNewTax(Ptdemand currPtDemand, BigDecimal newTax, final Installment installmentHalf) { if (currPtDemand != null) for (final EgDemandDetails dmdDet : currPtDemand.getEgDemandDetails()) if (dmdDet.getInstallmentStartDate().equals(installmentHalf.getFromDate()) && !DEMANDRSN_CODE_PENALTY_FINES .equals(dmdDet.getEgDemandReason().getEgDemandReasonMaster().getCode())) { newTax = newTax.add( dmdDet.getAmount().divide(new BigDecimal("2")).setScale(0, BigDecimal.ROUND_HALF_UP)); } return newTax; } private boolean isApprovedInFirstHalf(VacancyRemission vacancyRemission, final Installment installmentFirstHalf) { return DateUtils.between(vacancyRemission.getVacancyRemissionApproval().get(0).getApprovalDate(), installmentFirstHalf.getFromDate(), installmentFirstHalf.getToDate()); } public String getLoggedInUserDesignation(final Long posId, final User user) { final List<Assignment> loggedInUserAssign = assignmentService.getAssignmentByPositionAndUserAsOnDate(posId, user.getId(), new Date()); return !loggedInUserAssign.isEmpty() ? loggedInUserAssign.get(0).getDesignation().getName() : null; } /** * API to get workflow initiator assignment in Property Tax. * * @return assignment */ public Assignment getWorkflowInitiatorAssignment(final Long userId, final List<String> designations) { Assignment wfInitiatorAssignment = null; if (userId != null) { final List<Assignment> assignments = assignmentService.getAllActiveEmployeeAssignmentsByEmpId(userId); for (final Assignment assignment : assignments) if (designations.contains(assignment.getDesignation().getName()) && assignment.getEmployee().isActive()) { wfInitiatorAssignment = assignment; break; } } return wfInitiatorAssignment; } public Assignment getWorkflowInitiator(final StateAware<Position> property) { Assignment wfInitiator; List<Assignment> assignment; if (isEmployee(property.getCreatedBy())) { if (isStateNotNull(property)) wfInitiator = getWfInitiatorIfStateNotNull(property); else wfInitiator = assignmentService.getPrimaryAssignmentForUser(property.getCreatedBy().getId()); } else if (property.getState().getInitiatorPosition() != null) { assignment = assignmentService .getAssignmentsForPosition(property.getState().getInitiatorPosition().getId(), new Date()); wfInitiator = getActiveAssignment(assignment); if (wfInitiator == null && !property.getStateHistory().isEmpty()) wfInitiator = assignmentService.getPrimaryAssignmentForPositon( property.getStateHistory().get(0).getOwnerPosition().getId()); } else wfInitiator = assignmentService .getPrimaryAssignmentForPositon(property.getState().getOwnerPosition().getId()); return wfInitiator; } private Assignment getWfInitiatorIfStateNotNull(final StateAware<Position> property) { List<Assignment> assignment; Assignment wfInitiator = null; final Assignment assgmnt = propertyTaxCommonUtils.getUserAssignmentByPassingPositionAndUser( property.getCreatedBy(), property.getState().getInitiatorPosition()); if (assgmnt != null && assgmnt.getEmployee().isActive()) wfInitiator = assgmnt; if (wfInitiator == null) { assignment = assignmentService .getAssignmentsForPosition(property.getState().getInitiatorPosition().getId(), new Date()); wfInitiator = getActiveAssignment(assignment); } return wfInitiator; } private boolean isStateNotNull(final StateAware property) { return property.getState() != null && property.getState().getInitiatorPosition() != null; } private Assignment getActiveAssignment(final List<Assignment> assignment) { Assignment wfInitiator = null; for (final Assignment assign : assignment) if (assign.getEmployee().isActive()) { wfInitiator = assign; break; } return wfInitiator; } public Boolean isEmployee(final User user) { for (final Role role : user.getRoles()) for (final AppConfigValues appconfig : getThirdPartyUserRoles()) if (role != null && role.getName().equals(appconfig.getValue())) return false; return true; } public List<AppConfigValues> getThirdPartyUserRoles() { final List<AppConfigValues> appConfigValueList = appConfigValuesService .getConfigValuesByModuleAndKey(PTMODULENAME, PROPERTYTAX_ROLEFORNONEMPLOYEE); return !appConfigValueList.isEmpty() ? appConfigValueList : null; } @Transactional public void closeVacancyRemission(final VacancyRemission vacancyRemission) { final User user = securityUtils.getCurrentUser(); vacancyRemission.transition().end().withSenderName(user.getName()).withDateInfo(new Date()) .withNextAction(null).withOwner(vacancyRemission.getCurrentState().getOwnerPosition()); if (!VR_STATUS_APPROVED.equals(vacancyRemission.getStatus())) { vacancyRemission.setStatus(VR_STATUS_REJECTION_ACK_GENERATED); vacancyRemission.getBasicProperty().setUnderWorkflow(false); } if (Source.CITIZENPORTAL.toString().equalsIgnoreCase(vacancyRemission.getSource()) && propertyService.getPortalInbox(vacancyRemission.getApplicationNumber()) != null) { propertyService.updatePortal(vacancyRemission, APPLICATION_TYPE_VACANCY_REMISSION); } } private String getLoggedInUserDesignation(final VacancyRemission vacancyRemission, final User user) { String loggedInUserDesignation = ""; List<Assignment> loggedInUserAssign; if (vacancyRemission.getState() != null) { loggedInUserAssign = assignmentService.getAssignmentByPositionAndUserAsOnDate( vacancyRemission.getCurrentState().getOwnerPosition().getId(), user.getId(), new Date()); loggedInUserDesignation = !loggedInUserAssign.isEmpty() ? loggedInUserAssign.get(0).getDesignation().getName() : ""; } if (JUNIOR_ASSISTANT.equals(loggedInUserDesignation) || SENIOR_ASSISTANT.equals(loggedInUserDesignation)) loggedInUserDesignation = ""; return loggedInUserDesignation; } private String getWorkflowNextAction(final String designation) { String nextAction; if (COMMISSIONER_DESGN.equalsIgnoreCase(designation)) nextAction = VR_STATUS_COMMISSIONER_FORWARD_PENDING; else nextAction = new StringBuilder().append(designation).append(" ") .append(VR_STATUS_COMMISSIONER_FORWARD_PENDING).toString(); return nextAction; } private String getApprovalAsNextAction(final String designation) { String nextAction; if (designation.equalsIgnoreCase(COMMISSIONER_DESGN)) nextAction = WF_STATE_COMMISSIONER_APPROVAL_PENDING; else nextAction = new StringBuilder().append(designation).append(" ") .append(WF_STATE_COMMISSIONER_APPROVAL_PENDING).toString(); return nextAction; } private Assignment getInitiatorOnWFAction(final VacancyRemissionApproval vacancyRemissionApproval, final String wfAction) { Assignment wfInitiator = null; if (vacancyRemissionApproval.getId() != null && WFLOW_ACTION_STEP_REJECT.equalsIgnoreCase(wfAction)) wfInitiator = getWorkflowInitiatorAssignment(vacancyRemissionApproval.getState().getCreatedBy().getId(), Arrays.asList(PropertyTaxConstants.REVENUE_INSPECTOR_DESGN)); if (vacancyRemissionApproval.getId() != null && WFLOW_ACTION_STEP_NOTICE_GENERATE.equalsIgnoreCase(wfAction)) wfInitiator = assignmentService.getAssignmentsForPosition( vacancyRemissionApproval.getVacancyRemission().getState().getInitiatorPosition().getId(), new Date()).get(0); return wfInitiator; } public BigDecimal getWaterTaxDues(final String assessmentNo, final HttpServletRequest request) { return propertyService.getWaterTaxDues(assessmentNo, request) .get(PropertyTaxConstants.WATER_TAX_DUES) == null ? BigDecimal.ZERO : new BigDecimal(Double.valueOf((Double) propertyService .getWaterTaxDues(assessmentNo, request).get(PropertyTaxConstants.WATER_TAX_DUES))); } public Boolean isUnderWtmsWF(final String assessmentNo, final HttpServletRequest request) { return propertyService.getWaterTaxDues(assessmentNo, request) .get(PropertyTaxConstants.UNDER_WTMS_WF) == null ? FALSE : Boolean.valueOf((Boolean) propertyService.getWaterTaxDues(assessmentNo, request) .get(PropertyTaxConstants.UNDER_WTMS_WF)); } }