/*
* 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 2
* of the License, or (at your option) 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package net.rrm.ehour.report.reports.element;
import com.google.common.base.Optional;
import net.rrm.ehour.domain.ProjectAssignment;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.joda.time.Days;
import org.joda.time.LocalDateTime;
/**
* ReportElement for aggregate reports
*/
public class AssignmentAggregateReportElement implements Comparable<AssignmentAggregateReportElement>, ProjectStructuredReportElement {
private static final long serialVersionUID = -7175763322632066925L;
private ProjectAssignment projectAssignment;
private Number hours;
private Boolean emptyEntry;
public AssignmentAggregateReportElement() {
}
public AssignmentAggregateReportElement(ProjectAssignment projectAssignment, Number hours) {
this.hours = hours;
this.projectAssignment = projectAssignment;
}
public AssignmentAggregateReportElement(ProjectAssignment projectAssignment) {
this.emptyEntry = true;
this.projectAssignment = projectAssignment;
}
@Override
public Boolean isEmptyEntry() {
return emptyEntry == null ? false : emptyEntry;
}
/**
* Get the progress (booked hours) in percentage of the allotted hours, leaving out the overrun
* or for date ranges use the current date vs start & end date (if they're both null)
*/
public Optional<Float> getProgressPercentage() {
Optional<Float> percentage = Optional.absent();
if (projectAssignment == null) {
return Optional.absent();
}
if (projectAssignment.getAssignmentType().isAllottedType()) {
if (hours != null &&
projectAssignment.getAllottedHours() != null &&
hours.floatValue() > 0 &&
projectAssignment.getAllottedHours() > 0) {
percentage = Optional.of((hours.floatValue() / projectAssignment.getAllottedHours()) * 100);
}
} else if (projectAssignment.getAssignmentType().isDateType() &&
projectAssignment.getDateStart() != null &&
projectAssignment.getDateEnd() != null) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime start = new LocalDateTime(projectAssignment.getDateStart());
LocalDateTime end = new LocalDateTime(projectAssignment.getDateEnd());
if (now.isBefore(start)) {
percentage = Optional.of(0f);
} else if (now.isAfter(end)) {
percentage = Optional.of(100f);
} else {
float totalRange = Days.daysBetween(start, end).getDays();
float daysConsumed = Days.daysBetween(start, now).getDays();
percentage = Optional.of((daysConsumed / totalRange) * 100);
}
// if percentage is above 100 for daterange the user can't book anymore hours
// so don't display more than 100%
if (percentage.get() > 100) {
percentage = Optional.of(100f);
}
}
return percentage;
}
/**
* For flex/fixed allotted, give the available hours
*
* @return
*/
public Optional<Float> getAvailableHours() {
if (projectAssignment != null) {
if (projectAssignment.getAssignmentType().isFixedAllottedType()) {
if (hours != null &&
projectAssignment.getAllottedHours() != null &&
hours.floatValue() > 0 &&
projectAssignment.getAllottedHours() > 0) {
return Optional.of(projectAssignment.getAllottedHours() - hours.floatValue());
}
} else if (projectAssignment.getAssignmentType().isFlexAllottedType() && hours != null &&
projectAssignment.getAllottedHours() != null &&
hours.floatValue() > 0 &&
projectAssignment.getAllottedHours() > 0) {
return Optional.of((projectAssignment.getAllottedHours() +
((projectAssignment.getAllowedOverrun() != null) ? projectAssignment.getAllowedOverrun() : 0))
- hours.floatValue());
}
}
return Optional.absent();
}
public ProjectAssignment getProjectAssignment() {
return projectAssignment;
}
public void setProjectAssignment(ProjectAssignment projectAssignment) {
this.projectAssignment = projectAssignment;
}
public Number getTurnOver() {
if (projectAssignment != null && projectAssignment.getHourlyRate() != null && hours != null) {
return hours.floatValue() * projectAssignment.getHourlyRate();
} else {
return 0;
}
}
@Override
public int compareTo(AssignmentAggregateReportElement pagO) {
return this.getProjectAssignment().compareTo(pagO.getProjectAssignment());
}
@Override
public String toString() {
return new ToStringBuilder(this)
.append("ProjectAssignment", projectAssignment)
.append("hours", hours)
.toString();
}
public Number getHours() {
return hours == null ? 0 : hours;
}
public void setHours(Number hours) {
this.hours = hours;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof AssignmentAggregateReportElement)) {
return false;
}
AssignmentAggregateReportElement rhs = (AssignmentAggregateReportElement) object;
return new EqualsBuilder().appendSuper(super.equals(object)).append(this.projectAssignment, rhs.projectAssignment).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(259442803, 2067843191).appendSuper(super.hashCode()).append(this.projectAssignment).toHashCode();
}
@Override
public Integer getProjectId() {
return projectAssignment.getProject().getPK();
}
}