/* * eGov suite of products aim to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) <2015> 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. * * 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.Installment; 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.User; import org.egov.infra.config.core.ApplicationThreadLocals; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.messaging.MessagingService; import org.egov.infra.security.utils.SecurityUtils; import org.egov.infra.utils.ApplicationNumberGenerator; import org.egov.infra.utils.DateUtils; 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.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.property.BasicProperty; import org.egov.ptis.domain.entity.property.Property; 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 java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static org.egov.ptis.constants.PropertyTaxConstants.*; @Service @Transactional(readOnly = true) public class VacancyRemissionService { 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 MessagingService messagingService; @Autowired private PropertyTaxCommonUtils propertyTaxCommonUtils; public VacancyRemission getApprovedVacancyRemissionForProperty(final String upicNo) { return vacancyRemissionRepository.findByUpicNo(upicNo); } public VacancyRemission getLatestRejectAckGeneratedVacancyRemissionForProperty(final String upicNo) { VacancyRemission vacancyRemission = null; List<VacancyRemission> rejectedRemissionList = vacancyRemissionRepository .findAllRejectionAckGeneratedForUpicNo(upicNo); if (!rejectedRemissionList.isEmpty()) { vacancyRemission = rejectedRemissionList.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); } @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 = ""; if (!propertyByEmployee) { currentState = "Created"; final Assignment assignment = propertyService.getUserPositionByZone(vacancyRemission.getBasicProperty(), false); if (null != assignment) approvalPosition = assignment.getPosition().getId(); } else currentState = null; if (vacancyRemission.getId() != null && (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT) || workFlowAction .equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE))) wfInitiator = getWorkflowInitiator(vacancyRemission); else 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(true).end().withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withDateInfo(currentDate.toDate()); vacancyRemission.getBasicProperty().setUnderWorkflow(false); } } else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT)) { final String stateValue = WF_STATE_REJECTED; vacancyRemission.setStatus(VR_STATUS_REJECTED); vacancyRemission.transition(true).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 = null; if (null == vacancyRemission.getState()) { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemission.getStateType(), null, null, additionalRule, currentState, null); vacancyRemission.transition().start().withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()).withDateInfo(new Date()) .withOwner(pos).withNextAction(wfmatrix.getNextAction()).withNatureOfTask(NATURE_VACANCY_REMISSION) .withInitiator(wfInitiator != null ? wfInitiator.getPosition() : null); vacancyRemission.getBasicProperty().setUnderWorkflow(true); //to be enabled once acknowledgement feature is developed //buildSMS(vacancyRemission, workFlowAction); } else { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemission.getStateType(), null, null, additionalRule, vacancyRemission.getCurrentState().getValue(), null); if (wfmatrix != null) if (wfmatrix.getNextAction().equalsIgnoreCase("END")){ vacancyRemission.transition(true).end() .withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withDateInfo(currentDate.toDate()); vacancyRemission.getBasicProperty().setUnderWorkflow(false); } else vacancyRemission.transition(false).withSenderName(user.getUsername() + "::" + user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(currentDate.toDate()).withOwner(pos) .withNextAction(wfmatrix.getNextAction()); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)){ buildSMS(vacancyRemission, workFlowAction); } } } 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(VacancyRemission vacancyRemission, Installment demandInstallment, Installment effectiveInstallment){ Set<Ptdemand> activePropPtDemandSet = vacancyRemission.getBasicProperty().getActiveProperty().getPtDemandSet(); Ptdemand currPtDemand = null; for(Ptdemand ptDemand : activePropPtDemandSet){ if (ptDemand.getIsHistory().equalsIgnoreCase("N")) if (ptDemand.getEgInstallmentMaster().equals(demandInstallment)) { currPtDemand = ptDemand; break; } } for(EgDemandDetails dmdDet : currPtDemand.getEgDemandDetails()){ if(dmdDet.getInstallmentStartDate().equals(effectiveInstallment.getFromDate())){ dmdDet.setAmount((dmdDet.getAmount().divide(new BigDecimal("2"))).setScale(0, BigDecimal.ROUND_HALF_UP)); } } ptDemandDAO.update(currPtDemand); } 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 Map<String, Map<String,BigDecimal>> demandCollMap = propertyTaxUtil.prepareDemandDetForView(property, propertyTaxCommonUtils.getCurrentInstallment()); Map<String, BigDecimal> currentTaxDetails = propertyService.getCurrentTaxDetails(demandCollMap, new Date()); model.addAttribute("propertyTax", currentTaxDetails.get(DEMANDRSN_STR_GENERAL_TAX)); model.addAttribute("eduCess", (currentTaxDetails.get(DEMANDRSN_STR_EDUCATIONAL_CESS) == null ? BigDecimal.ZERO : currentTaxDetails.get(DEMANDRSN_STR_EDUCATIONAL_CESS))); 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 (Exception e) { LOG.error("Exception in addModelAttributes : ", e); throw new ApplicationRuntimeException("Exception in addModelAttributes : " + e); } Boolean propertyByEmployee = Boolean.TRUE; propertyByEmployee = checkIfEmployee(getLoggedInUser()); model.addAttribute("propertyByEmployee", propertyByEmployee); } } public Boolean checkIfEmployee(final User user) { return propertyService.isEmployee(user); } public String getInitiatorName(final VacancyRemission vacancyRemission) { String initiatorName = ""; Assignment assignment = new Assignment(); if (checkIfEmployee(vacancyRemission.getCreatedBy())) assignment = assignmentService.getPrimaryAssignmentForUser(vacancyRemission.getCreatedBy().getId()); else assignment = assignmentService .getPrimaryAssignmentForPositon( vacancyRemission.getStateHistory().get(0).getOwnerPosition().getId()); initiatorName=assignment.getEmployee().getName().concat("~").concat(assignment.getPosition().getName()); return initiatorName; } protected Assignment getWorkflowInitiator(final VacancyRemission vacancyRemission) { Assignment wfInitiator = null; 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()) wfInitiator = assignmentService.getPrimaryAssignmentForPositon( vacancyRemission.getStateHistory().get(0).getOwnerPosition().getId()); else { wfInitiator = assignmentService .getPrimaryAssignmentForPositon(vacancyRemission.getState().getOwnerPosition().getId()); } return wfInitiator; } @Transactional public void saveRemissionDetails(final VacancyRemission vacancyRemission) { vacancyRemissionRepository.save(vacancyRemission); } public List<VacancyRemissionDetails> getMonthlyDetailsHistory(final VacancyRemission vacancyRemission) { List<VacancyRemissionDetails> historyList = new ArrayList<VacancyRemissionDetails>(); 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(); final Assignment userAssignment = assignmentService.getPrimaryAssignmentForUser(user.getId()); final String designationList = propertyTaxCommonUtils.getAllDesignationsForUser(user.getId()); Position pos = null; Assignment wfInitiator = null; if (vacancyRemissionApproval.getId() != null && (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT) || workFlowAction .equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE))) if (StringUtils.containsIgnoreCase(designationList, REVENUE_INSPECTOR_DESGN)) wfInitiator = assignmentService.getPrimaryAssignmentForUser(vacancyRemissionApproval .getVacancyRemission().getCreatedBy().getId()); else wfInitiator = assignmentService.getPrimaryAssignmentForUser(vacancyRemissionApproval.getCreatedBy() .getId()); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_NOTICE_GENERATE)) { if (wfInitiator.equals(userAssignment)) { vacancyRemissionApproval.setStatus(VR_STATUS_REJECTION_ACK_GENERATED); vacancyRemissionApproval.transition().end().withSenderName(user.getName()).withComments(approvalComent) .withDateInfo(currentDate.toDate()); } } else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_REJECT)) { String stateValue = ""; String nextAction = ""; if (StringUtils.containsIgnoreCase(designationList, REVENUE_OFFICER_DESGN) || StringUtils.containsIgnoreCase(designationList, COMMISSIONER_DESGN)) { stateValue = WF_STATE_REJECTED; nextAction = WF_STATE_REVENUE_INSPECTOR_APPROVAL_PENDING; } else { stateValue = WF_STATE_REVENUE_INSPECTOR_REJECTED; nextAction = WF_STATE_ASSISTANT_APPROVAL_PENDING; } vacancyRemissionApproval.setStatus(VR_STATUS_REJECTED); vacancyRemissionApproval.transition().withSenderName(user.getName()).withComments(approvalComent) .withStateValue(stateValue).withDateInfo(currentDate.toDate()).withOwner(wfInitiator.getPosition()) .withNextAction(nextAction); } else { if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_FORWARD)) vacancyRemissionApproval.setStatus(VR_STATUS_WORKFLOW); else if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)) vacancyRemissionApproval.setStatus(VR_STATUS_APPROVED); if (null != approvalPosition && approvalPosition != -1 && !approvalPosition.equals(Long.valueOf(0))) pos = positionMasterService.getPositionById(approvalPosition); else if (WFLOW_ACTION_STEP_APPROVE.equalsIgnoreCase(workFlowAction)) pos = assignmentService.getPrimaryAssignmentForUser( vacancyRemissionApproval.getVacancyRemission().getCreatedBy().getId()).getPosition(); WorkFlowMatrix wfmatrix = null; if (null == vacancyRemissionApproval.getState()) { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemissionApproval.getStateType(), null, null, additionalRule, null, null); vacancyRemissionApproval.transition().start().withSenderName(user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()).withDateInfo(new Date()) .withOwner(pos).withNextAction(wfmatrix.getNextAction()).withNatureOfTask(NATURE_VACANCY_REMISSION); } else { wfmatrix = vacancyRemissionWorkflowService.getWfMatrix(vacancyRemissionApproval.getStateType(), null, null, additionalRule, vacancyRemissionApproval.getCurrentState().getValue(), null); if (wfmatrix != null){ if (wfmatrix.getNextAction().equalsIgnoreCase("END")) vacancyRemissionApproval.transition().end().withSenderName(user.getName()) .withComments(approvalComent).withDateInfo(currentDate.toDate()); else vacancyRemissionApproval.transition(false).withSenderName(user.getName()) .withComments(approvalComent).withStateValue(wfmatrix.getNextState()) .withDateInfo(currentDate.toDate()).withOwner(pos) .withNextAction(wfmatrix.getNextAction()); if (workFlowAction.equalsIgnoreCase(WFLOW_ACTION_STEP_APPROVE)){ Map<String, Installment> installmentMap = propertyTaxUtil.getInstallmentsForCurrYear(new Date()); Installment installmentFirstHalf = installmentMap.get(PropertyTaxConstants.CURRENTYEAR_FIRST_HALF); Installment installmentSecondHalf = installmentMap.get(PropertyTaxConstants.CURRENTYEAR_SECOND_HALF); /* * If VR is done in 1st half, provide 50% rebate on taxes of the 2nd half */ if(DateUtils.between(vacancyRemissionApproval.getVacancyRemission().getVacancyToDate(), installmentFirstHalf.getFromDate(), installmentFirstHalf.getToDate())) updateDemandDetailsWithRebate(vacancyRemissionApproval.getVacancyRemission(), installmentFirstHalf, installmentSecondHalf); } } } } if (LOG.isDebugEnabled()) LOG.debug(" WorkFlow Transition Completed ..."); vacancyRemissionApprovalRepository.save(vacancyRemissionApproval); } 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(VacancyRemission vacancyRemission, String workFlowAction) { for (PropertyOwnerInfo ownerInfo : vacancyRemission.getBasicProperty().getPropertyOwnerInfo()) { if (StringUtils.isNotBlank(ownerInfo.getOwner().getMobileNumber())) { buildSms(vacancyRemission, ownerInfo.getOwner(), workFlowAction); } } } private void buildSms(VacancyRemission vacancyRemission, User user, 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)) { messagingService.sendSMS(mobileNumber, smsMsg); } } }