/* * 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.egf.web.actions.budget; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.log4j.Logger; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import org.apache.struts2.interceptor.validation.SkipValidation; import org.egov.commons.CFinancialYear; import org.egov.commons.CFunction; import org.egov.commons.dao.EgwStatusHibernateDAO; import org.egov.commons.service.CFinancialYearService; import org.egov.commons.service.FunctionService; import org.egov.egf.model.BudgetAmountView; import org.egov.eis.entity.Assignment; import org.egov.eis.service.AssignmentService; import org.egov.eis.service.EmployeeService; import org.egov.infra.config.core.ApplicationThreadLocals; import org.egov.infra.validation.exception.ValidationError; import org.egov.infra.validation.exception.ValidationException; import org.egov.infra.web.struts.annotation.ValidationErrorPage; import org.egov.infra.workflow.entity.StateAware; import org.egov.infstr.services.PersistenceService; import org.egov.model.budget.Budget; import org.egov.model.budget.BudgetDetail; import org.egov.model.budget.BudgetGroup; import org.egov.model.voucher.WorkflowBean; import org.egov.utils.Constants; import org.egov.utils.FinancialConstants; import org.hibernate.SQLQuery; import org.hibernate.transform.Transformers; import org.hibernate.type.LongType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @ParentPackage("egov") @Results({ @Result(name = BudgetProposalDetailAction.NEWRE, location = "budgetProposalDetail-new-re.jsp"), @Result(name = BudgetProposalDetailAction.NEWDETAIL, location = "budgetProposalDetail-newDetail-re.jsp"), @Result(name = BudgetProposalDetailAction.BUDGETS, location = "budgetProposalDetail-budgets.jsp"), @Result(name = BudgetProposalDetailAction.FUNCTION, location = "budgetProposalDetail-functions.jsp"), @Result(name = BudgetProposalDetailAction.BUDGETGROUP, location = "budgetProposalDetail-budgetGroup.jsp"), @Result(name = "AJAX_RESULT", type = "stream", location = "returnStream", params = { "contentType", "text/plain" }) }) public class BudgetProposalDetailAction extends BaseBudgetDetailAction { @Autowired @Qualifier("persistenceService") private PersistenceService persistenceService; @Autowired private AssignmentService assignmentService; @Autowired private EgwStatusHibernateDAO egwStatusHibernateDAO; private static final long serialVersionUID = 1L; @Autowired private FunctionService functionService; @Autowired private EmployeeService employeeService; @Autowired private CFinancialYearService financialYearService; @PersistenceContext private EntityManager entityManager; public static final String NEWDETAIL = "newDetail-re"; public static final String NEWRE = "new-re"; public static final String BUDGETS = "budgets"; public static final String FUNCTION = "functions"; public static final String BUDGETGROUP = "budgetGroup"; private static final String ACTIONNAME = "actionName"; private static final String NAME = "name"; private Budget topBudget; private Map<Long, BigDecimal> beNextYearAmounts = new HashMap<Long, BigDecimal>(); private static Logger LOGGER = Logger.getLogger(BudgetProposalDetailAction.class); private final String streamResult = ""; private Long function; private Long budgetGroups; public List<CFunction> functionList = Collections.EMPTY_LIST; public List<BudgetGroup> budgetGroupList = Collections.EMPTY_LIST; public void setBudgetGroupList(final List budgetGroupList) { this.budgetGroupList = budgetGroupList; } @Override public StateAware getModel() { return budgetDetail; } /** * @return the streamResult */ public InputStream getReturnStream() { final ByteArrayInputStream is = new ByteArrayInputStream(streamResult.getBytes()); return is; } @Override protected void saveAndStartWorkFlow(final BudgetDetail detail, final WorkflowBean workflowBean) { try { if ((budgetDocumentNumber != null) && (budgetDetail.getBudget() != null)) { final Budget b = budgetService.findById(budgetDetail.getBudget().getId(), false); b.setDocumentNumber(budgetDocumentNumber); budgetService.persist(b); persistenceService.getSession().flush(); } budgetDetailService.createBudgetDetail(detail, getPosition(), getPersistenceService()); populateSavedbudgetDetailListForDetail(detail); headerDisabled = true; } catch (final ValidationException e) { handleDuplicateBudgetDetailError(e); populateSavedbudgetDetailListForDetail(detail); } } protected void handleDuplicateBudgetDetailError(final ValidationException e) { for (final ValidationError error : e.getErrors()) if ("budgetDetail.duplicate".equals(error.getKey())) { headerDisabled = true; break; } throw e; } @Override public void populateSavedbudgetDetailListFor(final Budget budget) { if ((budget != null) && (budget.getId() != null)) savedbudgetDetailList = budgetDetailService.findAllBy( "from BudgetDetail where budget.id=? order by function.name,budgetGroup.name", budget.getId()); } @Override public void populateSavedbudgetDetailListForDetail(final BudgetDetail bd) { if (bd != null) { // find all RE for the functin final List<BudgetDetail> findAllBy = budgetDetailService.findAllBy( "from BudgetDetail where budget=? and function.id=? order by function.name,budgetGroup.name", bd.getBudget(), bd.getFunction().getId()); savedbudgetDetailList = findAllBy; // find all next year be for the function savedbudgetDetailList.addAll(budgetDetailService.findAllBy( "from BudgetDetail where budget=(select bd from Budget bd where bd.referenceBudget=?) and function.id=? order by function.name,budgetGroup.name", bd.getBudget(), bd.getFunction().getId())); } } public String ajaxLoadBudgetDetailList() { final Long id = (Long) request.get("id"); if (!Long.valueOf(0).equals(id)) { savedbudgetDetailList = budgetDetailService.findAllBy("from BudgetDetail where budget.id=?", id); final Budget budget = budgetService.findById(id, false); re = budgetService.hasReForYear(budget.getFinancialYear().getId()); budgetDetail.setBudget(budget); setReferenceBudget(budgetService.getReferenceBudgetFor(budget)); budgetDocumentNumber = budget.getDocumentNumber(); } populateBeNextYearAmounts(); populateFinancialYear(); return Constants.SAVED_DATA; } @ValidationErrorPage(value = NEWRE) @Action(value = "/budget/budgetProposalDetail-loadBudgetDetailList") public String loadBudgetDetailList() { if (addNewDetails) return addNewDetails(); final Long id = budgetDetail.getBudget().getId(); showRe = true; getDetailsFilterdBy(); final Budget budget = budgetService.findById(id, false); re = budgetService.hasReForYear(budget.getFinancialYear().getId()); budgetDetail.setBudget(budget); setReferenceBudget(budgetService.getReferenceBudgetFor(budget)); budgetDocumentNumber = budget.getDocumentNumber(); budgetAmountView = new ArrayList<BudgetAmountView>(savedbudgetDetailList.size()); for (int i = 0; i < savedbudgetDetailList.size(); i++) budgetAmountView.add(new BudgetAmountView()); budgetDetailList = savedbudgetDetailList; populateBeNextYearAmountsAndBEAmounts(); populateFinancialYear(); loadAjaxedFunctionAndBudgetGroup(); populateBudgetList(); showDetails = true; return NEWRE; } @SkipValidation @Action(value = "/budget/budgetProposalDetail-loadNewBudgetDetailList") public String loadNewBudgetDetailList() { LOGGER.info("Initiating load budgets ....."); if (addNewDetails) return addNewDetails(); final Long id = budgetDetail.getBudget().getId(); showRe = true; // getDetailsFilterdBy(); final Budget budget = budgetService.findById(id, false); re = budgetService.hasReForYear(budget.getFinancialYear().getId()); budgetDetail.setBudget(budget); setReferenceBudget(budgetService.getReferenceBudgetFor(budget)); budgetDocumentNumber = budget.getDocumentNumber(); budgetAmountView = new ArrayList<BudgetAmountView>(savedbudgetDetailList.size()); for (int i = 0; i < savedbudgetDetailList.size(); i++) budgetAmountView.add(new BudgetAmountView()); budgetDetailList = savedbudgetDetailList; populateBeNextYearAmountsAndBEAmounts(); populateFinancialYear(); loadAjaxedFunctionAndBudgetGroup(); showDetails = true; return NEWDETAIL; } public String addNewDetails() { final Long id = budgetDetail.getBudget().getId(); addNewDetails = true; showRe = true; savedbudgetDetailList = new ArrayList<BudgetDetail>(); final Budget budget = budgetService.findById(id, false); re = budgetService.hasReForYear(budget.getFinancialYear().getId()); budgetDetail.setBudget(budget); setReferenceBudget(budgetService.getReferenceBudgetFor(budget)); budgetDocumentNumber = budget.getDocumentNumber(); populateFinancialYear(); loadAjaxedFunctionAndBudgetGroup(); return NEWDETAIL; } @SuppressWarnings("unchecked") private void loadAjaxedFunctionAndBudgetGroup() { ajaxLoadFunctions(); ajaxLoadBudgetGroups(); } @Action(value = "/budget/budgetProposalDetail-ajaxLoadBudgets") public String ajaxLoadBudgets() { final String bere = parameters.get("bere")[0]; loadBudgets(bere); return BUDGETS; } @Action(value = "/budget/budgetProposalDetail-ajaxLoadFunctions") public String ajaxLoadFunctions() { final String functionLists = "functionList"; if ((getBudgetDetail() != null) && (getBudgetDetail().getBudget() != null) && (getBudgetDetail().getExecutingDepartment() != null)) { final Budget budget = budgetService.find("from Budget where id=?", getBudgetDetail().getBudget().getId()); final String budgetName = budget.getName(); final Integer deptId = getBudgetDetail().getExecutingDepartment().getId().intValue(); String accountType; accountType = budgetDetailHelper.accountTypeForFunctionDeptMap(budgetName); final String sqlStr = "select distinct (f.name) as name,f.id as id from eg_dept_functionmap m,function f where departmentid=:deptId" + " and budgetaccount_Type=:accountType and f.id= m.functionid order by f.name"; final SQLQuery sqlQuery = persistenceService.getSession().createSQLQuery(sqlStr); sqlQuery.setInteger("deptId", deptId).setString("accountType", accountType); sqlQuery.addScalar(NAME).addScalar("id", LongType.INSTANCE) .setResultTransformer(Transformers.aliasToBean(CFunction.class)); if (!sqlQuery.list().isEmpty()) functionList = sqlQuery.list(); else functionList = employeeService.getAllFunctions(); if (functionList.isEmpty()) dropdownData.put(functionLists, functionService.findAll()); else dropdownData.put(functionLists, functionList); } return FUNCTION; } @Action(value = "/budget/budgetProposalDetail-ajaxLoadBudgetGroups") public String ajaxLoadBudgetGroups() { final Long id = (Long) request.get("id"); final String sqlStr = "select distinct (bg.name) as name ,bg.id as id from egf_budgetgroup bg,egf_budgetdetail bd where bg.id=bd.budgetgroup and bd.budget=" + id + " order by bg.name"; final SQLQuery sqlQuery = persistenceService.getSession().createSQLQuery(sqlStr); sqlQuery.addScalar(NAME).addScalar("id", LongType.INSTANCE) .setResultTransformer(Transformers.aliasToBean(BudgetGroup.class)); budgetGroupList = sqlQuery.list(); return BUDGETGROUP; } public String saveAndNew() { return create(); } public String saveAndNewRe() { return createRe(); } @Override public void prepare() { super.prepare(); populateSavedbudgetDetailListFor(budgetDetail.getBudget()); if (parameters.containsKey("re")) dropdownData.put("budgetList", Collections.EMPTY_LIST); loadAjaxedFunctionAndBudgetGroup(); } @Override public boolean isShowMessage() { return super.isShowMessage(); } public String getActionMessage() { if ((getActionMessages() != null) && (getActionMessages().iterator() != null) && (getActionMessages().iterator().next() != null)) return getActionMessages().iterator().next().toString(); else return ""; } private void populateBeNextYearAmounts() { if ((savedbudgetDetailList == null) || (savedbudgetDetailList.size() == 0)) return; final Budget referenceBudgetFor = budgetService.getReferenceBudgetFor(savedbudgetDetailList.get(0).getBudget()); if (referenceBudgetFor != null) { final List<BudgetDetail> result = budgetDetailService.findAllBy("from BudgetDetail where budget.id=?", referenceBudgetFor.getId()); for (final BudgetDetail budgetDetail : savedbudgetDetailList) for (final BudgetDetail row : result) if (compareDetails(row, budgetDetail)) beNextYearAmounts.put(budgetDetail.getId(), row.getOriginalAmount().setScale(2)); } } private void populateBeNextYearAmountsAndBEAmounts() { if ((savedbudgetDetailList == null) || (savedbudgetDetailList.size() == 0)) return; beAmounts = new ArrayList<BigDecimal>(savedbudgetDetailList.size()); final Budget referenceBudgetFor = budgetService.getReferenceBudgetFor(savedbudgetDetailList.get(0).getBudget()); if (referenceBudgetFor != null) { final List<BudgetDetail> result = budgetDetailService.findAllBy("from BudgetDetail where budget.id=?", referenceBudgetFor.getId()); for (final BudgetDetail budgetDetail : savedbudgetDetailList) for (final BudgetDetail row : result) if (compareDetails(row, budgetDetail)) { beNextYearAmounts.put(budgetDetail.getId(), row.getOriginalAmount().setScale(2)); beAmounts.add(row.getOriginalAmount()); } } } @Override protected void saveAndStartWorkFlowForRe(final BudgetDetail detail, final int index, final CFinancialYear finYear, final Budget refBudget, final WorkflowBean workflowBean) { try { if ((budgetDocumentNumber != null) && (budgetDetail.getBudget() != null)) { final Budget b = budgetService.findById(budgetDetail.getBudget().getId(), false); b.setDocumentNumber(budgetDocumentNumber); budgetService.persist(b); persistenceService.getSession().flush(); } detail.getBudget().setFinancialYear(finYear); /* * if(!chequeUnique(detail)){ throw new ValidationException( Arrays.asList(new * ValidationError("budgetDetail.duplicate", "budgetdetail.exists"))); } */ BudgetDetail reCurrentYear = budgetDetailService.createBudgetDetail(detail, null, getPersistenceService()); reCurrentYear .setUniqueNo(reCurrentYear.getFund().getId() + "-" + reCurrentYear.getExecutingDepartment().getId() + "-" + reCurrentYear.getFunction().getId() + "-" + reCurrentYear.getBudgetGroup().getId()); budgetDetailService.applyAuditing(reCurrentYear); reCurrentYear = budgetDetailService.transitionWorkFlow(reCurrentYear, workflowBean); budgetDetailService.applyAuditing(reCurrentYear.getState()); budgetDetailService.persist(reCurrentYear); headerDisabled = true; BudgetDetail beNextYear = new BudgetDetail(); if (addNewDetails) beNextYear.transition(true).withStateValue("END").withOwner(getPosition()).withComments(""); beNextYear.copyFrom(detail); beNextYear.setBudget(refBudget); beNextYear.setOriginalAmount(beAmounts.get(index)); beNextYear.setDocumentNumber(detail.getDocumentNumber()); beNextYear.setAnticipatoryAmount(reCurrentYear.getAnticipatoryAmount()); beNextYear = budgetDetailService.createBudgetDetail(beNextYear, null, getPersistenceService()); beNextYear.setUniqueNo(beNextYear.getFund().getId() + "-" + beNextYear.getExecutingDepartment().getId() + "-" + beNextYear.getFunction().getId() + "-" + beNextYear.getBudgetGroup().getId()); budgetDetailService.applyAuditing(beNextYear); beNextYear.setStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(FinancialConstants.BUDGETDETAIL, FinancialConstants.BUDGETDETAIL_CREATED_STATUS)); budgetDetailService.persist(beNextYear); } catch (final ValidationException e) { LOGGER.error(e.getMessage(), e); loadAjaxedFunctionAndBudgetGroup(); populateBeNextYearAmounts(); handleDuplicateBudgetDetailError(e); populateSavedbudgetDetailListFor(budgetDetail.getBudget()); throw e; } } public Assignment getWorkflowInitiator(final BudgetDetail budgetDetail) { final Assignment wfInitiator = assignmentService .findByEmployeeAndGivenDate(budgetDetail.getCreatedBy().getId(), new Date()).get(0); return wfInitiator; } @Override public List<String> getValidActions() { List<String> validActions = Collections.emptyList(); if ((budgetDetail.getId() == null) || (budgetDetail.getId() == 0) || (budgetDetail.getCurrentState() == null)) validActions = Arrays.asList(FinancialConstants.BUTTONSAVE, FinancialConstants.BUTTONFORWARD); else if (budgetDetail.getCurrentState() != null) validActions = customizedWorkFlowService.getNextValidActions(budgetDetail.getStateType(), getWorkFlowDepartment(), getAmountRule(), getAdditionalRule(), budgetDetail.getCurrentState().getValue(), getPendingActions(), budgetDetail.getCreatedDate()); else if ((budgetDetail.getId() == null) || (budgetDetail.getId() == 0) || budgetDetail.getCurrentState().getValue().endsWith("NEW")) validActions = Arrays.asList(FinancialConstants.BUTTONFORWARD); else if (budgetDetail.getCurrentState() != null) validActions = customizedWorkFlowService.getNextValidActions(budgetDetail.getStateType(), getWorkFlowDepartment(), getAmountRule(), getAdditionalRule(), budgetDetail.getCurrentState().getValue(), getPendingActions(), budgetDetail.getCreatedDate()); return validActions; } @Override public void approve() { if (!savedbudgetDetailList.isEmpty()) { topBudget = savedbudgetDetailList.get(0).getBudget(); setTopBudget(topBudget); } Integer userId = null; if ((parameters.get(ACTIONNAME)[0] != null) && parameters.get(ACTIONNAME)[0].contains("reject")) userId = Integer.valueOf(parameters.get("approverUserId")[0]); else if ((null != parameters.get("approverUserId")) && (Integer.valueOf(parameters.get("approverUserId")[0]) != -1)) userId = Integer.valueOf(parameters.get("approverUserId")[0]); else userId = ApplicationThreadLocals.getUserId().intValue(); for (final BudgetDetail detail : savedbudgetDetailList) { if (new String("forward").equals(parameters.get(ACTIONNAME)[0])) detail.transition(true).withStateValue("Forwarded by " + getPosition().getName()) .withOwner(getPositionByUserId(userId)).withComments(detail.getComment()); budgetDetailService.persist(detail); } // We Dont need to start budget workflow here, Its starts frm HOD level. // forwardBudget(budgetComment, userId); //for RE if (topBudget != null) setTopBudget(budgetService.getReferenceBudgetFor(topBudget)); // forwardBudget(budgetComment, userId); //for BE if (parameters.get(ACTIONNAME)[0].contains("approv")) { if (topBudget.getState().getValue().equals("END")) addActionMessage(getMessage("budgetdetail.approved.end")); else addActionMessage(getMessage("budgetdetail.approved") + budgetService.getEmployeeNameAndDesignationForPosition(getPositionByUserId(userId))); } else addActionMessage(getMessage("budgetdetail.approved") + budgetService.getEmployeeNameAndDesignationForPosition(getPositionByUserId(userId))); } @Action(value = "/budget/budgetProposalDetail-newRe") public String newRe() { showRe = true; final CFinancialYear date = financialYearService.getFinancialYearByDate(new Date()); persistenceService.getSession().setReadOnly(date, true); asOnDate = date.getStartingDate(); asOnDate.setMonth(Calendar.SEPTEMBER); asOnDate.setDate(30); // setFinancialYear(null); return NEWRE; } @Action(value = "/budget/budgetProposalDetail-newDetailRe") public String newDetailRe() { showRe = true; // setFinancialYear(null); return NEWDETAIL; } @ValidationErrorPage(value = NEWRE) @Action(value = "/budget/budgetProposalDetail-loadActualsForRe") public String loadActualsForRe() { showRe = true; try { final Long id = budgetDetail.getBudget().getId(); final Budget budget = budgetService.findById(id, false); budgetDetail.setBudget(budget); loadAjaxedFunctionAndBudgetGroup(); loadActuals(); } catch (final ValidationException e) { LOGGER.error(e.getMessage(), e); populateBudgetList(); throw e; } populateBudgetList(); return NEWRE; } @ValidationErrorPage(value = NEWDETAIL) @Action(value = "/budget/budgetProposalDetail-loadActualsForBudgetDetailRe") public String loadActualsForBudgetDetailRe() { showRe = true; try { loadActuals(); showDetails = true; } catch (final ValidationException e) { LOGGER.error(e.getMessage(), e); populateBudgetList(); throw e; } populateBudgetList(); return NEWDETAIL; } public void setShowRe(final boolean showRe) { this.showRe = showRe; } public boolean isShowRe() { return showRe; } protected String getMessage(final String key) { return getText(key); } public Budget getTopBudget() { return topBudget; } public void setTopBudget(final Budget topBudget) { this.topBudget = topBudget; } public void setBeNextYearAmounts(final Map<Long, BigDecimal> beNextYearAmounts) { this.beNextYearAmounts = beNextYearAmounts; } public Map<Long, BigDecimal> getBeNextYearAmounts() { return beNextYearAmounts; } public List getFunctionList() { return functionList; } public void setFunctionList(final List functionList) { this.functionList = functionList; } public List getBudgetGroupList() { return budgetGroupList; } public Long getFunction() { return function; } public void setFunction(final Long function) { this.function = function; } public Long getBudgetGroups() { return budgetGroups; } public void setBudgetGroups(final Long budgetGroups) { this.budgetGroups = budgetGroups; } }