/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition 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; version 3 of the License.
//
// This community edition 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/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.humanresources;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Cascade;
import org.hibernate.search.annotations.ContainedIn;
import org.hibernate.search.annotations.DateBridge;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.annotations.Resolution;
import org.projectforge.calendar.DayHolder;
import org.projectforge.common.DateHelper;
import org.projectforge.core.DefaultBaseDO;
import org.projectforge.core.PFPersistancyBehavior;
import org.projectforge.fibu.ProjektDO;
import org.projectforge.user.PFUserDO;
import org.projectforge.web.calendar.DateTimeFormatter;
/**
*
* @author Mario Groß (m.gross@micromata.de)
*
*/
@Entity
@Indexed
@Table(name = "T_HR_PLANNING", uniqueConstraints = { @UniqueConstraint(columnNames = { "user_fk", "week"})})
public class HRPlanningDO extends DefaultBaseDO
{
private static final long serialVersionUID = 6413788186422319573L;
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(HRPlanningDO.class);
@IndexedEmbedded(depth = 1)
private PFUserDO user;
@Field(index = Index.UN_TOKENIZED)
@DateBridge(resolution = Resolution.DAY)
private Date week;
@PFPersistancyBehavior(autoUpdateCollectionEntries = true)
@ContainedIn
private List<HRPlanningEntryDO> entries;
/**
* @param date
* @return The first day of week (UTC). The first day of the week is monday (use Locale.GERMAN) because monday is the first working day of
* the week.
* @see DayHolder#setBeginOfWeek()
*/
public static final Date getFirstDayOfWeek(final Date date)
{
final DayHolder day = new DayHolder(date, DateHelper.UTC, Locale.GERMAN);
day.setBeginOfWeek();
return day.getSQLDate();
}
/**
* @param date
* @return The first day of week (UTC). The first day of the week is monday (use Locale.GERMAN) because monday is the first working day of
* the week.
* @see DayHolder#setBeginOfWeek()
*/
public static final Date getFirstDayOfWeek(final java.util.Date date)
{
final DayHolder day = new DayHolder(date, DateHelper.UTC, Locale.GERMAN);
day.setBeginOfWeek();
return day.getSQLDate();
}
/**
* @return The first day of the week.
*/
@Column(name = "week", nullable = false)
public Date getWeek()
{
return week;
}
/**
* @param week
*/
public void setWeek(final Date week)
{
this.week = week;
}
/**
* @param week
* @see #getFirstDayOfWeek(Date)
*/
public void setFirstDayOfWeek(final Date week)
{
this.week = getFirstDayOfWeek(week);
}
@Transient
public String getFormattedWeekOfYear()
{
return DateTimeFormatter.formatWeekOfYear(week);
}
/**
* The employee assigned to this planned week.
*
* @return the user
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_fk", nullable = false)
public PFUserDO getUser()
{
return user;
}
/**
* @param user the user to set
*/
public HRPlanningDO setUser(final PFUserDO user)
{
this.user = user;
return this;
}
@Transient
public Integer getUserId()
{
if (this.user == null)
return null;
return user.getId();
}
/**
* Get the entries for this planned week.
*/
@OneToMany(cascade = { CascadeType.ALL}, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "planning_fk")
@Cascade(value = org.hibernate.annotations.CascadeType.SAVE_UPDATE)
public List<HRPlanningEntryDO> getEntries()
{
return this.entries;
}
public void setEntries(final List<HRPlanningEntryDO> entries)
{
this.entries = entries;
}
public void addEntry(final HRPlanningEntryDO entry)
{
ensureAndGetEntries();
entry.setPlanning(this);
this.entries.add(entry);
}
/**
* Deletes the given entry from the list of entries if not already persisted. If the entry is already persisted then the entry will be
* marked as deleted. Undelete is possible by adding a entry with the same status/project again.
* @param entry
*/
public void deleteEntry(final HRPlanningEntryDO entry)
{
if (this.entries == null) {
log.error("Can't remove entry because the list of entries is null (do nothing): " + entry);
return;
}
if (entry.getId() == null) {
if (this.entries.remove(entry) == false) {
log.error("Can't remove entry because the list of entries does not contain such an entry: " + entry);
}
} else {
entry.setDeleted(true);
}
}
public List<HRPlanningEntryDO> ensureAndGetEntries()
{
if (this.entries == null) {
setEntries(new ArrayList<HRPlanningEntryDO>());
}
return getEntries();
}
/**
* @param idx
* @return HRPlanningEntryDO with given index or null, if not exist.
*/
public HRPlanningEntryDO getEntry(final int idx)
{
if (entries == null) {
return null;
}
if (idx >= entries.size()) { // Index out of bounds.
return null;
}
return entries.get(idx);
}
public HRPlanningEntryDO getProjectEntry(final ProjektDO project)
{
if (entries == null) {
return null;
}
for (final HRPlanningEntryDO entry : entries) {
if (project.getId().equals(entry.getProjektId()) == true) {
return entry;
}
}
return null;
}
public HRPlanningEntryDO getStatusEntry(final HRPlanningEntryStatus status)
{
if (entries == null) {
return null;
}
for (final HRPlanningEntryDO entry : entries) {
if (entry.getStatus() == status) {
return entry;
}
}
return null;
}
/**
* @return The total duration of all entries.
* @see HRPlanningEntryDO#getTotalHours()
*/
@Transient
public BigDecimal getTotalHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
if (entry.isDeleted() == false) {
duration = duration.add(entry.getTotalHours());
}
}
return duration;
}
private BigDecimal add(final BigDecimal sum, final BigDecimal value)
{
if (value == null) {
return sum;
} else {
return sum.add(value);
}
}
/**
* @return The total hours of all unassigned entries.
* @see HRPlanningEntryDO#getUnassignedHours()
*/
@Transient
public BigDecimal getTotalUnassignedHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getUnassignedHours());
}
return duration;
}
/**
* @return The total hours of all entries for Monday.
* @see HRPlanningEntryDO#getMondayHours()
*/
@Transient
public BigDecimal getTotalMondayHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getMondayHours());
}
return duration;
}
/**
* @return The total hours of all entries for Tuesday.
* @see HRPlanningEntryDO#getTuesdayHours()
*/
@Transient
public BigDecimal getTotalTuesdayHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getTuesdayHours());
}
return duration;
}
/**
* @return The total hours of all entries for Wednesday.
* @see HRPlanningEntryDO#getWednesdayHours()
*/
@Transient
public BigDecimal getTotalWednesdayHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getWednesdayHours());
}
return duration;
}
/**
* @return The total hours of all entries for Thursday.
* @see HRPlanningEntryDO#getThursdayHours()
*/
@Transient
public BigDecimal getTotalThursdayHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getThursdayHours());
}
return duration;
}
/**
* @return The total hours of all entries for Friday.
* @see HRPlanningEntryDO#getFridayHours()
*/
@Transient
public BigDecimal getTotalFridayHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getFridayHours());
}
return duration;
}
/**
* @return The total hours of all entries for weekend.
* @see HRPlanningEntryDO#getWeekendHours()
*/
@Transient
public BigDecimal getTotalWeekendHours()
{
BigDecimal duration = BigDecimal.ZERO;
if (entries == null) {
return duration;
}
for (final HRPlanningEntryDO entry : entries) {
duration = add(duration, entry.getWeekendHours());
}
return duration;
}
public boolean hasDeletedEntries()
{
if (this.entries == null) {
return false;
}
for (final HRPlanningEntryDO entry : this.entries) {
if (entry.isDeleted() == true) {
return true;
}
}
return false;
}
}