/*
* 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.works.web.actions.tender;
import net.sf.jasperreports.engine.JRException;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
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.dao.EgwStatusHibernateDAO;
import org.egov.eis.entity.Assignment;
import org.egov.eis.service.AssignmentService;
import org.egov.eis.web.actions.workflow.GenericWorkFlowAction;
import org.egov.infra.admin.master.entity.Boundary;
import org.egov.infra.admin.master.entity.Department;
import org.egov.infra.admin.master.entity.User;
import org.egov.infra.admin.master.service.UserService;
import org.egov.infra.persistence.entity.component.Money;
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.validation.exception.ValidationError;
import org.egov.infra.validation.exception.ValidationException;
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.works.abstractestimate.entity.AbstractEstimate;
import org.egov.works.models.tender.WorksPackage;
import org.egov.works.models.tender.WorksPackageDetails;
import org.egov.works.services.AbstractEstimateService;
import org.egov.works.services.WorksPackageService;
import org.egov.works.services.WorksService;
import org.egov.works.utils.DateConversionUtil;
import org.egov.works.utils.WorksConstants;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Results({ @Result(name = WorksPackageAction.PRINT, type = "stream", location = "WorkspackagePDF", params = {
"inputName", "WorkspackagePDF", "contentType", "application/pdf", "contentDisposition",
"no-cache;filename=WorksPackage.pdf" }),
@Result(name = WorksPackageAction.NEW, location = "worksPackage-new.jsp"),
@Result(name = WorksPackageAction.EDIT, location = "worksPackage-edit.jsp"),
@Result(name = WorksPackageAction.SUCCESS, location = "worksPackage-success.jsp") })
public class WorksPackageAction extends GenericWorkFlowAction {
private static final long serialVersionUID = -6365331777546797839L;
private WorksService worksService;
private WorksPackage worksPackage = new WorksPackage();
private String designation;
private Integer empId;
private Long[] estId;
private String sourcepage;
private Money worktotalValue;
@Autowired
private EgwStatusHibernateDAO egwStatusHibernateDAO;
private WorksPackageService workspackageService;
private AbstractEstimateService abstractEstimateService;
private List<AbstractEstimate> abstractEstimateList = new ArrayList<AbstractEstimate>();
private Long id;
private String messageKey;
private String nextEmployeeName;
private String nextDesignation;
private String packageNumber;
private static final String DEPARTMENT_LIST = "departmentList";
public static final String WORKSPACKAGE = "WorksPackage";
public static final String PRINT = "print";
private InputStream WorkspackagePDF;
private ReportService reportService;
@Autowired
private AssignmentService assignmentService;
@Autowired
private SecurityUtils securityUtils;
@Autowired
@Qualifier("workflowService")
private SimpleWorkflowService<AbstractEstimate> worksPackageWorkflowService;
public WorksPackageAction() {
addRelatedEntity("department", Department.class);
}
@Override
public void prepare() {
super.prepare();
if (id != null) {
worksPackage = workspackageService.findById(id, false);
worksPackage = workspackageService.merge(worksPackage);
}
if (id == null && packageNumber != null && StringUtils.isNotBlank(packageNumber))
worksPackage = workspackageService.find("from WorksPackage where wpNumber=? and egwStatus.code='APPROVED'",
packageNumber);
setupDropdownDataExcluding("department");
if (worksPackage.getId() == null || worksPackage.getId() != null
&& (worksPackage.getEgwStatus().getCode()
.equalsIgnoreCase(WorksPackage.WorkPacakgeStatus.REJECTED.toString()) || worksPackage
.getEgwStatus().getCode().equalsIgnoreCase("NEW")))
addDropdownData(DEPARTMENT_LIST, worksService.getAllDeptmentsForLoggedInUser());
else
addDropdownData(DEPARTMENT_LIST, Arrays.asList(worksPackage.getDepartment()));
final Assignment latestAssignment = abstractEstimateService.getLatestAssignmentForCurrentLoginUser();
if (latestAssignment != null) {
approverDepartment = abstractEstimateService.getLatestAssignmentForCurrentLoginUser()
.getDepartment().getId().toString();
if (worksPackage.getDepartment() == null)
worksPackage.setDepartment(latestAssignment.getDepartment());
}
}
@Action(value = "/tender/worksPackage-newform")
public String newform() {
return NEW;
}
@Action(value = "/tender/worksPackage-edit")
public String edit() {
// TODO:Fixme - commented out for time being since the validation not working properly
/*
* if (SOURCE_INBOX.equalsIgnoreCase(sourcepage)) { final User user =
* userService.getUserById(worksService.getCurrentLoggedInUserId()); final boolean isValidUser =
* worksService.validateWorkflowForUser(worksPackage, user); if (isValidUser) throw new ApplicationRuntimeException(
* "Error: Invalid Owner - No permission to view this page."); } else
*/if (StringUtils.isEmpty(sourcepage))
sourcepage = "search";
abstractEstimateList = workspackageService.getAbStractEstimateListByWorksPackage(worksPackage);
setWorktotalValue(abstractEstimateService.getWorkValueIncludingTaxesForEstList(abstractEstimateList));
return EDIT;
}
@Action(value = "/tender/worksPackage-save")
public String save() {
if (validTenderFileNo())
throw new ValidationException(Arrays.asList(new ValidationError("wp.tenderfilenumber.isunique",
"wp.tenderfilenumber.isunique")));
if (worksPackage.getId() != null
&& (worksPackage.getEgwStatus().getCode()
.equalsIgnoreCase(WorksPackage.WorkPacakgeStatus.REJECTED.toString()) || worksPackage
.getEgwStatus().getCode().equalsIgnoreCase("NEW")))
worksPackage.getWorksPackageDetails().clear();
if (worksPackage.getId() == null
|| worksPackage.getEgwStatus().getCode()
.equalsIgnoreCase(WorksPackage.WorkPacakgeStatus.REJECTED.toString())
|| worksPackage.getEgwStatus().getCode().equalsIgnoreCase("NEW"))
populateEstimatesList(estId);
if (worksPackage.getId() == null && worksPackage.getEgwStatus() == null && abstractEstimateList.size() > 0) {
validateFinancingSource(abstractEstimateList);
validateEstimateForUniqueness();
}
validateWorksPackageDate();
transitionWorkFlow(worksPackage);
abstractEstimateService.applyAuditing(worksPackage.getState());
workspackageService.setWorksPackageNumber(worksPackage,
abstractEstimateService.getCurrentFinancialYear(worksPackage.getWpDate()));
if (worksPackage.getEgwStatus() != null
&& worksPackage.getEgwStatus().getCode()
.equals(WorksPackage.WorkPacakgeStatus.APPROVED.toString()))
worksPackage.setApprovedDate(new Date());
worksPackage = workspackageService.persist(worksPackage);
messageKey = "worksPackage." + workFlowAction;
addActionMessage(getText(messageKey, "The Works Package was saved successfully"));
if (WorksConstants.SAVE_ACTION.equals(workFlowAction))
sourcepage = "inbox";
return WorksConstants.SAVE_ACTION.equals(workFlowAction) ? EDIT : SUCCESS;
}
private void validateWorksPackageDate() {
if (worksPackage.getWpDate() != null && DateConversionUtil.isBeforeByDate(new Date(), worksPackage.getWpDate()))
throw new ValidationException(Arrays.asList(new ValidationError("invalid.wpDate", "invalid.wpDate")));
}
private void validateFinancingSource(final List<AbstractEstimate> estimateList) {
Integer fundSourceId1;
fundSourceId1 = abstractEstimateList.get(0).getFundSource().getId().intValue();
for (int i = 1; i < abstractEstimateList.size(); i++)
if (fundSourceId1 != abstractEstimateList.get(i).getFundSource().getId().intValue())
throw new ValidationException(Arrays.asList(new ValidationError(
"wp.estimate.different.fund.source.not.allowed",
"wp.estimate.different.fund.source.not.allowed")));
}
private void validateEstimateForUniqueness() {
WorksPackage wp = null;
final Map<String, List<AbstractEstimate>> wpMap = new HashMap<String, List<AbstractEstimate>>();
List<AbstractEstimate> estimateList = null;
for (final AbstractEstimate estimate : abstractEstimateList) {
wp = workspackageService.getWorksPackageForAbstractEstimate(estimate);
if (wp != null) {
final String wpString = wp.getWpNumber() + "~!"
+ (wp.getEgwStatus().getDescription() != null ? wp.getEgwStatus().getDescription() : " ");
if (wpMap.get(wpString) == null) {
estimateList = new ArrayList<AbstractEstimate>();
estimateList.add(estimate);
wpMap.put(wpString, estimateList);
} else
wpMap.get(wpString).add(estimate);
}
}
if (!wpMap.isEmpty()) {
final List<ValidationError> errors = new ArrayList<ValidationError>();
for (final String wpnumber : wpMap.keySet()) {
final List<AbstractEstimate> estList = wpMap.get(wpnumber);
StringBuffer estimatesSting = null;
for (final AbstractEstimate absEstimate : estList)
if (estimatesSting == null) {
estimatesSting = new StringBuffer();
estimatesSting.append(absEstimate.getEstimateNumber());
} else
estimatesSting.append(", ").append(absEstimate.getEstimateNumber());
final String[] str = StringUtils.split(wpnumber, "~!");
errors.add(new ValidationError("worksPackage.uniqueCheck.message", "worksPackage.uniqueCheck.message",
new String[] { str[0], estimatesSting.toString(), str[1] }));
}
throw new ValidationException(errors);
}
}
private void transitionWorkFlow(final WorksPackage worksPackage) {
final DateTime currentDate = new DateTime();
final User user = securityUtils.getCurrentUser();
final Assignment userAssignment = assignmentService.getPrimaryAssignmentForUser(user.getId());
Position position = null;
Assignment wfInitiator = null;
wfInitiator = getWorkflowInitiator(worksPackage);
if (WorksConstants.CANCEL_ACTION.equals(workFlowAction)) {
if (wfInitiator.equals(userAssignment)) {
worksPackage.transition(true).end().withSenderName(user.getName()).withComments(approverComments)
.withStateValue(WorksPackage.WorkPacakgeStatus.CANCELLED.toString()).withDateInfo(currentDate.toDate())
.withNextAction("END");
worksPackage.setEgwStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(WORKSPACKAGE,
WorksPackage.WorkPacakgeStatus.CANCELLED.toString()));
}
} else if (WorksConstants.REJECT_ACTION.equals(workFlowAction)) {
worksPackage.transition(true).withSenderName(user.getName()).withComments(approverComments)
.withStateValue(WorksPackage.WorkPacakgeStatus.REJECTED.toString()).withDateInfo(currentDate.toDate())
.withOwner(wfInitiator.getPosition()).withNextAction("");
worksPackage.setEgwStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(WORKSPACKAGE,
WorksPackage.WorkPacakgeStatus.REJECTED.toString()));
} else if (WorksConstants.SAVE_ACTION.equals(workFlowAction)) {
if (worksPackage.getState() == null) {
final WorkFlowMatrix wfmatrix = worksPackageWorkflowService.getWfMatrix(worksPackage.getStateType(), null,
null, getAdditionalRule(), currentState, null);
worksPackage.transition().start().withSenderName(user.getName()).withComments(approverComments)
.withStateValue(wfmatrix.getCurrentState()).withDateInfo(currentDate.toDate())
.withOwner(wfInitiator.getPosition());
worksPackage
.setEgwStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(WORKSPACKAGE, "NEW"));
}
} else {
if (null != approverPositionId && approverPositionId != -1)
position = (Position) persistenceService.find("from Position where id=?", approverPositionId);
if (worksPackage.getState() == null) {
final WorkFlowMatrix wfmatrix = worksPackageWorkflowService.getWfMatrix(worksPackage.getStateType(), null,
null, getAdditionalRule(), currentState, null);
worksPackage.transition().start().withSenderName(user.getName()).withComments(approverComments)
.withStateValue(wfmatrix.getNextState()).withDateInfo(currentDate.toDate()).withOwner(position)
.withNextAction(wfmatrix.getNextAction());
worksPackage
.setEgwStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(WORKSPACKAGE, wfmatrix.getNextStatus()));
} else {
final WorkFlowMatrix wfmatrix = worksPackageWorkflowService.getWfMatrix(worksPackage.getStateType(), null,
null, getAdditionalRule(), worksPackage.getCurrentState().getValue(), null);
if (wfmatrix.getNextAction() != null && wfmatrix.getNextAction().equalsIgnoreCase("END"))
worksPackage.transition(true).end().withSenderName(user.getName()).withComments(approverComments)
.withStateValue(wfmatrix.getNextState()).withDateInfo(currentDate.toDate())
.withNextAction(wfmatrix.getNextAction());
else
worksPackage.transition(true).withSenderName(user.getName()).withComments(approverComments)
.withStateValue(wfmatrix.getNextState()).withDateInfo(currentDate.toDate()).withOwner(position)
.withNextAction(wfmatrix.getNextAction());
worksPackage
.setEgwStatus(egwStatusHibernateDAO.getStatusByModuleAndCode(WORKSPACKAGE, wfmatrix.getNextStatus()));
}
}
if (!(WorksConstants.CANCEL_ACTION.equals(workFlowAction) || WorksConstants.SAVE_ACTION.equals(workFlowAction)))
setApproverAndDesignation(worksPackage);
}
private Assignment getWorkflowInitiator(final WorksPackage worksPackage) {
Assignment wfInitiator;
if (worksPackage.getCreatedBy() == null)
wfInitiator = assignmentService.getPrimaryAssignmentForUser(worksService.getCurrentLoggedInUserId());
else
wfInitiator = assignmentService.getPrimaryAssignmentForUser(worksPackage.getCreatedBy().getId());
return wfInitiator;
}
@Override
public StateAware getModel() {
return worksPackage;
}
public void setModel(final WorksPackage worksPackage) {
this.worksPackage = worksPackage;
}
protected void populateEstimatesList(final Long[] estimateID) {
if (estimateID != null && estimateID.length > 0) {
abstractEstimateList = abstractEstimateService.getAbEstimateListById(StringUtils.join(estId, "`~`"));
setWorktotalValue(abstractEstimateService.getWorkValueIncludingTaxesForEstList(abstractEstimateList));
} else
throw new ValidationException(Arrays.asList(new ValidationError("estimates.null",
"estimates.null")));
setWPDetails();
}
private void setWPDetails() {
if (!abstractEstimateList.isEmpty())
for (final AbstractEstimate ab : abstractEstimateList) {
final WorksPackageDetails wpDetails = new WorksPackageDetails();
wpDetails.setEstimate(ab);
wpDetails.setWorksPackage(worksPackage);
// TODO:Fixme - Manually setting auditable properties by time being since HibernateEventListener is not getting
// triggered on update of workspackage for child objects
final User user = worksService.getCurrentLoggedInUser();
wpDetails.setCreatedBy(user);
wpDetails.setCreatedDate(new Date());
wpDetails.setModifiedBy(user);
wpDetails.setModifiedDate(new Date());
worksPackage.addEstimates(wpDetails);
}
}
public boolean validTenderFileNo() {
boolean status = false;
if (worksPackage != null && worksPackage.getTenderFileNumber() != null) {
final AjaxWorksPackageAction ajaxWorksPackageAction = new AjaxWorksPackageAction();
ajaxWorksPackageAction.setPersistenceService(getPersistenceService());
ajaxWorksPackageAction.setWorkspackageService(workspackageService);
ajaxWorksPackageAction.setTenderFileNumber(worksPackage.getTenderFileNumber());
ajaxWorksPackageAction.setId(id);
if (ajaxWorksPackageAction.getTenderFileNumberCheck())
status = true;
}
return status;
}
/**
* print pdf *
* @throws JRException ,Exception
*/
@SkipValidation
@Action(value = "/tender/worksPackage-viewWorksPackagePdf")
public String viewWorksPackagePdf() throws JRException, Exception {
final ReportRequest reportRequest = new ReportRequest("Workspackage", worksPackage.getActivitiesForEstimate(),
createHeaderParams());
final ReportOutput reportOutput = reportService.createReport(reportRequest);
if (reportOutput != null && reportOutput.getReportOutputData() != null)
WorkspackagePDF = new ByteArrayInputStream(reportOutput.getReportOutputData());
return PRINT;
}
private Map createHeaderParams() {
final Map<String, Object> reportParams = new HashMap<String, Object>();
final List<WorksPackageDetails> worksPackageDetails = worksPackage.getWorksPackageDetails();
final AbstractEstimate estimate = worksPackageDetails.get(0).getEstimate();
final Boundary b = getTopLevelBoundary(estimate.getWard());
reportParams
.put("financialYear", abstractEstimateService.getCurrentFinancialYear(new Date()).getFinYearRange());
reportParams.put("total", worksPackage.getTotalAmount());
reportParams.put("cityName", b == null ? "" : b.getName());
reportParams.put("workPackageName", worksPackage.getName());
reportParams.put("worksPackageNumber", worksPackage.getWpNumber());
reportParams.put("departmentName", worksPackage.getDepartment().getName());
reportParams.put("tenderFileNumber", worksPackage.getTenderFileNumber());
reportParams.put("estimateNumbers", getEstimateNumbers(worksPackage));
return reportParams;
}
private String getEstimateNumbers(final WorksPackage wp) {
String estimateNumbers = "";
for (final WorksPackageDetails wpDetail : wp.getWorksPackageDetails())
estimateNumbers = estimateNumbers.concat(wpDetail.getEstimate().getEstimateNumber()).concat(",");
if (estimateNumbers.length() > 1)
estimateNumbers = estimateNumbers.substring(0, estimateNumbers.length() - 1);
return estimateNumbers;
}
protected Boundary getTopLevelBoundary(final Boundary boundary) {
Boundary b = boundary;
while (b != null && b.getParent() != null)
b = b.getParent();
return b;
}
private void setApproverAndDesignation(final WorksPackage worksPackage) {
/* start for customizing workflow message display */
if (worksPackage.getEgwStatus() != null
&& !"NEW".equalsIgnoreCase(worksPackage.getEgwStatus().getCode())) {
Date date = new Date();
if (worksPackage.getState().getCreatedDate() != null)
date = worksPackage.getState().getCreatedDate();
final String result = worksService.getEmpNameDesignation(worksPackage.getState().getOwnerPosition(),
date);
if (result != null && !"@".equalsIgnoreCase(result)) {
final String empName = result.substring(0, result.lastIndexOf('@'));
final String designation = result.substring(result.lastIndexOf('@') + 1, result.length());
setNextEmployeeName(empName);
setNextDesignation(designation);
}
}
/* end */
}
public void setWorksService(final WorksService worksService) {
this.worksService = worksService;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(final Integer empId) {
this.empId = empId;
}
public String getDesignation() {
return designation;
}
public void setDesignation(final String designation) {
this.designation = designation;
}
public void setWorkspackageService(final WorksPackageService workspackageService) {
this.workspackageService = workspackageService;
}
public Long[] getEstId() {
return estId;
}
public void setEstId(final Long[] estId) {
this.estId = estId;
}
public void setAbstractEstimateService(final AbstractEstimateService abstractEstimateService) {
this.abstractEstimateService = abstractEstimateService;
}
public List<AbstractEstimate> getAbstractEstimateList() {
return abstractEstimateList;
}
public void setAbstractEstimateList(final List<AbstractEstimate> abstractEstimateList) {
this.abstractEstimateList = abstractEstimateList;
}
public Money getWorktotalValue() {
return worktotalValue;
}
public void setWorktotalValue(final Money worktotalValue) {
this.worktotalValue = worktotalValue;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getSourcepage() {
return sourcepage;
}
public void setSourcepage(final String sourcepage) {
this.sourcepage = sourcepage;
}
public static String getPRINT() {
return PRINT;
}
public InputStream getWorkspackagePDF() {
return WorkspackagePDF;
}
public ReportService getReportService() {
return reportService;
}
public void setWorkspackagePDF(final InputStream workspackagePDF) {
WorkspackagePDF = workspackagePDF;
}
public void setReportService(final ReportService reportService) {
this.reportService = reportService;
}
public String getMessageKey() {
return messageKey;
}
public String getNextEmployeeName() {
return nextEmployeeName;
}
public void setNextEmployeeName(final String nextEmployeeName) {
this.nextEmployeeName = nextEmployeeName;
}
public String getNextDesignation() {
return nextDesignation;
}
public void setNextDesignation(final String nextDesignation) {
this.nextDesignation = nextDesignation;
}
public void setUserService(final UserService userService) {
}
public String getPackageNumber() {
return packageNumber;
}
public void setPackageNumber(final String packageNumber) {
this.packageNumber = packageNumber;
}
}