/*
* 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.abstractestimate.entity;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.egov.commons.CFinancialYear;
import org.egov.commons.EgwStatus;
import org.egov.commons.EgwTypeOfWork;
import org.egov.commons.Fundsource;
import org.egov.infra.admin.master.entity.Boundary;
import org.egov.infra.admin.master.entity.Department;
import org.egov.infra.persistence.entity.Auditable;
import org.egov.infra.persistence.entity.component.Money;
import org.egov.infra.persistence.validator.annotation.DateFormat;
import org.egov.infra.persistence.validator.annotation.Required;
import org.egov.infra.utils.StringUtils;
import org.egov.infra.validation.exception.ValidationError;
import org.egov.infra.workflow.entity.StateAware;
import org.egov.works.lineestimate.entity.LineEstimateDetails;
import org.egov.works.models.estimate.ProjectCode;
import org.egov.works.models.masters.DepositCode;
import org.egov.works.models.masters.NatureOfWork;
import org.egov.works.revisionestimate.entity.enums.RevisionType;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.SafeHtml;
@Entity
@Table(name = "EGW_ABSTRACTESTIMATE")
@Inheritance(strategy = InheritanceType.JOINED)
@NamedQueries({
@NamedQuery(name = AbstractEstimate.ABSTRACTESTIMATELIST_BY_ID, query = "from AbstractEstimate ab where ab.id in(:param_0)"),
@NamedQuery(name = AbstractEstimate.REVISION_ESTIMATES_BY_ESTID, query = "from AbstractEstimate ae where ae.parent.id=? and ae.egwStatus.code='APPROVED' order by ae.id"),
@NamedQuery(name = AbstractEstimate.REVISION_ESTIMATES_BY_ESTID_WOID, query = "from AbstractEstimate ae where ae.parent.id=? and ae.egwStatus.code='APPROVED' order by ae.id") })
@SequenceGenerator(name = AbstractEstimate.SEQ_EGW_ABSTRACTESTIMATE, sequenceName = AbstractEstimate.SEQ_EGW_ABSTRACTESTIMATE, allocationSize = 1)
public class AbstractEstimate extends StateAware implements Auditable {
private static final long serialVersionUID = 5010991868891221454L;
public enum EstimateStatus {
CREATED, TECH_SANCTION_CHECKED, TECH_SANCTIONED, BUDGETARY_APPR_CHECKED, BUDGETARY_APPROPRIATION_DONE, ADMIN_CHECKED, ADMIN_SANCTIONED, REJECTED, CANCELLED, APPROVED
}
public enum Actions {
SUBMIT_FOR_APPROVAL, TECH_SANCTION, BUDGET_DETAILS_SAVE, BUDGET_APPROPRIATION, ADMIN_SANCTION, REJECT, CANCEL;
@Override
public String toString() {
return name().toLowerCase();
}
}
public static final String SEQ_EGW_ABSTRACTESTIMATE = "SEQ_EGW_ABSTRACTESTIMATE";
public static final String ABSTRACTESTIMATELIST_BY_ID = "ABSTRACTESTIMATELIST_BY_ID";
public static final String REVISION_ESTIMATES_BY_ESTID = "REVISION_ESTIMATES_BY_ESTID";
public static final String REVISION_ESTIMATES_BY_ESTID_WOID = "REVISION_ESTIMATES_BY_ESTID_WOID";
@Id
@GeneratedValue(generator = SEQ_EGW_ABSTRACTESTIMATE, strategy = GenerationType.SEQUENCE)
private Long id;
@NotNull
@SafeHtml
@Length(max = 256)
private String estimateNumber;
@NotNull
@Temporal(value = TemporalType.DATE)
private Date estimateDate;
@NotNull
@SafeHtml
@Length(max = 1024)
@Column(name = "nameofwork")
private String name;
@NotNull
@SafeHtml
@Length(max = 1024)
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userdepartment")
private Department userDepartment;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "executingdepartment")
private Department executingDepartment;
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "jurisdiction", nullable = false)
private Boundary ward;
@SafeHtml
@Length(max = 250)
private String location;
private BigDecimal latitude;
private BigDecimal longitude;
@NotNull(message = "estimate.worktype.null")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "natureofwork", nullable = false)
private NatureOfWork natureOfWork;
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "typeofwork", nullable = false)
private EgwTypeOfWork parentCategory;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "subtypeofwork")
private EgwTypeOfWork category;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fundsource")
private Fundsource fundSource;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status", nullable = false)
private EgwStatus egwStatus;
private double workValue;
private BigDecimal estimateValue;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "projectcode")
private ProjectCode projectCode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "despositcode")
private DepositCode depositCode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent")
private AbstractEstimate parent;
@Temporal(value = TemporalType.DATE)
@Column(name = "approveddate")
private Date approvedDate;
private boolean copiedEstimate = false;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "lineEstimateDetails")
private LineEstimateDetails lineEstimateDetails;
@Transient
private String positionAndUserName;
@Transient
private Integer approverUserId;
@Valid
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = OverheadValue.class)
private List<OverheadValue> overheadValues = new ArrayList<OverheadValue>(0);
@Valid
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = AssetsForEstimate.class)
private List<AssetsForEstimate> assetValues = new ArrayList<AssetsForEstimate>(0);
@Valid
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = Activity.class)
private List<Activity> activities = new ArrayList<Activity>(0);
@Valid
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = MultiYearEstimate.class)
private List<MultiYearEstimate> multiYearEstimates = new ArrayList<MultiYearEstimate>(0);
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = AbstractEstimateAppropriation.class)
private List<AbstractEstimateAppropriation> abstractEstimateAppropriations = new ArrayList<AbstractEstimateAppropriation>(0);
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = FinancialDetail.class)
private List<FinancialDetail> financialDetails = new ArrayList<FinancialDetail>(0);
@OrderBy("id")
@OneToMany(mappedBy = "abstractEstimate", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = EstimateTechnicalSanction.class)
private List<EstimateTechnicalSanction> estimateTechnicalSanctions = new ArrayList<EstimateTechnicalSanction>(0);
@Override
public Long getId() {
return id;
}
@Override
public void setId(final Long id) {
this.id = id;
}
@Required(message = "estimate.name.null")
@Length(max = 1024, message = "estimate.name.length")
public String getName() {
return name;
}
public String getNameJS() {
return StringUtils.escapeJavaScript(name);
}
public String getNameJson() {
return org.apache.commons.lang.StringUtils.escape(name);
}
public void setName(final String name) {
this.name = StringEscapeUtils.unescapeHtml(name);
}
@Required(message = "estimate.date.null")
@DateFormat(message = "invalid.fieldvalue.estimateDate")
public Date getEstimateDate() {
return estimateDate;
}
public void setEstimateDate(final Date estimateDate) {
this.estimateDate = estimateDate;
}
@Required(message = "estimate.desc.null")
@Length(max = 1024, message = "estimate.desc.length")
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
@Length(max = 250, message = "estimate.loc.length")
public String getLocation() {
return location;
}
public void setLocation(final String location) {
this.location = location;
}
@Required(message = "estimate.natureofwork.null")
public NatureOfWork getNatureOfWork() {
return natureOfWork;
}
public void setNatureOfWork(final NatureOfWork natureOfWork) {
this.natureOfWork = natureOfWork;
}
public EgwTypeOfWork getCategory() {
return category;
}
public void setCategory(final EgwTypeOfWork category) {
this.category = category;
}
public Department getUserDepartment() {
return userDepartment;
}
public void setUserDepartment(final Department userDepartment) {
this.userDepartment = userDepartment;
}
@Required(message = "estimate.executingDept.null")
public Department getExecutingDepartment() {
return executingDepartment;
}
public void setExecutingDepartment(final Department executingDepartment) {
this.executingDepartment = executingDepartment;
}
@Required(message = "estimate.ward.null")
public Boundary getWard() {
return ward;
}
public void setWard(final Boundary ward) {
this.ward = ward;
}
public double getWorkValue() {
double amt = 0;
if (!activities.isEmpty()) {
for (final Activity activity : activities)
if (activity.getRevisionType() != null && activity.getRevisionType().equals(RevisionType.REDUCED_QUANTITY))
amt -= activity.getAmount().getValue();
else
amt += activity.getAmount().getValue();
workValue = amt;
}
return workValue;
}
/**
* This method returns the grand total of the work value for all the activities ( both SOR and Non SOR combined)
*
* @return a double value representing the rounded figure of the total of the grand total of the work value for all the
* activities ( both SOR and Non SOR combined)
*/
public Money getWorkValueIncludingTaxes() {
return new Money(getWorkValue() + getTotalTax().getValue());
}
public Money getTotalTax() {
double amt = 0;
for (final Activity activity : activities)
if (activity.getRevisionType() != null && activity.getRevisionType().equals(RevisionType.REDUCED_QUANTITY))
amt = amt - activity.getTaxAmount().getValue();
else
amt += activity.getTaxAmount().getValue();
return new Money(amt);
}
public void setWorkValue(final double workValue) {
this.workValue = workValue;
}
public List<OverheadValue> getOverheadValues() {
return overheadValues;
}
public void setOverheadValues(final List<OverheadValue> overheadValues) {
this.overheadValues = overheadValues;
}
public void addOverheadValue(final OverheadValue overheadValue) {
overheadValues.add(overheadValue);
}
public List<AssetsForEstimate> getAssetValues() {
return assetValues;
}
public void setAssetValues(final List<AssetsForEstimate> assetValues) {
this.assetValues = assetValues;
}
public void addAssetValue(final AssetsForEstimate assetValue) {
assetValues.add(assetValue);
}
public List<FinancialDetail> getFinancialDetails() {
return financialDetails;
}
public void setFinancialDetails(final List<FinancialDetail> financialDetails) {
this.financialDetails = financialDetails;
}
public void addFinancialDetails(final FinancialDetail financialDetails) {
this.financialDetails.add(financialDetails);
}
public Money getTotalAmount() {
return new Money(estimateValue.doubleValue());
}
public List<Activity> getActivities() {
return activities;
}
public ProjectCode getProjectCode() {
return projectCode;
}
public void setProjectCode(final ProjectCode projectCode) {
this.projectCode = projectCode;
}
public Collection<Activity> getSORActivities() {
return CollectionUtils.select(activities, activity -> ((Activity) activity).getSchedule() != null);
}
public Collection<Activity> getNonSORActivities() {
return CollectionUtils.select(activities, activity -> ((Activity) activity).getNonSor() != null);
}
public void setActivities(final List<Activity> activities) {
this.activities = activities;
}
public void addActivity(final Activity activity) {
activities.add(activity);
}
public String getEstimateNumber() {
return estimateNumber;
}
public void setEstimateNumber(final String estimateNumber) {
this.estimateNumber = estimateNumber;
}
public EgwTypeOfWork getParentCategory() {
return parentCategory;
}
public void setParentCategory(final EgwTypeOfWork parentCategory) {
this.parentCategory = parentCategory;
}
public List<MultiYearEstimate> getMultiYearEstimates() {
return multiYearEstimates;
}
public void setMultiYearEstimates(final List<MultiYearEstimate> multiYearEstimates) {
this.multiYearEstimates = multiYearEstimates;
}
public void addMultiYearEstimate(final MultiYearEstimate multiYearEstimate) {
multiYearEstimates.add(multiYearEstimate);
}
public List<ValidationError> validate() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
validationErrors.addAll(validateActivities());
validationErrors.addAll(validateOverheads());
validationErrors.addAll(validateAssets());
validationErrors.addAll(validateMultiYearEstimates());
validationErrors.addAll(validateFinancialDetails());
return validationErrors;
}
public List<ValidationError> validateFinancialDetails() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (final FinancialDetail financialDetail : financialDetails)
validationErrors.addAll(financialDetail.validate());
return validationErrors;
}
public List<ValidationError> validateActivities() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (final Activity activity : activities)
validationErrors.addAll(activity.validate());
return validationErrors;
}
public List<ValidationError> validateOverheads() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (final OverheadValue overheadValue : overheadValues)
validationErrors.addAll(overheadValue.validate());
return validationErrors;
}
public List<ValidationError> validateAssets() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (final AssetsForEstimate assetValue : assetValues)
validationErrors.addAll(assetValue.validate());
return validationErrors;
}
public List<ValidationError> validateMultiYearEstimates() {
final List<ValidationError> validationErrors = new ArrayList<ValidationError>();
for (final MultiYearEstimate multiYearEstimate : multiYearEstimates)
validationErrors.addAll(multiYearEstimate.validate());
return validationErrors;
}
/**
* This method returns the least of the financial years chosen from the multi year estimates
*
* @return an instance of <code>CFinancialYear</code> representing the least financial year
*/
public CFinancialYear getLeastFinancialYearForEstimate() {
CFinancialYear minfinYr = null;
Date minStartDate = new Date();
Date startDate;
if (getMultiYearEstimates() != null) {
minStartDate = getMultiYearEstimates().get(0).getFinancialYear().getStartingDate();
minfinYr = getMultiYearEstimates().get(0).getFinancialYear();
}
for (int i = 1; i < getMultiYearEstimates().size(); i++) {
startDate = getMultiYearEstimates().get(i).getFinancialYear().getStartingDate();
if (startDate.before(minStartDate)) {
minStartDate = startDate;
minfinYr = getMultiYearEstimates().get(i).getFinancialYear();
}
}
return minfinYr;
}
@Override
public String getStateDetails() {
return "Abstract Estimate : " + getEstimateNumber();
}
// @Required(message = "estimate.fund.null")
public Fundsource getFundSource() {
return fundSource;
}
public void setFundSource(final Fundsource fundSource) {
this.fundSource = fundSource;
}
public void setApproverUserId(final Integer approverUserId) {
this.approverUserId = approverUserId;
}
public Integer getApproverUserId() {
return approverUserId;
}
public String getPositionAndUserName() {
return positionAndUserName;
}
public void setPositionAndUserName(final String positionAndUserName) {
this.positionAndUserName = positionAndUserName;
}
public DepositCode getDepositCode() {
return depositCode;
}
public void setDepositCode(final DepositCode depositCode) {
this.depositCode = depositCode;
}
public String getCurrentStateCreatedDate() {
String createdDate = "";
if (getCurrentState() != null)
createdDate = new java.text.SimpleDateFormat("dd/MM/yyyy").format(getCurrentState().getCreatedDate());
return createdDate;
}
public List<AbstractEstimateAppropriation> getAbstractEstimateAppropriations() {
return abstractEstimateAppropriations;
}
public void setAbstractEstimateAppropriations(
final List<AbstractEstimateAppropriation> abstractEstimateAppropriations) {
this.abstractEstimateAppropriations = abstractEstimateAppropriations;
}
public AbstractEstimate getParent() {
return parent;
}
public void setParent(final AbstractEstimate parent) {
this.parent = parent;
}
public void setTotalAmount(final Money totalAmount) {
}
public Date getApprovedDate() {
return approvedDate;
}
public void setApprovedDate(final Date approvedDate) {
this.approvedDate = approvedDate;
}
public BigDecimal getLatitude() {
return latitude;
}
public BigDecimal getLongitude() {
return longitude;
}
public void setLatitude(final BigDecimal latitude) {
this.latitude = latitude;
}
public void setLongitude(final BigDecimal longitude) {
this.longitude = longitude;
}
@Override
public String toString() {
return "AbstractEstimate ( Id : " + getId() + "Estimate No: " + estimateNumber + ")";
}
public BigDecimal getEstimateValue() {
return estimateValue;
}
public void setEstimateValue(final BigDecimal estimateValue) {
this.estimateValue = estimateValue;
}
public LineEstimateDetails getLineEstimateDetails() {
return lineEstimateDetails;
}
public void setLineEstimateDetails(final LineEstimateDetails lineEstimateDetails) {
this.lineEstimateDetails = lineEstimateDetails;
}
public EgwStatus getEgwStatus() {
return egwStatus;
}
public void setEgwStatus(final EgwStatus egwStatus) {
this.egwStatus = egwStatus;
}
public boolean isCopiedEstimate() {
return copiedEstimate;
}
public void setCopiedEstimate(final boolean copiedEstimate) {
this.copiedEstimate = copiedEstimate;
}
public List<EstimateTechnicalSanction> getEstimateTechnicalSanctions() {
return estimateTechnicalSanctions;
}
public void setEstimateTechnicalSanctions(final List<EstimateTechnicalSanction> estimateTechnicalSanctions) {
this.estimateTechnicalSanctions = estimateTechnicalSanctions;
}
}