/*
* 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.services.budget;
import org.apache.log4j.Logger;
import org.egov.commons.CChartOfAccounts;
import org.egov.commons.EgwStatus;
import org.egov.commons.dao.EgwStatusHibernateDAO;
import org.egov.eis.entity.Assignment;
import org.egov.eis.entity.Employee;
import org.egov.eis.service.EisCommonService;
import org.egov.infra.admin.master.entity.Department;
import org.egov.infra.admin.master.entity.User;
import org.egov.infra.exception.ApplicationRuntimeException;
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.workflow.service.SimpleWorkflowService;
import org.egov.infra.workflow.service.WorkflowService;
import org.egov.infstr.services.PersistenceService;
import org.egov.infstr.utils.EGovConfig;
import org.egov.model.budget.Budget;
import org.egov.model.budget.BudgetDetail;
import org.egov.model.budget.BudgetGroup;
import org.egov.pims.commons.Position;
import org.egov.pims.model.PersonalInformation;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* @author Manikanta
*
*/
public class BudgetService extends PersistenceService<Budget, Long> {
private static final Logger LOGGER = Logger.getLogger(BudgetService.class);
@Autowired
protected EisCommonService eisCommonService;
protected WorkflowService<Budget> budgetWorkflowService;
@Autowired
@Qualifier("workflowService")
protected SimpleWorkflowService<BudgetDetail> budgetDetailWorkflowService;
@Autowired
@Qualifier("persistenceService")
private PersistenceService persistenceService;
@Autowired
private EgwStatusHibernateDAO egwStatusDAO;
public void setEisCommonService(final EisCommonService eisCommonService) {
this.eisCommonService = eisCommonService;
}
public BudgetService() {
super(Budget.class);
}
public BudgetService(final Class<Budget> type) {
super(type);
}
public Budget getByName(final String name) {
return find("from Budget b where b.name = ?", name);
}
public User getUser() {
return (User) ((PersistenceService) this).find(" from User where id=?", ApplicationThreadLocals.getUserId());
}
public Position getPositionForEmployee(final Employee emp) throws ApplicationRuntimeException
{
return eisCommonService.getPrimaryAssignmentPositionForEmp(emp.getId());
}
/**
* return the department of any one budget detail will work for only leaf budget not for non leaf budgets
* @param budget
* @return Department
* @throws ApplicationRuntimeException
*/
public Department getDepartmentForBudget(final Budget budget) throws ApplicationRuntimeException
{
Department dept = null;
final List<BudgetDetail> detailList = ((PersistenceService) this).findAllBy(
"from BudgetDetail budgetDetail where budgetDetail.budget=?", budget);
if (detailList.isEmpty() || detailList.size() == 0)
throw new ApplicationRuntimeException("Details not found for the Budget" + budget.getName());
else if (detailList.get(0).getExecutingDepartment() == null)
throw new ApplicationRuntimeException("Department not found for the Budget" + budget.getName());
else
dept = detailList.get(0).getExecutingDepartment();
return dept;
}
/**
* returns department of the employee from assignment for the current date
* @param emp
* @return department
*/
public Department depertmentForEmployee(final Employee emp)
{
Department dept = null;
final Date currDate = new Date();
try {
final Assignment empAssignment = eisCommonService.getLatestAssignmentForEmployeeByToDate(emp.getId(), currDate);
dept = empAssignment.getDepartment();
return dept;
} catch (final NullPointerException ne)
{
throw new ApplicationRuntimeException(ne.getMessage());
} catch (final Exception e) {
throw new ApplicationRuntimeException("Error while getting Department fort the employee" + emp.getName());
}
}
public boolean hasReForYear(final Long financialYear) {
return checkForRe("from Budget where financialYear.id=? and isbere='RE' and isActiveBudget=true", financialYear);
}
public boolean hasApprovedBeForYear(final Long financialYear) {
return checkForRe(
"from Budget where financialYear.id=? and isbere='BE' and isActiveBudget=true and parent is null and isPrimaryBudget=true and status.code='Approved'",
financialYear);
}
public boolean hasApprovedReForYear(final Long financialYear) {
return checkForRe(
"from Budget where financialYear.id=? and isbere='RE' and isActiveBudget=true and parent is null and isPrimaryBudget=true and status.code='Approved'",
financialYear);
}
/**
*
* @param financialYear
* @return boolean Finds out whether RE is created and Approved for the given date
*/
public boolean hasApprovedReAsonDate(final Long finYearId, final Date budgetApprovedDate) {
final Query qry = getSearchSession()
.createQuery(
"select name from Budget where financialYear.id=:finYearId and isbere='RE' "
+
"and isActiveBudget=true and parent is null and isPrimaryBudget=true and status.code='Approved' and to_date(state.createdDate)<=:budgetApprovedDate");
qry.setParameter("finYearId", finYearId);
qry.setParameter("budgetApprovedDate", budgetApprovedDate);
final String approvedBudgetName = (String) qry.uniqueResult();
return approvedBudgetName == null ? false : true;
}
private boolean checkForRe(final String query, final Long financialYear) {
final Budget budget = find(query, financialYear);
if (budget == null)
return false;
return true;
}
/**
* finds all the child budget tree for approval or rejection
* @param b
* @param position
* @return
*/
public List<Budget> moveBudgetTree(final Budget b, final Position position) {
final List<Budget> budgetsList = findAllBy("from Budget b where b.materializedPath like '" + b.getMaterializedPath()
+ ".%'");
return budgetsList;
}
/**
* @param budgetsList
* @return The Base Budget Item is set from action class for which the details are moved Budget b is used to avoid recursive
* class
*/
public void moveDetailsTree(final List budgetsList, final Budget b, final String actionName) {
for (final Object o : budgetsList) {
final Budget childBudget = (Budget) o;
if (LOGGER.isDebugEnabled())
LOGGER.debug("Budget name " + childBudget.getName() + "moved details are ...");
final List<BudgetDetail> unsavedbudgetDetailList = new ArrayList<BudgetDetail>();
// unsavedbudgetDetailList.addAll(budgetDetailService.getRemainingDetailsForApproveOrReject(childBudget));
// move rest of the details
for (final BudgetDetail detail : unsavedbudgetDetailList) {
if (LOGGER.isDebugEnabled())
LOGGER.debug("moveDetails" + detail.getApprovedAmount());
budgetDetailWorkflowService.transition(actionName, detail, detail.getComment());
}
}
}
public boolean canForwardParent(final Position position, final Budget b) {
final Budget treeBudget = b;
final List<Budget> totalCountList = findAllBy("from Budget where parent=? and isActiveBudget=?", treeBudget.getParent(),
true);
// can forward the budget even though one of the child is not in the state of forwarding if isActiveBudget is set as false
final List<Budget> budgetList = findAllBy("from Budget where state.owner=? and parent.id=? and isActiveBudget=?",
position,
treeBudget.getParent().getId(), true);
if (totalCountList.size() == budgetList.size()) {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Approving Parent Budget:... " + treeBudget.getParent().getName());
return true;
} else {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Still some ChildBudgets are pending to move Parent .Exiting.... ");
return false;
}
}
/**
*
* @param bgroupList
* @return List of CChartOfAccounts objects associated with each BudgetGroup object in the list , null if no CChartOfAccounts
* objects are associated with any BudgetGroup object in the list.
* @throws ValidationException
*
*/
@SuppressWarnings("unchecked")
public List<CChartOfAccounts> getAccountCodeForBudgetHead(final List<BudgetGroup> bgroupList) throws ValidationException
{
if (bgroupList == null)
throw new ValidationException(Arrays.asList(new ValidationError("BudgetGroup List is Null",
"budgetgroup.list.is.null")));
if (bgroupList.size() == 0)
throw new ValidationException(Arrays.asList(new ValidationError("BudgetGroup List is Empty",
"budgetgroup.list.is.empty")));
final List<CChartOfAccounts> coaList = new ArrayList<CChartOfAccounts>();
final Integer maxpossibleGlcodeLength = Integer.parseInt(EGovConfig.getProperty("egf_config.xml", "glcodeMaxLength", "",
"AccountCode"));
CChartOfAccounts maxCode, minCode;
String maxGlcodeStr, minGlcodeStr, glcodeFrom, glcodeTo;
final String multipleZeros = new String("00000000000000000000");
final String multipleNines = new String("99999999999999999999");
for (final BudgetGroup bdgtgrp : bgroupList)
if (((PersistenceService) this).find("from BudgetGroup where id = ? ", bdgtgrp.getId()) == null)
throw new ValidationException(Arrays.asList(new ValidationError("BudgetGroup with id:" + bdgtgrp.getId()
+ " and name:" + bdgtgrp.getName() + " does not exist ", "BudgetGroup with id:" + bdgtgrp.getId()
+ " and name:" + bdgtgrp.getName() + " does not exist ")));
List<CChartOfAccounts> clist;
for (final BudgetGroup bdgtgrp : bgroupList)
{
if (bdgtgrp.getMajorCode() == null)
{
maxCode = bdgtgrp.getMaxCode();
minCode = bdgtgrp.getMinCode();
if (maxCode != null && minCode != null) {
maxGlcodeStr = maxCode.getGlcode();
minGlcodeStr = minCode.getGlcode();
if (maxpossibleGlcodeLength == maxGlcodeStr.length())
{
glcodeFrom = minGlcodeStr;
glcodeTo = maxGlcodeStr;
}
else
{
glcodeFrom = minGlcodeStr + multipleZeros.substring(0, maxpossibleGlcodeLength - minGlcodeStr.length());
glcodeTo = maxGlcodeStr + multipleNines.substring(0, maxpossibleGlcodeLength - maxGlcodeStr.length());
}
final String query = new String(
"from CChartOfAccounts coa where cast(coa.glcode,long) between ? and ? and coa.classification = ? and coa.isActiveForPosting=? ");
clist = ((PersistenceService) this).findAllBy(query, Long.parseLong(glcodeFrom),
Long.parseLong(glcodeTo), Long.valueOf(4), Long.valueOf(1));
}
else
throw new ValidationException(Arrays.asList(new ValidationError(
"Maxcode or Mincode is null also Majorcode is null for BudgetGroup:" + bdgtgrp.getName(),
"maxcode.or.mincode.is.null.and.majorcode.is.null.for.budgetgroup:" + bdgtgrp.getName())));
} else
clist = ((PersistenceService) this).findAllBy(
"from CChartOfAccounts coa where coa.glcode like '" + bdgtgrp.getMajorCode().getGlcode().toString()
+ "%' and coa.classification = ? and coa.isActiveForPosting= ? ", Long.valueOf(4),
Long.valueOf(1));
if (clist != null && clist.size() != 0)
coaList.addAll(clist);
}
return coaList.size() == 0 ? null : coaList;
}
public void setBudgetWorkflowService(final WorkflowService<Budget> budgetWorkflowService) {
this.budgetWorkflowService = budgetWorkflowService;
}
public void setBudgetDetailWorkflowService(final SimpleWorkflowService<BudgetDetail> budgetDetailWorkflowService) {
this.budgetDetailWorkflowService = budgetDetailWorkflowService;
}
public String getEmployeeNameAndDesignationForPosition(final Position pos) throws ApplicationRuntimeException {
final Employee pi = eisCommonService.getPrimaryAssignmentEmployeeForPos(pos.getId());
final Assignment assignment = eisCommonService.getLatestAssignmentForEmployee(pi.getId());
return pi.getName() + " (" + assignment.getDesignation().getName() + ")";
}
public PersonalInformation getEmpForCurrentUser() {
return eisCommonService.getEmployeeByUserId(ApplicationThreadLocals.getUserId());
}
public Budget getReferenceBudgetFor(final Budget budget) {
Budget refBudget = null;
try {
refBudget = find("from Budget where referenceBudget.id=?", budget.getId());
} catch (final Exception e) {
throw new ValidationException(Arrays.asList(new ValidationError(e.getMessage(), e.getMessage())));
}
return refBudget;
}
public boolean isLeaf(final Budget budget) {
final List<Budget> budgetList = findAllBy(
"from Budget where financialYear.id=? and id in (select parent from Budget where financialYear.id=? and parent.id=?)",
budget.getFinancialYear().getId(), budget.getFinancialYear().getId(), budget.getId());
return budgetList == null || budgetList.isEmpty();
}
public List getFYForNonApprovedBudgets() {
return findAllBy("select distinct b.financialYear from Budget b where b.status.code=!'Approved' and isActiveBudget=true and isPrimaryBudget=true order by b.financialYear.finYearRange desc");
}
public Budget getBudget(String budgetHead, String deptCode, String budgetType, String fyear) {
String budgetName;
if (budgetHead.substring(0, 1).equalsIgnoreCase("1")
|| budgetHead.substring(0, 1).equalsIgnoreCase("2"))
budgetName = deptCode + "-" + budgetType + "-Rev-" + fyear;
else
budgetName = deptCode + "-" + budgetType + "-Cap-" + fyear;
return getByName(budgetName);
}
public List<Budget> getBudgetsForUploadReport() {
return findAllBy("select distinct b from Budget b where b.name like '%RE%' and b.materializedPath in (select distinct substring(bd.materializedPath, 1 , 1) from BudgetDetail bd where bd.status.code = 'Created')");
}
@Transactional
public void updateByMaterializedPath(final String materializedPath) {
EgwStatus approvedStatus = egwStatusDAO.getStatusByModuleAndCode("BUDGET", "Approved");
EgwStatus createdStatus = egwStatusDAO.getStatusByModuleAndCode("BUDGET", "Created");
persistenceService
.getSession()
.createSQLQuery(
"update egf_budget set status = :approvedStatus where status =:createdStatus and materializedPath like'"
+ materializedPath + "%'").setLong("approvedStatus", approvedStatus.getId())
.setLong("createdStatus", createdStatus.getId()).executeUpdate();
}
}