Merge branch 'personal-timesheets-periodicity'
This commit is contained in:
commit
be439d08d1
43 changed files with 887 additions and 373 deletions
|
|
@ -109,8 +109,9 @@ public class Configuration extends BaseEntity {
|
|||
private String currencyCode = "EUR";
|
||||
private String currencySymbol = "€";
|
||||
|
||||
private TypeOfWorkHours monthlyTimesheetsTypeOfWorkHours;
|
||||
private TypeOfWorkHours personalTimesheetsTypeOfWorkHours;
|
||||
|
||||
private PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity = PersonalTimesheetsPeriodicityEnum.MONTHLY;
|
||||
|
||||
public void setDefaultCalendar(BaseCalendar defaultCalendar) {
|
||||
this.defaultCalendar = defaultCalendar;
|
||||
|
|
@ -451,13 +452,22 @@ public class Configuration extends BaseEntity {
|
|||
this.currencySymbol = currencySymbol;
|
||||
}
|
||||
|
||||
public TypeOfWorkHours getMonthlyTimesheetsTypeOfWorkHours() {
|
||||
return monthlyTimesheetsTypeOfWorkHours;
|
||||
public TypeOfWorkHours getPersonalTimesheetsTypeOfWorkHours() {
|
||||
return personalTimesheetsTypeOfWorkHours;
|
||||
}
|
||||
|
||||
public void setMonthlyTimesheetsTypeOfWorkHours(
|
||||
public void setPersonalTimesheetsTypeOfWorkHours(
|
||||
TypeOfWorkHours typeOfWorkHours) {
|
||||
monthlyTimesheetsTypeOfWorkHours = typeOfWorkHours;
|
||||
personalTimesheetsTypeOfWorkHours = typeOfWorkHours;
|
||||
}
|
||||
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return personalTimesheetsPeriodicity;
|
||||
}
|
||||
|
||||
public void setPersonalTimesheetsPeriodicity(
|
||||
PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity) {
|
||||
this.personalTimesheetsPeriodicity = personalTimesheetsPeriodicity;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ package org.libreplan.business.common.entities;
|
|||
import org.libreplan.business.IDataBootstrap;
|
||||
|
||||
/**
|
||||
* Contract for {@link MonthlyTimesheetsTypeOfWorkHoursBootstrap}.
|
||||
* Contract for {@link PersonalTimesheetsTypeOfWorkHoursBootstrap}.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public interface IMonthlyTimesheetsTypeOfWorkHoursBootstrap extends
|
||||
public interface IPersonalTimesheetsTypeOfWorkHoursBootstrap extends
|
||||
IDataBootstrap {
|
||||
|
||||
void loadRequiredData();
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* This file is part of LibrePlan
|
||||
*
|
||||
* Copyright (C) 2012 Igalia, S.L.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.libreplan.business.common.entities;
|
||||
|
||||
import static org.libreplan.business.i18n.I18nHelper._;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.Months;
|
||||
import org.joda.time.Weeks;
|
||||
|
||||
/**
|
||||
* Different values for personal timesheets periodicity.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
*/
|
||||
public enum PersonalTimesheetsPeriodicityEnum {
|
||||
|
||||
MONTHLY(_("Monthly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
return date.dayOfMonth().withMaximumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Months.monthsBetween(start, end).getMonths();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
return fromDate.plusMonths(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
return getStart(date).minusMonths(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
return getStart(date).plusMonths(1);
|
||||
}
|
||||
},
|
||||
TWICE_MONTHLY(_("Twice-monthly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
} else {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(14);
|
||||
} else {
|
||||
return date.dayOfMonth().withMaximumValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Months.monthsBetween(start, end).getMonths() * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
int months = (item % 2 == 0) ? (item / 2) : ((item - 1) / 2);
|
||||
LocalDate date = fromDate.plusMonths(months);
|
||||
if (item % 2 != 0) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
date = date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
} else {
|
||||
date = date.plusMonths(1).dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.minusMonths(1).dayOfMonth().withMinimumValue()
|
||||
.plusDays(15);
|
||||
} else {
|
||||
return date.dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
if (date.getDayOfMonth() <= 15) {
|
||||
return date.dayOfMonth().withMinimumValue().plusDays(15);
|
||||
} else {
|
||||
return date.plusMonths(1).dayOfMonth().withMinimumValue();
|
||||
}
|
||||
}
|
||||
},
|
||||
WEEKLY(_("Weekly")) {
|
||||
@Override
|
||||
public LocalDate getStart(LocalDate date) {
|
||||
return date.dayOfWeek().withMinimumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getEnd(LocalDate date) {
|
||||
return date.dayOfWeek().withMaximumValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemsBetween(LocalDate start, LocalDate end) {
|
||||
return Weeks.weeksBetween(start, end).getWeeks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getDateForItemFromDate(int item, LocalDate fromDate) {
|
||||
return fromDate.plusWeeks(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate previous(LocalDate date) {
|
||||
return getStart(date).minusWeeks(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate next(LocalDate date) {
|
||||
return getStart(date).plusWeeks(1);
|
||||
}
|
||||
};
|
||||
|
||||
private String name;
|
||||
|
||||
private PersonalTimesheetsPeriodicityEnum(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start date of the personal timesheet which includes the
|
||||
* specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate getStart(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the end date of the personal timesheet which includes the
|
||||
* specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate getEnd(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the number of personal timesheets between the specified dates.
|
||||
*/
|
||||
public abstract int getItemsBetween(LocalDate start, LocalDate end);
|
||||
|
||||
/**
|
||||
* Returns the date of the personal timesheet in the position specified by
|
||||
* <code>item</code> taking into account the <code>fromDate</code>.
|
||||
*/
|
||||
public abstract LocalDate getDateForItemFromDate(int item,
|
||||
LocalDate fromDate);
|
||||
|
||||
/**
|
||||
* Returns the date of the previous personal timesheet to the one which
|
||||
* includes the specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate previous(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the date of the next personal timesheet to the one which includes
|
||||
* the specified <code>date</code>.
|
||||
*/
|
||||
public abstract LocalDate next(LocalDate date);
|
||||
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Fills the attribute {@link Configuration#monthlyTimesheetsTypeOfWorkHours}
|
||||
* Fills the attribute {@link Configuration#personalTimesheetsTypeOfWorkHours}
|
||||
* with a default value.<br />
|
||||
*
|
||||
* If possible it uses the "Default" {@link TypeOfWorkHours}, but if it doesn't
|
||||
|
|
@ -47,8 +47,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Component
|
||||
@Scope("singleton")
|
||||
@BootstrapOrder(1)
|
||||
public class MonthlyTimesheetsTypeOfWorkHoursBootstrap implements
|
||||
IMonthlyTimesheetsTypeOfWorkHoursBootstrap {
|
||||
public class PersonalTimesheetsTypeOfWorkHoursBootstrap implements
|
||||
IPersonalTimesheetsTypeOfWorkHoursBootstrap {
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
|
@ -73,7 +73,7 @@ public class MonthlyTimesheetsTypeOfWorkHoursBootstrap implements
|
|||
typeOfWorkHours = typeOfWorkHoursDAO.findActive().get(0);
|
||||
}
|
||||
|
||||
configuration.setMonthlyTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configuration.setPersonalTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configurationDAO.save(configuration);
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ public class TypeOfWorkHoursDAO extends IntegrationEntityDAO<TypeOfWorkHours>
|
|||
public void checkIsReferencedByOtherEntities(TypeOfWorkHours type) throws ValidationException {
|
||||
checkHasHourCost(type);
|
||||
checkHasWorkReportLine(type);
|
||||
checkIsMonthlyTimesheetsTypeOfWorkHours(type);
|
||||
checkIsPersonalTimesheetsTypeOfWorkHours(type);
|
||||
}
|
||||
|
||||
private void checkHasWorkReportLine(TypeOfWorkHours type) {
|
||||
|
|
@ -174,13 +174,13 @@ public class TypeOfWorkHoursDAO extends IntegrationEntityDAO<TypeOfWorkHours>
|
|||
}
|
||||
}
|
||||
|
||||
private void checkIsMonthlyTimesheetsTypeOfWorkHours(TypeOfWorkHours type) {
|
||||
private void checkIsPersonalTimesheetsTypeOfWorkHours(TypeOfWorkHours type) {
|
||||
Configuration configuration = configurationDAO.getConfiguration();
|
||||
if (configuration.getMonthlyTimesheetsTypeOfWorkHours().getId()
|
||||
if (configuration.getPersonalTimesheetsTypeOfWorkHours().getId()
|
||||
.equals(type.getId())) {
|
||||
throw ValidationException
|
||||
.invalidValue(
|
||||
"Cannot delete the type of work hours. It is configured as type of work hours for monthly timesheets.",
|
||||
"Cannot delete the type of work hours. It is configured as type of work hours for personal timesheets.",
|
||||
type);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,11 +143,11 @@ public class TypeOfWorkHours extends IntegrationEntity implements IHumanIdentifi
|
|||
}
|
||||
}
|
||||
|
||||
@AssertTrue(message = "type of work hours for monthly timesheets cannot be disabled")
|
||||
public boolean checkMonthlyTimesheetsTypeOfWorkHoursNotDisabled() {
|
||||
@AssertTrue(message = "type of work hours for personal timesheets cannot be disabled")
|
||||
public boolean checkPersonalTimesheetsTypeOfWorkHoursNotDisabled() {
|
||||
if (!isNewObject() && !getEnabled()) {
|
||||
TypeOfWorkHours typeOfWorkHours = Registry.getConfigurationDAO()
|
||||
.getConfiguration().getMonthlyTimesheetsTypeOfWorkHours();
|
||||
.getConfiguration().getPersonalTimesheetsTypeOfWorkHours();
|
||||
if (typeOfWorkHours.getId().equals(getId())) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.common.daos.IIntegrationEntityDAO;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.resources.entities.Resource;
|
||||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
import org.libreplan.business.workreports.entities.WorkReportType;
|
||||
|
|
@ -47,11 +48,15 @@ public interface IWorkReportDAO extends IIntegrationEntityDAO<WorkReport> {
|
|||
int getLastReportYear();
|
||||
|
||||
/**
|
||||
* Returns the {@link WorkReport} of the predefined type monthly timesheet
|
||||
* for the given <code>resource</code> in the specified <code>date</code>.<br />
|
||||
* Returns the {@link WorkReport} of the predefined type personal timesheet
|
||||
* for the given <code>resource</code> in the specified <code>date</code>
|
||||
* depending on the configured <code>periodicity</code>.<br />
|
||||
*
|
||||
* If there isn't any, it returns <code>null</code>.
|
||||
*/
|
||||
WorkReport getMonthlyTimesheetWorkReport(Resource resource, LocalDate date);
|
||||
WorkReport getPersonalTimesheetWorkReport(Resource resource, LocalDate date,
|
||||
PersonalTimesheetsPeriodicityEnum periodicity);
|
||||
|
||||
boolean isAnyPersonalTimesheetAlreadySaved();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.joda.time.LocalDate;
|
|||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.business.common.daos.IntegrationEntityDAO;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.orders.daos.IOrderDAO;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
|
|
@ -140,12 +141,12 @@ public class WorkReportDAO extends IntegrationEntityDAO<WorkReport>
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public WorkReport getMonthlyTimesheetWorkReport(Resource resource,
|
||||
LocalDate date) {
|
||||
public WorkReport getPersonalTimesheetWorkReport(Resource resource,
|
||||
LocalDate date, PersonalTimesheetsPeriodicityEnum periodicity) {
|
||||
WorkReportType workReportType;
|
||||
try {
|
||||
workReportType = workReportTypeDAO
|
||||
.findUniqueByName(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS
|
||||
.findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName());
|
||||
} catch (NonUniqueResultException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -155,17 +156,21 @@ public class WorkReportDAO extends IntegrationEntityDAO<WorkReport>
|
|||
|
||||
Criteria criteria = getSession().createCriteria(WorkReport.class);
|
||||
criteria.add(Restrictions.eq("workReportType", workReportType));
|
||||
List<WorkReport> monthlyTimesheets = criteria.add(
|
||||
List<WorkReport> personalTimesheets = criteria.add(
|
||||
Restrictions.eq("resource", resource)).list();
|
||||
|
||||
for (WorkReport workReport : monthlyTimesheets) {
|
||||
LocalDate start = periodicity.getStart(date);
|
||||
LocalDate end = periodicity.getEnd(date);
|
||||
|
||||
for (WorkReport workReport : personalTimesheets) {
|
||||
Set<WorkReportLine> workReportLines = workReport
|
||||
.getWorkReportLines();
|
||||
if (workReportLines.size() > 0) {
|
||||
Date workReportDate = workReportLines.iterator().next()
|
||||
.getDate();
|
||||
if (LocalDate.fromDateFields(workReportDate).monthOfYear()
|
||||
.equals(date.monthOfYear())) {
|
||||
LocalDate workReportDate = LocalDate
|
||||
.fromDateFields(workReportLines.iterator().next()
|
||||
.getDate());
|
||||
if (workReportDate.compareTo(start) >= 0
|
||||
&& workReportDate.compareTo(end) <= 0) {
|
||||
return workReport;
|
||||
}
|
||||
}
|
||||
|
|
@ -174,4 +179,22 @@ public class WorkReportDAO extends IntegrationEntityDAO<WorkReport>
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyPersonalTimesheetAlreadySaved() {
|
||||
WorkReportType workReportType;
|
||||
try {
|
||||
workReportType = workReportTypeDAO
|
||||
.findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName());
|
||||
} catch (NonUniqueResultException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Criteria criteria = getSession().createCriteria(WorkReport.class);
|
||||
criteria.add(Restrictions.eq("workReportType", workReportType));
|
||||
return criteria.list().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ package org.libreplan.business.workreports.entities;
|
|||
*/
|
||||
public enum PredefinedWorkReportTypes {
|
||||
DEFAULT("Default", false, false, false),
|
||||
MONTHLY_TIMESHEETS("Monthly timesheets", false, true, false);
|
||||
PERSONAL_TIMESHEETS("Personal timesheets", false, true, false);
|
||||
|
||||
private WorkReportType workReportType;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ import org.hibernate.validator.AssertTrue;
|
|||
import org.hibernate.validator.NotNull;
|
||||
import org.hibernate.validator.Valid;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.LocalDate.Property;
|
||||
import org.libreplan.business.common.IntegrationEntity;
|
||||
import org.libreplan.business.common.Registry;
|
||||
import org.libreplan.business.common.entities.EntitySequence;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.labels.entities.Label;
|
||||
import org.libreplan.business.labels.entities.LabelType;
|
||||
|
|
@ -470,9 +470,9 @@ public class WorkReport extends IntegrationEntity implements
|
|||
return result;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "only one timesheet line per day and task is allowed in monthly timesheets")
|
||||
public boolean checkConstraintOnlyOneWorkReportLinePerDayAndOrderElementInMonthlyTimesheet() {
|
||||
if (!getWorkReportType().isMonthlyTimesheetsType()) {
|
||||
@AssertTrue(message = "only one timesheet line per day and task is allowed in personal timesheets")
|
||||
public boolean checkConstraintOnlyOneWorkReportLinePerDayAndOrderElementInPersonalTimesheet() {
|
||||
if (!getWorkReportType().isPersonalTimesheetsType()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -492,9 +492,9 @@ public class WorkReport extends IntegrationEntity implements
|
|||
return true;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "In monthly timesheets, all timesheet lines should be in the same month")
|
||||
public boolean checkConstraintAllWorkReportLinesInTheSameMonthInMonthlyTimesheet() {
|
||||
if (!getWorkReportType().isMonthlyTimesheetsType()) {
|
||||
@AssertTrue(message = "In personal timesheets, all timesheet lines should be in the same period")
|
||||
public boolean checkConstraintAllWorkReportLinesInTheSamePeriodInPersonalTimesheet() {
|
||||
if (!getWorkReportType().isPersonalTimesheetsType()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -502,10 +502,14 @@ public class WorkReport extends IntegrationEntity implements
|
|||
return true;
|
||||
}
|
||||
|
||||
Property dayOfMonth = LocalDate.fromDateFields(
|
||||
workReportLines.iterator().next().getDate()).dayOfMonth();
|
||||
LocalDate min = dayOfMonth.withMinimumValue();
|
||||
LocalDate max = dayOfMonth.withMaximumValue();
|
||||
LocalDate workReportDate = LocalDate.fromDateFields(workReportLines
|
||||
.iterator().next().getDate());
|
||||
PersonalTimesheetsPeriodicityEnum periodicity = Registry
|
||||
.getConfigurationDAO()
|
||||
.getConfigurationWithReadOnlyTransaction()
|
||||
.getPersonalTimesheetsPeriodicity();
|
||||
LocalDate min = periodicity.getStart(workReportDate);
|
||||
LocalDate max = periodicity.getEnd(workReportDate);
|
||||
|
||||
for (WorkReportLine line : workReportLines) {
|
||||
LocalDate date = LocalDate.fromDateFields(line.getDate());
|
||||
|
|
@ -516,9 +520,9 @@ public class WorkReport extends IntegrationEntity implements
|
|||
return true;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "resource has to be bound to a user in monthly timesheets")
|
||||
public boolean checkConstraintResourceIsBoundInMonthlyTimesheet() {
|
||||
if (!getWorkReportType().isMonthlyTimesheetsType()) {
|
||||
@AssertTrue(message = "resource has to be bound to a user in personal timesheets")
|
||||
public boolean checkConstraintResourceIsBoundInPersonalTimesheet() {
|
||||
if (!getWorkReportType().isPersonalTimesheetsType()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -524,11 +524,11 @@ public class WorkReportType extends IntegrationEntity implements IHumanIdentifia
|
|||
return name;
|
||||
}
|
||||
|
||||
public boolean isMonthlyTimesheetsType() {
|
||||
public boolean isPersonalTimesheetsType() {
|
||||
if (StringUtils.isBlank(name)) {
|
||||
return false;
|
||||
}
|
||||
return name.equals(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS
|
||||
return name.equals(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
* If there is no work report types, it creates a default work report type.<br />
|
||||
*
|
||||
* Even if there are already some work report types defined, it creates a work
|
||||
* report type for monthly timesheets if it is not present in the database yet.
|
||||
* report type for personal timesheets if it is not present in the database yet.
|
||||
*
|
||||
* @author Ignacio Díaz Teijido <ignacio.diaz@cafedered.com>
|
||||
* @author Manuel Rego Casasnovas <rego@igalia.com>
|
||||
|
|
@ -59,7 +59,7 @@ public class WorkReportTypeBootstrap implements IWorkReportTypeBootstrap {
|
|||
createAndSaveWorkReportType(predefinedWorkReportType);
|
||||
}
|
||||
} else {
|
||||
createMonthlyTimesheetsWorkReportTypeIfNeeded();
|
||||
createPersonalTimesheetsWorkReportTypeIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,15 +74,15 @@ public class WorkReportTypeBootstrap implements IWorkReportTypeBootstrap {
|
|||
workReportTypeDAO.save(workReportType);
|
||||
}
|
||||
|
||||
private void createMonthlyTimesheetsWorkReportTypeIfNeeded() {
|
||||
private void createPersonalTimesheetsWorkReportTypeIfNeeded() {
|
||||
try {
|
||||
workReportTypeDAO
|
||||
.findUniqueByName(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS
|
||||
.findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName());
|
||||
} catch (NonUniqueResultException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
createAndSaveWorkReportType(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS);
|
||||
createAndSaveWorkReportType(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,4 +16,44 @@
|
|||
<sql>ALTER TABLE task_element MODIFY notes TEXT</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
<changeSet id="update-work_report_type-name-to-personal-timehseets"
|
||||
author="mrego">
|
||||
<comment>
|
||||
Update work_report_type name from "Monthly timesheets" to "Personal
|
||||
timehsheets"
|
||||
</comment>
|
||||
<update tableName="work_report_type">
|
||||
<column name="name" value="Personal timesheets"/>
|
||||
<where>name='Monthly timesheets'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="add-personal_timesheets_periodicity-column-to-configuration"
|
||||
author="mrego">
|
||||
<comment>Add personal_timesheets_periodicity column to configuration</comment>
|
||||
<addColumn tableName="configuration">
|
||||
<column name="personal_timesheets_periodicity" type="INTEGER" />
|
||||
</addColumn>
|
||||
<update tableName="configuration">
|
||||
<column name="personal_timesheets_periodicity" value="0" />
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="rename-column-from-monthly-to-personal-in-configuration"
|
||||
author="mrego">
|
||||
<comment>
|
||||
Rename column monthly_timesheets_type_of_work_hours to
|
||||
personal_timesheets_type_of_work_hours in configuration table
|
||||
</comment>
|
||||
<dropForeignKeyConstraint baseTableName="configuration"
|
||||
constraintName="configuration_type_of_work_hours_fkey"/>
|
||||
<renameColumn tableName="configuration"
|
||||
oldColumnName="monthly_timesheets_type_of_work_hours"
|
||||
newColumnName="personal_timesheets_type_of_work_hours"
|
||||
columnDataType="BIGINT" />
|
||||
<addForeignKeyConstraint constraintName="configuration_type_of_work_hours_fkey"
|
||||
baseTableName="configuration" baseColumnNames="personal_timesheets_type_of_work_hours"
|
||||
referencedTableName="type_of_work_hours" referencedColumnNames="id" />
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
|
|
|||
|
|
@ -79,8 +79,14 @@
|
|||
<property name="currencyCode" not-null="true" column="currency_code" />
|
||||
<property name="currencySymbol" not-null="true" column="currency_symbol" />
|
||||
|
||||
<many-to-one name="monthlyTimesheetsTypeOfWorkHours" cascade="none"
|
||||
column="monthly_timesheets_type_of_work_hours" />
|
||||
<many-to-one name="personalTimesheetsTypeOfWorkHours" cascade="none"
|
||||
column="personal_timesheets_type_of_work_hours" />
|
||||
|
||||
<property name="personalTimesheetsPeriodicity" column="personal_timesheets_periodicity">
|
||||
<type name="org.hibernate.type.EnumType">
|
||||
<param name="enumClass">org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum</param>
|
||||
</type>
|
||||
</property>
|
||||
|
||||
<component name="ldapConfiguration" class="org.libreplan.business.common.entities.LDAPConfiguration">
|
||||
<property name="ldapHost" column="ldap_host"/>
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.libreplan.business.common.entities.Configuration;
|
|||
import org.libreplan.business.common.entities.EntityNameEnum;
|
||||
import org.libreplan.business.common.entities.EntitySequence;
|
||||
import org.libreplan.business.common.entities.LDAPConfiguration;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.entities.ProgressType;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
|
|
@ -869,13 +870,49 @@ public class ConfigurationController extends GenericForwardComposer {
|
|||
configurationModel.setCurrency(currencyCode);
|
||||
}
|
||||
|
||||
public TypeOfWorkHours getMonthlyTimesheetsTypeOfWorkHours() {
|
||||
return configurationModel.getMonthlyTimesheetsTypeOfWorkHours();
|
||||
public TypeOfWorkHours getPersonalTimesheetsTypeOfWorkHours() {
|
||||
return configurationModel.getPersonalTimesheetsTypeOfWorkHours();
|
||||
}
|
||||
|
||||
public void setMonthlyTimesheetsTypeOfWorkHours(
|
||||
public void setPersonalTimesheetsTypeOfWorkHours(
|
||||
TypeOfWorkHours typeOfWorkHours) {
|
||||
configurationModel.setMonthlyTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configurationModel.setPersonalTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
}
|
||||
|
||||
public List<PersonalTimesheetsPeriodicityEnum> getPersonalTimesheetsPeriodicities() {
|
||||
return Arrays.asList(PersonalTimesheetsPeriodicityEnum.values());
|
||||
}
|
||||
|
||||
public ListitemRenderer getPersonalTimesheetsPeriodicityRenderer() {
|
||||
return new ListitemRenderer() {
|
||||
@Override
|
||||
public void render(Listitem item, Object data) throws Exception {
|
||||
PersonalTimesheetsPeriodicityEnum periodicity = (PersonalTimesheetsPeriodicityEnum) data;
|
||||
item.setLabel(_(periodicity.getName()));
|
||||
item.setValue(periodicity);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public PersonalTimesheetsPeriodicityEnum getSelectedPersonalTimesheetsPeriodicity() {
|
||||
return configurationModel.getPersonalTimesheetsPeriodicity();
|
||||
}
|
||||
|
||||
public void setSelectedPersonalTimesheetsPeriodicity(
|
||||
PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity) {
|
||||
configurationModel
|
||||
.setPersonalTimesheetsPeriodicity(personalTimesheetsPeriodicity);
|
||||
}
|
||||
|
||||
public boolean isPersonalTimesheetsPeriodicityDisabled() {
|
||||
return configurationModel.isAnyPersonalTimesheetAlreadySaved();
|
||||
}
|
||||
|
||||
public String getPersonalTimesheetsPeriodicityTooltip() {
|
||||
if (isPersonalTimesheetsPeriodicityDisabled()) {
|
||||
return _("Periocity cannot be changed because there is already any personal timesheet stored");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,10 +43,12 @@ import org.libreplan.business.common.entities.Configuration;
|
|||
import org.libreplan.business.common.entities.EntityNameEnum;
|
||||
import org.libreplan.business.common.entities.EntitySequence;
|
||||
import org.libreplan.business.common.entities.LDAPConfiguration;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.entities.ProgressType;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportDAO;
|
||||
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
|
@ -82,6 +84,9 @@ public class ConfigurationModel implements IConfigurationModel {
|
|||
@Autowired
|
||||
private IEntitySequenceDAO entitySequenceDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportDAO workReportDAO;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<BaseCalendar> getCalendars() {
|
||||
|
|
@ -132,7 +137,7 @@ public class ConfigurationModel implements IConfigurationModel {
|
|||
|
||||
private void forceLoad(Configuration configuration) {
|
||||
forceLoad(configuration.getDefaultCalendar());
|
||||
forceLoad(configuration.getMonthlyTimesheetsTypeOfWorkHours());
|
||||
forceLoad(configuration.getPersonalTimesheetsTypeOfWorkHours());
|
||||
}
|
||||
|
||||
private void forceLoad(BaseCalendar calendar) {
|
||||
|
|
@ -622,16 +627,34 @@ public class ConfigurationModel implements IConfigurationModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TypeOfWorkHours getMonthlyTimesheetsTypeOfWorkHours() {
|
||||
return configuration.getMonthlyTimesheetsTypeOfWorkHours();
|
||||
public TypeOfWorkHours getPersonalTimesheetsTypeOfWorkHours() {
|
||||
return configuration.getPersonalTimesheetsTypeOfWorkHours();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMonthlyTimesheetsTypeOfWorkHours(
|
||||
public void setPersonalTimesheetsTypeOfWorkHours(
|
||||
TypeOfWorkHours typeOfWorkHours) {
|
||||
if (configuration != null) {
|
||||
configuration.setMonthlyTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
configuration.setPersonalTimesheetsTypeOfWorkHours(typeOfWorkHours);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return configuration.getPersonalTimesheetsPeriodicity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersonalTimesheetsPeriodicity(
|
||||
PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity) {
|
||||
configuration
|
||||
.setPersonalTimesheetsPeriodicity(personalTimesheetsPeriodicity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isAnyPersonalTimesheetAlreadySaved() {
|
||||
return !workReportDAO.isAnyPersonalTimesheetAlreadySaved();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import org.libreplan.business.calendars.entities.BaseCalendar;
|
|||
import org.libreplan.business.common.entities.EntityNameEnum;
|
||||
import org.libreplan.business.common.entities.EntitySequence;
|
||||
import org.libreplan.business.common.entities.LDAPConfiguration;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.entities.ProgressType;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
|
||||
|
|
@ -168,8 +169,15 @@ public interface IConfigurationModel {
|
|||
|
||||
void setCurrency(String currencyCode);
|
||||
|
||||
TypeOfWorkHours getMonthlyTimesheetsTypeOfWorkHours();
|
||||
TypeOfWorkHours getPersonalTimesheetsTypeOfWorkHours();
|
||||
|
||||
void setMonthlyTimesheetsTypeOfWorkHours(TypeOfWorkHours typeOfWorkHours);
|
||||
void setPersonalTimesheetsTypeOfWorkHours(TypeOfWorkHours typeOfWorkHours);
|
||||
|
||||
PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity();
|
||||
|
||||
void setPersonalTimesheetsPeriodicity(
|
||||
PersonalTimesheetsPeriodicityEnum personalTimesheetsPeriodicity);
|
||||
|
||||
boolean isAnyPersonalTimesheetAlreadySaved();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ package org.libreplan.web.users.dashboard;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.libreplan.business.common.entities.Configuration;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
import org.libreplan.business.planner.entities.TaskElement;
|
||||
|
|
@ -40,4 +42,10 @@ public interface IMyTasksAreaModel {
|
|||
*/
|
||||
List<Task> getTasks();
|
||||
|
||||
/**
|
||||
* Returns the {@link PersonalTimesheetsPeriodicityEnum} from
|
||||
* {@link Configuration}.
|
||||
*/
|
||||
PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ import org.libreplan.web.common.entrypoints.EntryPoint;
|
|||
import org.libreplan.web.common.entrypoints.EntryPoints;
|
||||
|
||||
/**
|
||||
* Entry points for monthly timesheet creation/edition window
|
||||
* Entry points for personal timesheet creation/edition window
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@EntryPoints(page = "/myaccount/monthlyTimesheet.zul", registerAs = "monthlyTimesheetController")
|
||||
public interface IMonthlyTimesheetController {
|
||||
@EntryPoints(page = "/myaccount/personalTimesheet.zul", registerAs = "personalTimesheetController")
|
||||
public interface IPersonalTimesheetController {
|
||||
|
||||
@EntryPoint("date")
|
||||
void goToCreateOrEditForm(LocalDate date);
|
||||
|
|
@ -22,6 +22,8 @@ package org.libreplan.web.users.dashboard;
|
|||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.common.entities.Configuration;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.resources.entities.Resource;
|
||||
|
|
@ -30,40 +32,38 @@ import org.libreplan.business.workingday.EffortDuration;
|
|||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
|
||||
/**
|
||||
* Interface for creation/edition of a monthly timesheet model
|
||||
* Interface for creation/edition of a personal timesheet model
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public interface IMonthlyTimesheetModel {
|
||||
public interface IPersonalTimesheetModel {
|
||||
|
||||
/**
|
||||
* Edits the monthly timesheet for the specified <code>date</code> and
|
||||
* Edits the personal timesheet for the specified <code>date</code> and
|
||||
* resource bound to current user or creates a new one if it doesn't exist
|
||||
* yet.
|
||||
*/
|
||||
void initCreateOrEdit(LocalDate date);
|
||||
|
||||
/**
|
||||
* Edits the monthly timesheet for the specified <code>date</code> and
|
||||
* Edits the personal timesheet for the specified <code>date</code> and
|
||||
* resource bound to the {@link Worker} specified by the
|
||||
* <code>resource</code> or creates a new one if it doesn't exist yet.
|
||||
*/
|
||||
void initCreateOrEdit(LocalDate date, Resource resource);
|
||||
|
||||
/**
|
||||
* Returns the date of the monthly timesheet (only year and month should
|
||||
* take into account as the day is not important to define a monthly
|
||||
* timesheet).
|
||||
* Returns the date of the personal timesheet.
|
||||
*/
|
||||
LocalDate getDate();
|
||||
|
||||
/**
|
||||
* Returns the first day of the month of the current monthly timesheet.
|
||||
* Returns the first day of the current personal timesheet.
|
||||
*/
|
||||
LocalDate getFirstDay();
|
||||
|
||||
/**
|
||||
* Returns the last day of the month of the current monthly timesheet.
|
||||
* Returns the last day of the current personal timesheet.
|
||||
*/
|
||||
LocalDate getLastDate();
|
||||
|
||||
|
|
@ -79,45 +79,45 @@ public interface IMonthlyTimesheetModel {
|
|||
List<OrderElement> getOrderElements();
|
||||
|
||||
/**
|
||||
* Returns the {@link EffortDuration} in the current monthly timesheet for
|
||||
* Returns the {@link EffortDuration} in the current personal timesheet for
|
||||
* the specified <code>orderElement</code> and <code>date</code>.
|
||||
*/
|
||||
EffortDuration getEffortDuration(OrderElement orderElement, LocalDate date);
|
||||
|
||||
/**
|
||||
* Sets the {@link EffortDuration} in the current monthly timesheet for the
|
||||
* Sets the {@link EffortDuration} in the current personal timesheet for the
|
||||
* specified <code>orderElement</code> and <code>date</code>.<br />
|
||||
*
|
||||
* Marks the current monthly timesheet as modified.
|
||||
* Marks the current personal timesheet as modified.
|
||||
*/
|
||||
void setEffortDuration(OrderElement orderElement, LocalDate date,
|
||||
EffortDuration effortDuration);
|
||||
|
||||
/**
|
||||
* Save {@link WorkReport} for the monthly timesheet.
|
||||
* Save {@link WorkReport} for the personal timesheet.
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Cancel changes in {@link WorkReport} for the monthly timesheet.
|
||||
* Cancel changes in {@link WorkReport} for the personal timesheet.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Returns the {@link EffortDuration} in the current monthly timesheet for
|
||||
* Returns the {@link EffortDuration} in the current personal timesheet for
|
||||
* the specified <code>orderElement</code>.
|
||||
*/
|
||||
EffortDuration getEffortDuration(OrderElement orderElement);
|
||||
|
||||
/**
|
||||
* Returns the {@link EffortDuration} for all the {@link OrderElement
|
||||
* OrderElements} in the current monthly timesheet in the specified
|
||||
* OrderElements} in the current personal timesheet in the specified
|
||||
* <code>date</code>.
|
||||
*/
|
||||
EffortDuration getEffortDuration(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the total {@link EffortDuration} for the currently monthly
|
||||
* Returns the total {@link EffortDuration} for the currently personal
|
||||
* timesheet.
|
||||
*/
|
||||
EffortDuration getTotalEffortDuration();
|
||||
|
|
@ -129,7 +129,7 @@ public interface IMonthlyTimesheetModel {
|
|||
EffortDuration getResourceCapacity(LocalDate date);
|
||||
|
||||
/**
|
||||
* Adds the <code>orderElement</code> to the current monthly timehseet.
|
||||
* Adds the <code>orderElement</code> to the current personal timehseet.
|
||||
*/
|
||||
void addOrderElement(OrderElement orderElement);
|
||||
|
||||
|
|
@ -140,22 +140,22 @@ public interface IMonthlyTimesheetModel {
|
|||
Order getOrder(OrderElement orderElement);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if current monthly timesheet has been modified
|
||||
* Returns <code>true</code> if current personal timesheet has been modified
|
||||
* by the user.
|
||||
*/
|
||||
boolean isModified();
|
||||
|
||||
/**
|
||||
* Checks if current monthly timesheet is the first month, that means the
|
||||
* Checks if current personal timesheet is the first period, that means the
|
||||
* first activation period of the resource.
|
||||
*/
|
||||
boolean isFirstMonth();
|
||||
boolean isFirstPeriod();
|
||||
|
||||
/**
|
||||
* Checks if current monthly timesheet is the last month, that means the
|
||||
* Checks if current personal timesheet is the last period, that means the
|
||||
* next month of current date.
|
||||
*/
|
||||
boolean isLastMonth();
|
||||
boolean isLastPeriod();
|
||||
|
||||
/**
|
||||
* Returns true if the value for the specified <code>orderElement</code> in
|
||||
|
|
@ -165,7 +165,7 @@ public interface IMonthlyTimesheetModel {
|
|||
|
||||
/**
|
||||
* Returns <code>true</code> or <code>false</code> depending on if it's
|
||||
* editing a monthly timesheet of the current user or not.<br />
|
||||
* editing a personal timesheet of the current user or not.<br />
|
||||
*
|
||||
* That means if you entered via:
|
||||
* <ul>
|
||||
|
|
@ -177,30 +177,54 @@ public interface IMonthlyTimesheetModel {
|
|||
boolean isCurrentUser();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the resource of the current monthly
|
||||
* Returns <code>true</code> if the resource of the current personal
|
||||
* timesheet has any effort reported in other {@link WorkReport WorkReports}
|
||||
* in the month of the timesheet.
|
||||
* in the period of the timesheet.
|
||||
*/
|
||||
boolean hasOtherReports();
|
||||
|
||||
/**
|
||||
* Returns the {@link EffortDuration} of the specified
|
||||
* <code>orderElement</code> from other {@link WorkReport WorkReports} for
|
||||
* the current resource in the month of the timesheet.<br />
|
||||
* the current resource in the period of the timesheet.<br />
|
||||
*/
|
||||
EffortDuration getOtherEffortDuration(OrderElement orderElement);
|
||||
|
||||
/**
|
||||
* Returns the {@link EffortDuration} in the specified <code>date</code>
|
||||
* from other {@link WorkReport WorkReports} for the current resource in the
|
||||
* month of the timesheet.
|
||||
* period of the timesheet.
|
||||
*/
|
||||
EffortDuration getOtherEffortDuration(LocalDate date);
|
||||
|
||||
/**
|
||||
* Returns the total {@link EffortDuration} from other {@link WorkReport
|
||||
* WorkReports} for the current resource in the month of the timesheet.
|
||||
* WorkReports} for the current resource in the period of the timesheet.
|
||||
*/
|
||||
EffortDuration getTotalOtherEffortDuration();
|
||||
|
||||
/**
|
||||
* Returns the {@link PersonalTimesheetsPeriodicityEnum} from
|
||||
* {@link Configuration}.
|
||||
*/
|
||||
PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity();
|
||||
|
||||
/**
|
||||
* Returns the string that represents the personal timesheet depending on
|
||||
* the configured periodicity.
|
||||
*/
|
||||
String getTimesheetString();
|
||||
|
||||
/**
|
||||
* Returns the previous personal timesheet to the current one depending on
|
||||
* the configured periodicity.
|
||||
*/
|
||||
LocalDate getPrevious();
|
||||
|
||||
/**
|
||||
* Returns the next personal timesheet to the current one depending on the
|
||||
* configured periodicity.
|
||||
*/
|
||||
LocalDate getNext();
|
||||
|
||||
}
|
||||
|
|
@ -22,30 +22,31 @@ package org.libreplan.web.users.dashboard;
|
|||
import java.util.List;
|
||||
|
||||
import org.libreplan.business.calendars.entities.CalendarAvailability;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.users.entities.User;
|
||||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
|
||||
/**
|
||||
* Interface for "Monthly timesheets" area model
|
||||
* Interface for "Personal timesheets" area model
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public interface IMonthlyTimesheetsAreaModel {
|
||||
public interface IPersonalTimesheetsAreaModel {
|
||||
|
||||
/**
|
||||
* Returns the list of {@link MonthlyTimesheetDTO MonthlyTimesheets} for the
|
||||
* resource bound to current {@link User}.<br />
|
||||
* Returns the list of {@link PersonalTimesheetDTO PersonalTimesheetDTOs}
|
||||
* for the resource bound to current {@link User}.<br />
|
||||
*
|
||||
* There's no need that a {@link WorkReport} is saved in order to a
|
||||
* {@link MonthlyTimesheetDTO} exists for a month.<br />
|
||||
* {@link PersonalTimesheetDTO} exists for a period.<br />
|
||||
*
|
||||
* The list of {@link MonthlyTimesheetDTO MonthlyTimesheets} will be since the
|
||||
* date the resource is activated in the system (checking
|
||||
* The list of {@link PersonalTimesheetDTO PersonalTimesheetDTOs} will be
|
||||
* since the date the resource is activated in the system (checking
|
||||
* {@link CalendarAvailability} for the resource) to next month of current
|
||||
* date.
|
||||
*/
|
||||
List<MonthlyTimesheetDTO> getMonthlyTimesheets();
|
||||
List<PersonalTimesheetDTO> getPersonalTimesheets();
|
||||
|
||||
/**
|
||||
* Returns the number of different {@link OrderElement OrderElements} with
|
||||
|
|
@ -53,4 +54,9 @@ public interface IMonthlyTimesheetsAreaModel {
|
|||
*/
|
||||
int getNumberOfOrderElementsWithTrackedTime(WorkReport workReport);
|
||||
|
||||
/**
|
||||
* Returns configured periodicity for personal timesheets.
|
||||
*/
|
||||
PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity();
|
||||
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import javax.annotation.Resource;
|
|||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.advance.entities.AdvanceMeasurement;
|
||||
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.orders.entities.SumChargedEffort;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
|
|
@ -54,7 +55,7 @@ public class MyTasksAreaController extends GenericForwardComposer {
|
|||
private IMyTasksAreaModel myTasksAreaModel;
|
||||
|
||||
@Resource
|
||||
private IMonthlyTimesheetController monthlyTimesheetController;
|
||||
private IPersonalTimesheetController personalTimesheetController;
|
||||
|
||||
private RowRenderer tasksRenderer = new RowRenderer() {
|
||||
|
||||
|
|
@ -112,17 +113,19 @@ public class MyTasksAreaController extends GenericForwardComposer {
|
|||
EventListener trackTimeButtonListener = new EventListener() {
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
monthlyTimesheetController
|
||||
.goToCreateOrEditForm(getMonthlyTimesheetDateForTask(task));
|
||||
personalTimesheetController
|
||||
.goToCreateOrEditForm(getPersonalTimesheetDateForTask(task));
|
||||
}
|
||||
|
||||
private LocalDate getMonthlyTimesheetDateForTask(Task task) {
|
||||
private LocalDate getPersonalTimesheetDateForTask(Task task) {
|
||||
LocalDate start = task.getStartAsLocalDate();
|
||||
LocalDate end = task.getEndAsLocalDate();
|
||||
|
||||
LocalDate currentDate = new LocalDate();
|
||||
LocalDate min = currentDate.dayOfMonth().withMinimumValue();
|
||||
LocalDate max = currentDate.dayOfMonth().withMaximumValue();
|
||||
PersonalTimesheetsPeriodicityEnum periodicity = myTasksAreaModel
|
||||
.getPersonalTimesheetsPeriodicity();
|
||||
LocalDate min = periodicity.getStart(currentDate);
|
||||
LocalDate max = periodicity.getEnd(currentDate);
|
||||
|
||||
if (dateBetween(start, min, max)) {
|
||||
return start;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import java.util.List;
|
|||
|
||||
import org.libreplan.business.advance.entities.AdvanceMeasurement;
|
||||
import org.libreplan.business.advance.entities.DirectAdvanceAssignment;
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.planner.daos.IResourceAllocationDAO;
|
||||
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
|
||||
import org.libreplan.business.planner.entities.Task;
|
||||
|
|
@ -53,6 +55,9 @@ public class MyTasksAreaModel implements IMyTasksAreaModel {
|
|||
@Autowired
|
||||
private IScenarioManager scenarioManager;
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<Task> getTasks() {
|
||||
|
|
@ -103,4 +108,11 @@ public class MyTasksAreaModel implements IMyTasksAreaModel {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return configurationDAO.getConfiguration()
|
||||
.getPersonalTimesheetsPeriodicity();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,20 +67,20 @@ import org.zkoss.zul.Textbox;
|
|||
import org.zkoss.zul.api.Grid;
|
||||
|
||||
/**
|
||||
* Controller for creation/edition of a monthly timesheet
|
||||
* Controller for creation/edition of a personal timesheet
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MonthlyTimesheetController extends GenericForwardComposer
|
||||
implements IMonthlyTimesheetController {
|
||||
public class PersonalTimesheetController extends GenericForwardComposer
|
||||
implements IPersonalTimesheetController {
|
||||
|
||||
private final static String EFFORT_DURATION_TEXTBOX_WIDTH = "30px";
|
||||
private final static String TOTAL_DURATION_TEXTBOX_WIDTH = "50px";
|
||||
|
||||
private final static String WORK_REPORTS_URL = "/workreports/workReport.zul";
|
||||
|
||||
private IMonthlyTimesheetModel monthlyTimesheetModel;
|
||||
private IPersonalTimesheetModel personalTimesheetModel;
|
||||
|
||||
private IURLHandlerRegistry URLHandlerRegistry;
|
||||
|
||||
|
|
@ -90,15 +90,15 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
private BandboxSearch orderElementBandboxSearch;
|
||||
|
||||
private Button previousMonth;
|
||||
private Button previousPeriod;
|
||||
|
||||
private Button nextMonth;
|
||||
private Button nextPeriod;
|
||||
|
||||
private Component messagesContainer;
|
||||
|
||||
private IMessagesForUser messagesForUser;
|
||||
|
||||
private Label summaryTotalMonthlyTimesheet;
|
||||
private Label summaryTotalPersonalTimesheet;
|
||||
|
||||
private Label summaryTotalOther;
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
private Label summaryTotalExtra;
|
||||
|
||||
@Resource
|
||||
private IMonthlyTimesheetController monthlyTimesheetController;
|
||||
private IPersonalTimesheetController personalTimesheetController;
|
||||
|
||||
private RowRenderer rowRenderer = new RowRenderer() {
|
||||
|
||||
|
|
@ -120,14 +120,14 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
@Override
|
||||
public void render(Row row, Object data) throws Exception {
|
||||
MonthlyTimesheetRow monthlyTimesheetRow = (MonthlyTimesheetRow) data;
|
||||
PersonalTimesheetRow personalTimesheetRow = (PersonalTimesheetRow) data;
|
||||
|
||||
initMonthlyTimesheetDates();
|
||||
initPersonalTimesheetDates();
|
||||
|
||||
switch (monthlyTimesheetRow.getType()) {
|
||||
switch (personalTimesheetRow.getType()) {
|
||||
case ORDER_ELEMENT:
|
||||
renderOrderElementRow(row,
|
||||
monthlyTimesheetRow.getOrderElemement());
|
||||
personalTimesheetRow.getOrderElemement());
|
||||
break;
|
||||
case OTHER:
|
||||
renderOtherRow(row);
|
||||
|
|
@ -146,24 +146,24 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
break;
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Unknown MonthlyTimesheetRow type: "
|
||||
+ monthlyTimesheetRow.getType());
|
||||
"Unknown PersonalTimesheetRow type: "
|
||||
+ personalTimesheetRow.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private void initMonthlyTimesheetDates() {
|
||||
first = monthlyTimesheetModel.getFirstDay();
|
||||
last = monthlyTimesheetModel.getLastDate();
|
||||
private void initPersonalTimesheetDates() {
|
||||
first = personalTimesheetModel.getFirstDay();
|
||||
last = personalTimesheetModel.getLastDate();
|
||||
}
|
||||
|
||||
private void renderOrderElementRow(Row row, OrderElement orderElement) {
|
||||
Util.appendLabel(row, monthlyTimesheetModel.getOrder(orderElement)
|
||||
Util.appendLabel(row, personalTimesheetModel.getOrder(orderElement)
|
||||
.getName());
|
||||
Util.appendLabel(row, orderElement.getName());
|
||||
|
||||
appendInputsForDays(row, orderElement);
|
||||
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
appendOtherColumn(row, orderElement);
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
Util.bind(textbox, new Util.Getter<String>() {
|
||||
@Override
|
||||
public String get() {
|
||||
EffortDuration effortDuration = monthlyTimesheetModel
|
||||
EffortDuration effortDuration = personalTimesheetModel
|
||||
.getEffortDuration(orderElement, textboxDate);
|
||||
return effortDurationToString(effortDuration);
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
throw new WrongValueException(textbox,
|
||||
_("Invalid Effort Duration"));
|
||||
}
|
||||
monthlyTimesheetModel.setEffortDuration(orderElement,
|
||||
personalTimesheetModel.setEffortDuration(orderElement,
|
||||
textboxDate, effortDuration);
|
||||
markAsModified(textbox);
|
||||
updateTotals(orderElement, textboxDate);
|
||||
|
|
@ -212,13 +212,13 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
});
|
||||
|
||||
if (monthlyTimesheetModel
|
||||
if (personalTimesheetModel
|
||||
.wasModified(orderElement, textboxDate)) {
|
||||
markAsModified(textbox);
|
||||
}
|
||||
|
||||
Cell cell = getCenteredCell(textbox);
|
||||
if (monthlyTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -232,7 +232,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
private void appendOtherColumn(Row row, final OrderElement orderElement) {
|
||||
Textbox other = getDisabledTextbox(getOtherRowTextboxId(orderElement));
|
||||
other.setValue(effortDurationToString(monthlyTimesheetModel.getOtherEffortDuration(orderElement)));
|
||||
other.setValue(effortDurationToString(personalTimesheetModel.getOtherEffortDuration(orderElement)));
|
||||
row.appendChild(getCenteredCell(other));
|
||||
}
|
||||
|
||||
|
|
@ -242,9 +242,9 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void updateTotalColumn(OrderElement orderElement) {
|
||||
EffortDuration effort = monthlyTimesheetModel
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getEffortDuration(orderElement);
|
||||
effort = effort.plus(monthlyTimesheetModel
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getOtherEffortDuration(orderElement));
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
|
|
@ -272,7 +272,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getTotalColumnTextboxId(day)));
|
||||
if (monthlyTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -282,9 +282,9 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void updateTotalRow(LocalDate date) {
|
||||
EffortDuration effort = monthlyTimesheetModel
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getEffortDuration(date);
|
||||
effort = effort.plus(monthlyTimesheetModel
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getOtherEffortDuration(date));
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
|
|
@ -294,7 +294,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
private void appendTotalColumn(Row row) {
|
||||
Cell totalCell = getCenteredCell(getDisabledTextbox(getTotalTextboxId()));
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
totalCell.setColspan(2);
|
||||
}
|
||||
row.appendChild(totalCell);
|
||||
|
|
@ -302,9 +302,9 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void updateTotalColumn() {
|
||||
EffortDuration effort = monthlyTimesheetModel
|
||||
EffortDuration effort = personalTimesheetModel
|
||||
.getTotalEffortDuration();
|
||||
effort = effort.plus(monthlyTimesheetModel
|
||||
effort = effort.plus(personalTimesheetModel
|
||||
.getTotalOtherEffortDuration());
|
||||
|
||||
Textbox textbox = (Textbox) timesheet
|
||||
|
|
@ -322,12 +322,12 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
EffortDuration other = monthlyTimesheetModel
|
||||
EffortDuration other = personalTimesheetModel
|
||||
.getOtherEffortDuration(day);
|
||||
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
||||
getOtherColumnTextboxId(day), other));
|
||||
if (monthlyTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -351,12 +351,12 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
EffortDuration capacity = monthlyTimesheetModel
|
||||
EffortDuration capacity = personalTimesheetModel
|
||||
.getResourceCapacity(day);
|
||||
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(
|
||||
getCapcityColumnTextboxId(day), capacity));
|
||||
if (monthlyTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -366,7 +366,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
Cell totalCapacityCell = getCenteredCell(getDisabledTextbox(
|
||||
getTotalCapacityTextboxId(), totalCapacity));
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
totalCapacityCell.setColspan(2);
|
||||
}
|
||||
row.appendChild(totalCapacityCell);
|
||||
|
|
@ -382,7 +382,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
for (LocalDate day = first; day.compareTo(last) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
Cell cell = getCenteredCell(getDisabledTextbox(getExtraColumnTextboxId(day)));
|
||||
if (monthlyTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
if (personalTimesheetModel.getResourceCapacity(day).isZero()) {
|
||||
setBackgroundNonCapacityCell(cell);
|
||||
}
|
||||
row.appendChild(cell);
|
||||
|
|
@ -414,7 +414,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
private void appendTotalExtra(Row row) {
|
||||
Cell totalExtraCell = getCenteredCell(getDisabledTextbox(getTotalExtraTextboxId()));
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
totalExtraCell.setColspan(2);
|
||||
}
|
||||
row.appendChild(totalExtraCell);
|
||||
|
|
@ -478,7 +478,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
|
||||
checkUserComesFromEntryPointsOrSendForbiddenCode();
|
||||
|
||||
URLHandlerRegistry.getRedirectorFor(IMonthlyTimesheetController.class)
|
||||
URLHandlerRegistry.getRedirectorFor(IPersonalTimesheetController.class)
|
||||
.register(this, page);
|
||||
}
|
||||
|
||||
|
|
@ -508,7 +508,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||
breadcrumbs.appendChild(new Label(_("My dashboard")));
|
||||
breadcrumbs.appendChild(new Image(BREADCRUMBS_SEPARATOR));
|
||||
breadcrumbs.appendChild(new Label(_("Monthly timesheet")));
|
||||
breadcrumbs.appendChild(new Label(_("Personal timesheet")));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -517,7 +517,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||
}
|
||||
|
||||
monthlyTimesheetModel.initCreateOrEdit(date);
|
||||
personalTimesheetModel.initCreateOrEdit(date);
|
||||
initTimesheet(date);
|
||||
}
|
||||
|
||||
|
|
@ -528,7 +528,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
Util.sendForbiddenStatusCodeInHttpServletResponse();
|
||||
}
|
||||
|
||||
monthlyTimesheetModel.initCreateOrEdit(date, resource);
|
||||
personalTimesheetModel.initCreateOrEdit(date, resource);
|
||||
initTimesheet(date);
|
||||
}
|
||||
|
||||
|
|
@ -549,7 +549,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
private void createColumns(LocalDate date) {
|
||||
createProjectAndTaskColumns();
|
||||
createColumnsForDays(date);
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
createOtherColumn();
|
||||
}
|
||||
createTotalColumn();
|
||||
|
|
@ -568,8 +568,10 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
private void createColumnsForDays(LocalDate date) {
|
||||
LocalDate start = date.dayOfMonth().withMinimumValue();
|
||||
LocalDate end = date.dayOfMonth().withMaximumValue();
|
||||
LocalDate start = personalTimesheetModel
|
||||
.getPersonalTimesheetsPeriodicity().getStart(date);
|
||||
LocalDate end = personalTimesheetModel
|
||||
.getPersonalTimesheetsPeriodicity().getEnd(date);
|
||||
|
||||
for (LocalDate day = start; day.compareTo(end) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
|
|
@ -596,24 +598,24 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
columns.appendChild(total);
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return monthlyTimesheetModel.getDate().toString("MMMM y");
|
||||
public String getTimesheetString() {
|
||||
return personalTimesheetModel.getTimesheetString();
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return monthlyTimesheetModel.getWorker().getShortDescription();
|
||||
return personalTimesheetModel.getWorker().getShortDescription();
|
||||
}
|
||||
|
||||
public List<MonthlyTimesheetRow> getRows() {
|
||||
List<MonthlyTimesheetRow> result = MonthlyTimesheetRow
|
||||
.wrap(monthlyTimesheetModel
|
||||
public List<PersonalTimesheetRow> getRows() {
|
||||
List<PersonalTimesheetRow> result = PersonalTimesheetRow
|
||||
.wrap(personalTimesheetModel
|
||||
.getOrderElements());
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
result.add(MonthlyTimesheetRow.createOtherRow());
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
result.add(PersonalTimesheetRow.createOtherRow());
|
||||
}
|
||||
result.add(MonthlyTimesheetRow.createTotalRow());
|
||||
result.add(MonthlyTimesheetRow.createCapacityRow());
|
||||
result.add(MonthlyTimesheetRow.createExtraRow());
|
||||
result.add(PersonalTimesheetRow.createTotalRow());
|
||||
result.add(PersonalTimesheetRow.createCapacityRow());
|
||||
result.add(PersonalTimesheetRow.createExtraRow());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -622,31 +624,31 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
public void save() {
|
||||
monthlyTimesheetModel.save();
|
||||
personalTimesheetModel.save();
|
||||
String url = CustomTargetUrlResolver.USER_DASHBOARD_URL
|
||||
+ "?timesheet_saved=" + monthlyTimesheetModel.getDate();
|
||||
if (!monthlyTimesheetModel.isCurrentUser()) {
|
||||
+ "?timesheet_saved=" + personalTimesheetModel.getDate();
|
||||
if (!personalTimesheetModel.isCurrentUser()) {
|
||||
url = WORK_REPORTS_URL + "?timesheet_saved=true";
|
||||
}
|
||||
Executions.getCurrent().sendRedirect(url);
|
||||
}
|
||||
|
||||
public void saveAndContinue() {
|
||||
monthlyTimesheetModel.save();
|
||||
if (monthlyTimesheetModel.isCurrentUser()) {
|
||||
goToCreateOrEditForm(monthlyTimesheetModel.getDate());
|
||||
personalTimesheetModel.save();
|
||||
if (personalTimesheetModel.isCurrentUser()) {
|
||||
goToCreateOrEditForm(personalTimesheetModel.getDate());
|
||||
} else {
|
||||
goToCreateOrEditFormForResource(monthlyTimesheetModel.getDate(),
|
||||
monthlyTimesheetModel.getWorker());
|
||||
goToCreateOrEditFormForResource(personalTimesheetModel.getDate(),
|
||||
personalTimesheetModel.getWorker());
|
||||
}
|
||||
messagesForUser.showMessage(Level.INFO, _("Monthly timesheet saved"));
|
||||
messagesForUser.showMessage(Level.INFO, _("Personal timesheet saved"));
|
||||
Util.reloadBindings(timesheet);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
monthlyTimesheetModel.cancel();
|
||||
personalTimesheetModel.cancel();
|
||||
String url = CustomTargetUrlResolver.USER_DASHBOARD_URL;
|
||||
if (!monthlyTimesheetModel.isCurrentUser()) {
|
||||
if (!personalTimesheetModel.isCurrentUser()) {
|
||||
url = WORK_REPORTS_URL;
|
||||
}
|
||||
Executions.getCurrent().sendRedirect(url);
|
||||
|
|
@ -656,56 +658,56 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
OrderElement orderElement = (OrderElement) orderElementBandboxSearch
|
||||
.getSelectedElement();
|
||||
if (orderElement != null) {
|
||||
monthlyTimesheetModel.addOrderElement(orderElement);
|
||||
personalTimesheetModel.addOrderElement(orderElement);
|
||||
orderElementBandboxSearch.setSelectedElement(null);
|
||||
Util.reloadBindings(timesheet);
|
||||
adjustFrozenWidth();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFirstMonth() {
|
||||
return monthlyTimesheetModel.isFirstMonth();
|
||||
public boolean isFirstPeriod() {
|
||||
return personalTimesheetModel.isFirstPeriod();
|
||||
}
|
||||
|
||||
public boolean isLastMonth() {
|
||||
return monthlyTimesheetModel.isLastMonth();
|
||||
public boolean isLastPeriod() {
|
||||
return personalTimesheetModel.isLastPeriod();
|
||||
}
|
||||
|
||||
public void previousMonth() {
|
||||
if (monthlyTimesheetModel.isModified()) {
|
||||
public void previousPeriod() {
|
||||
if (personalTimesheetModel.isModified()) {
|
||||
throw new WrongValueException(
|
||||
previousMonth,
|
||||
_("There are unsaved changes in the current monthly timesheet, please save before moving"));
|
||||
previousPeriod,
|
||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
||||
}
|
||||
sendToMonthlyTimesheet(monthlyTimesheetModel.getDate().minusMonths(1));
|
||||
sendToPersonalTimesheet(personalTimesheetModel.getPrevious());
|
||||
}
|
||||
|
||||
public void nextMonth() {
|
||||
if (monthlyTimesheetModel.isModified()) {
|
||||
public void nextPeriod() {
|
||||
if (personalTimesheetModel.isModified()) {
|
||||
throw new WrongValueException(
|
||||
nextMonth,
|
||||
_("There are unsaved changes in the current monthly timesheet, please save before moving"));
|
||||
nextPeriod,
|
||||
_("There are unsaved changes in the current personal timesheet, please save before moving"));
|
||||
}
|
||||
|
||||
sendToMonthlyTimesheet(monthlyTimesheetModel.getDate().plusMonths(1));
|
||||
sendToPersonalTimesheet(personalTimesheetModel.getNext());
|
||||
}
|
||||
|
||||
private void sendToMonthlyTimesheet(final LocalDate date) {
|
||||
private void sendToPersonalTimesheet(final LocalDate date) {
|
||||
String capturePath = EntryPointsHandler.capturePath(new ICapture() {
|
||||
@Override
|
||||
public void capture() {
|
||||
monthlyTimesheetController.goToCreateOrEditForm(date);
|
||||
personalTimesheetController.goToCreateOrEditForm(date);
|
||||
}
|
||||
});
|
||||
Executions.getCurrent().sendRedirect(capturePath);
|
||||
}
|
||||
|
||||
public boolean isCurrentUser() {
|
||||
return monthlyTimesheetModel.isCurrentUser();
|
||||
return personalTimesheetModel.isCurrentUser();
|
||||
}
|
||||
|
||||
public boolean isNotCurrentUser() {
|
||||
return !monthlyTimesheetModel.isCurrentUser();
|
||||
return !personalTimesheetModel.isCurrentUser();
|
||||
}
|
||||
|
||||
private static String getTotalRowTextboxId(final OrderElement orderElement) {
|
||||
|
|
@ -781,7 +783,7 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
public void updateSummary() {
|
||||
EffortDuration total = getEffortDurationFromTextbox(getTotalTextboxId());
|
||||
EffortDuration other = EffortDuration.zero();
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
other = getEffortDurationFromTextbox(getTotalOtherTextboxId());
|
||||
}
|
||||
EffortDuration capacity = getEffortDurationFromTextbox(getTotalCapacityTextboxId());
|
||||
|
|
@ -793,8 +795,8 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
extra = total.minus(capacity);
|
||||
}
|
||||
|
||||
if (monthlyTimesheetModel.hasOtherReports()) {
|
||||
summaryTotalMonthlyTimesheet
|
||||
if (personalTimesheetModel.hasOtherReports()) {
|
||||
summaryTotalPersonalTimesheet
|
||||
.setValue(timesheet.toFormattedString());
|
||||
summaryTotalOther.setValue(other.toFormattedString());
|
||||
}
|
||||
|
|
@ -811,64 +813,64 @@ public class MonthlyTimesheetController extends GenericForwardComposer
|
|||
}
|
||||
|
||||
public boolean hasOtherReports() {
|
||||
return monthlyTimesheetModel.hasOtherReports();
|
||||
return personalTimesheetModel.hasOtherReports();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class to represent the the rows in the monthly timesheet grid.<br />
|
||||
* Simple class to represent the the rows in the personal timesheet grid.<br />
|
||||
*
|
||||
* This is used to mark the special rows like capacity and total.
|
||||
*/
|
||||
class MonthlyTimesheetRow {
|
||||
enum MonthlyTimesheetRowType {
|
||||
class PersonalTimesheetRow {
|
||||
enum PersonalTimesheetRowType {
|
||||
ORDER_ELEMENT, OTHER, CAPACITY, TOTAL, EXTRA
|
||||
};
|
||||
|
||||
private MonthlyTimesheetRowType type;
|
||||
private PersonalTimesheetRowType type;
|
||||
private OrderElement orderElemement;
|
||||
|
||||
public static MonthlyTimesheetRow createOrderElementRow(
|
||||
public static PersonalTimesheetRow createOrderElementRow(
|
||||
OrderElement orderElemement) {
|
||||
MonthlyTimesheetRow row = new MonthlyTimesheetRow(
|
||||
MonthlyTimesheetRowType.ORDER_ELEMENT);
|
||||
PersonalTimesheetRow row = new PersonalTimesheetRow(
|
||||
PersonalTimesheetRowType.ORDER_ELEMENT);
|
||||
Assert.notNull(orderElemement);
|
||||
row.orderElemement = orderElemement;
|
||||
return row;
|
||||
}
|
||||
|
||||
public static MonthlyTimesheetRow createOtherRow() {
|
||||
return new MonthlyTimesheetRow(MonthlyTimesheetRowType.OTHER);
|
||||
public static PersonalTimesheetRow createOtherRow() {
|
||||
return new PersonalTimesheetRow(PersonalTimesheetRowType.OTHER);
|
||||
}
|
||||
|
||||
public static MonthlyTimesheetRow createCapacityRow() {
|
||||
return new MonthlyTimesheetRow(MonthlyTimesheetRowType.CAPACITY);
|
||||
public static PersonalTimesheetRow createCapacityRow() {
|
||||
return new PersonalTimesheetRow(PersonalTimesheetRowType.CAPACITY);
|
||||
}
|
||||
|
||||
public static MonthlyTimesheetRow createTotalRow() {
|
||||
return new MonthlyTimesheetRow(MonthlyTimesheetRowType.TOTAL);
|
||||
public static PersonalTimesheetRow createTotalRow() {
|
||||
return new PersonalTimesheetRow(PersonalTimesheetRowType.TOTAL);
|
||||
}
|
||||
|
||||
public static MonthlyTimesheetRow createExtraRow() {
|
||||
return new MonthlyTimesheetRow(MonthlyTimesheetRowType.EXTRA);
|
||||
public static PersonalTimesheetRow createExtraRow() {
|
||||
return new PersonalTimesheetRow(PersonalTimesheetRowType.EXTRA);
|
||||
}
|
||||
|
||||
public static List<MonthlyTimesheetRow> wrap(
|
||||
public static List<PersonalTimesheetRow> wrap(
|
||||
List<OrderElement> orderElements) {
|
||||
List<MonthlyTimesheetRow> result = new ArrayList<MonthlyTimesheetRow>();
|
||||
List<PersonalTimesheetRow> result = new ArrayList<PersonalTimesheetRow>();
|
||||
for (OrderElement each : orderElements) {
|
||||
result.add(createOrderElementRow(each));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private MonthlyTimesheetRow(MonthlyTimesheetRowType type) {
|
||||
private PersonalTimesheetRow(PersonalTimesheetRowType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public MonthlyTimesheetRowType getType() {
|
||||
public PersonalTimesheetRowType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
@ -19,19 +19,22 @@
|
|||
|
||||
package org.libreplan.web.users.dashboard;
|
||||
|
||||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
|
||||
/**
|
||||
* Simple class to represent the monthly timesheets to be shown in the list.<br />
|
||||
* Simple class to represent the personal timesheets to be shown in the list.<br />
|
||||
*
|
||||
* This is only a utility class for the UI, everything will be saved using
|
||||
* {@link WorkReport} class.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
public class MonthlyTimesheetDTO {
|
||||
public class PersonalTimesheetDTO {
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
|
|
@ -45,24 +48,23 @@ public class MonthlyTimesheetDTO {
|
|||
|
||||
/**
|
||||
* @param date
|
||||
* Only the year and month are used, the day is reseted to first
|
||||
* day of the month. As there's only one timesheet per month.
|
||||
* The date of the timesheet.
|
||||
* @param workReport
|
||||
* The work report of the monthly timesheet, it could be
|
||||
* The work report of the personal timesheet, it could be
|
||||
* <code>null</code> if it doesn't exist yet.
|
||||
* @param resourceCapacity
|
||||
* The capacity of the resource bound to current user in the
|
||||
* month of this timesheet.
|
||||
* period of this timesheet.
|
||||
* @param totalHours
|
||||
* Total hours worked by the resource bound to the current user
|
||||
* in the monthly timesheet
|
||||
* in the personal timesheet
|
||||
* @param tasksNumber
|
||||
* Number of tasks in the monthly timesheet
|
||||
* Number of tasks in the personal timesheet
|
||||
*/
|
||||
MonthlyTimesheetDTO(LocalDate date, WorkReport workReport,
|
||||
PersonalTimesheetDTO(LocalDate date, WorkReport workReport,
|
||||
EffortDuration resourceCapacity, EffortDuration totalHours,
|
||||
int tasksNumber) {
|
||||
this.date = date.dayOfMonth().withMaximumValue();
|
||||
this.date = date;
|
||||
this.workReport = workReport;
|
||||
this.resourceCapacity = resourceCapacity;
|
||||
this.totalHours = totalHours;
|
||||
|
|
@ -89,4 +91,41 @@ public class MonthlyTimesheetDTO {
|
|||
return tasksNumber;
|
||||
}
|
||||
|
||||
public String toString(PersonalTimesheetsPeriodicityEnum periodicity) {
|
||||
return toString(periodicity, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the personal timehseet in a given
|
||||
* <code>date</code> depending on the <code>periodicity</code>.
|
||||
*/
|
||||
public static String toString(PersonalTimesheetsPeriodicityEnum periodicity, LocalDate date) {
|
||||
switch (periodicity) {
|
||||
case WEEKLY:
|
||||
LocalDate start = periodicity.getStart(date);
|
||||
LocalDate end = periodicity.getEnd(date);
|
||||
|
||||
String string = date.toString("w");
|
||||
if (start.getMonthOfYear() == end.getMonthOfYear()) {
|
||||
string += " (" + date.toString("MMMM y") + ")";
|
||||
} else {
|
||||
if (start.getYear() == end.getYear()) {
|
||||
string += " (" + start.toString("MMMM") + " - "
|
||||
+ end.toString("MMMM y") + ")";
|
||||
} else {
|
||||
string += " (" + start.toString("MMMM y") + " - "
|
||||
+ end.toString("MMMM y") + ")";
|
||||
}
|
||||
}
|
||||
return _("Week {0}", string);
|
||||
case TWICE_MONTHLY:
|
||||
return (date.getDayOfMonth() <= 15) ?
|
||||
_("{0} 1st fortnight", date.toString("MMMM y")) :
|
||||
_("{0} 2nd fortnight", date.toString("MMMM y"));
|
||||
case MONTHLY:
|
||||
default:
|
||||
return date.toString("MMMM y");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ import org.libreplan.business.calendars.entities.ResourceCalendar;
|
|||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.daos.IEntitySequenceDAO;
|
||||
import org.libreplan.business.common.entities.EntityNameEnum;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.costcategories.entities.TypeOfWorkHours;
|
||||
import org.libreplan.business.orders.daos.IOrderDAO;
|
||||
|
|
@ -67,14 +68,14 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Model for creation/edition of a monthly timesheet
|
||||
* Model for creation/edition of a personal timesheet
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@Service
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
@OnConcurrentModification(goToPage = "/myaccount/userDashboard.zul")
|
||||
public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
||||
public class PersonalTimesheetModel implements IPersonalTimesheetModel {
|
||||
|
||||
private User user;
|
||||
|
||||
|
|
@ -102,6 +103,8 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
|
||||
private Map<LocalDate, EffortDuration> otherEffortPerDay;
|
||||
|
||||
private PersonalTimesheetsPeriodicityEnum periodicity;
|
||||
|
||||
@Autowired
|
||||
private IResourceAllocationDAO resourceAllocationDAO;
|
||||
|
||||
|
|
@ -147,6 +150,8 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
private void initFields(LocalDate date) {
|
||||
this.date = date;
|
||||
|
||||
periodicity = getPersonalTimesheetsPeriodicity();
|
||||
|
||||
initDates();
|
||||
|
||||
initCapacityMap();
|
||||
|
|
@ -173,8 +178,8 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
}
|
||||
|
||||
private void initDates() {
|
||||
firstDay = date.dayOfMonth().withMinimumValue();
|
||||
lastDay = date.dayOfMonth().withMaximumValue();
|
||||
firstDay = periodicity.getStart(date);
|
||||
lastDay = periodicity.getEnd(date);
|
||||
}
|
||||
|
||||
private void initCapacityMap() {
|
||||
|
|
@ -195,13 +200,13 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
}
|
||||
|
||||
private void initWorkReport() {
|
||||
// Get work report representing this monthly timesheet
|
||||
workReport = workReportDAO.getMonthlyTimesheetWorkReport(
|
||||
user.getWorker(), date);
|
||||
// Get work report representing this personal timesheet
|
||||
workReport = workReportDAO.getPersonalTimesheetWorkReport(
|
||||
user.getWorker(), date, periodicity);
|
||||
if (workReport == null) {
|
||||
// If it doesn't exist yet create a new one
|
||||
workReport = WorkReport
|
||||
.create(getMonthlyTimesheetsWorkReportType());
|
||||
.create(getPersonalTimesheetsWorkReportType());
|
||||
workReport
|
||||
.setCode(entitySequenceDAO
|
||||
.getNextEntityCodeWithoutTransaction(EntityNameEnum.WORK_REPORT));
|
||||
|
|
@ -211,10 +216,10 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
forceLoad(workReport.getWorkReportType());
|
||||
}
|
||||
|
||||
private WorkReportType getMonthlyTimesheetsWorkReportType() {
|
||||
private WorkReportType getPersonalTimesheetsWorkReportType() {
|
||||
try {
|
||||
WorkReportType workReportType = workReportTypeDAO
|
||||
.findUniqueByName(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS
|
||||
.findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName());
|
||||
return workReportType;
|
||||
} catch (NonUniqueResultException e) {
|
||||
|
|
@ -413,7 +418,7 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
|
||||
private TypeOfWorkHours getTypeOfWorkHours() {
|
||||
return configurationDAO.getConfiguration()
|
||||
.getMonthlyTimesheetsTypeOfWorkHours();
|
||||
.getPersonalTimesheetsTypeOfWorkHours();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -424,7 +429,7 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
// Do nothing.
|
||||
// A new work report if it doesn't have work report lines is not
|
||||
// saved as it will not be possible to find it later with
|
||||
// WorkReportDAO.getMonthlyTimesheetWorkReport() method.
|
||||
// WorkReportDAO.getPersonalTimesheetWorkReport() method.
|
||||
} else {
|
||||
sumChargedEffortDAO
|
||||
.updateRelatedSumChargedEffortWithWorkReportLineSet(workReport
|
||||
|
|
@ -502,16 +507,18 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isFirstMonth() {
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isFirstPeriod() {
|
||||
LocalDate activationDate = getWorker().getCalendar()
|
||||
.getFistCalendarAvailability().getStartDate();
|
||||
return firstDay.equals(activationDate.dayOfMonth().withMinimumValue());
|
||||
return firstDay.equals(periodicity.getStart(activationDate));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLastMonth() {
|
||||
return firstDay.equals(new LocalDate().plusMonths(1).dayOfMonth()
|
||||
.withMinimumValue());
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isLastPeriod() {
|
||||
return firstDay.equals(periodicity.getStart(new LocalDate()
|
||||
.plusMonths(1)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -552,4 +559,26 @@ public class MonthlyTimesheetModel implements IMonthlyTimesheetModel {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return configurationDAO.getConfiguration()
|
||||
.getPersonalTimesheetsPeriodicity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTimesheetString() {
|
||||
return PersonalTimesheetDTO.toString(periodicity, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getPrevious() {
|
||||
return periodicity.previous(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate getNext() {
|
||||
return periodicity.next(date);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,37 +32,39 @@ import org.zkoss.zul.Row;
|
|||
import org.zkoss.zul.RowRenderer;
|
||||
|
||||
/**
|
||||
* Controller for "Monthly timesheets" area in the user dashboard window
|
||||
* Controller for "Personal timesheets" area in the user dashboard window
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MonthlyTimesheetsAreaController extends GenericForwardComposer {
|
||||
public class PersonalTimesheetsAreaController extends GenericForwardComposer {
|
||||
|
||||
private IMonthlyTimesheetsAreaModel monthlyTimesheetsAreaModel;
|
||||
private IPersonalTimesheetsAreaModel personalTimesheetsAreaModel;
|
||||
|
||||
@Resource
|
||||
private IMonthlyTimesheetController monthlyTimesheetController;
|
||||
private IPersonalTimesheetController personalTimesheetController;
|
||||
|
||||
private RowRenderer monthlyTimesheetsRenderer = new RowRenderer() {
|
||||
private RowRenderer personalTimesheetsRenderer = new RowRenderer() {
|
||||
|
||||
@Override
|
||||
public void render(Row row, Object data) throws Exception {
|
||||
final MonthlyTimesheetDTO monthlyTimesheet = (MonthlyTimesheetDTO) data;
|
||||
row.setValue(monthlyTimesheet);
|
||||
final PersonalTimesheetDTO personalTimesheet = (PersonalTimesheetDTO) data;
|
||||
row.setValue(personalTimesheet);
|
||||
|
||||
Util.appendLabel(row, monthlyTimesheet.getDate().toString("MMMM y"));
|
||||
Util.appendLabel(row, monthlyTimesheet.getResourceCapacity()
|
||||
Util.appendLabel(row, personalTimesheet
|
||||
.toString(personalTimesheetsAreaModel
|
||||
.getPersonalTimesheetsPeriodicity()));
|
||||
Util.appendLabel(row, personalTimesheet.getResourceCapacity()
|
||||
.toFormattedString());
|
||||
Util.appendLabel(row, monthlyTimesheet.getTotalHours()
|
||||
Util.appendLabel(row, personalTimesheet.getTotalHours()
|
||||
.toFormattedString());
|
||||
Util.appendLabel(row, monthlyTimesheet.getTasksNumber() + "");
|
||||
Util.appendLabel(row, personalTimesheet.getTasksNumber() + "");
|
||||
|
||||
Util.appendOperationsAndOnClickEvent(row, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
monthlyTimesheetController.goToCreateOrEditForm(monthlyTimesheet
|
||||
personalTimesheetController.goToCreateOrEditForm(personalTimesheet
|
||||
.getDate());
|
||||
}
|
||||
}, null);
|
||||
|
|
@ -76,12 +78,12 @@ public class MonthlyTimesheetsAreaController extends GenericForwardComposer {
|
|||
comp.setAttribute("controller", this);
|
||||
}
|
||||
|
||||
public List<MonthlyTimesheetDTO> getMonthlyTimesheets() {
|
||||
return monthlyTimesheetsAreaModel.getMonthlyTimesheets();
|
||||
public List<PersonalTimesheetDTO> getPersonalTimesheets() {
|
||||
return personalTimesheetsAreaModel.getPersonalTimesheets();
|
||||
}
|
||||
|
||||
public RowRenderer getMonthlyTimesheetsRenderer() {
|
||||
return monthlyTimesheetsRenderer;
|
||||
public RowRenderer getPersonalTimesheetsRenderer() {
|
||||
return personalTimesheetsRenderer;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.Months;
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.resources.entities.Resource;
|
||||
import org.libreplan.business.resources.entities.Worker;
|
||||
|
|
@ -45,20 +46,23 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Model for for "Monthly timesheets" area in the user dashboard window
|
||||
* Model for for "Personal timesheets" area in the user dashboard window
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
@Service
|
||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
public class MonthlyTimesheetsAreaModel implements IMonthlyTimesheetsAreaModel {
|
||||
public class PersonalTimesheetsAreaModel implements IPersonalTimesheetsAreaModel {
|
||||
|
||||
@Autowired
|
||||
private IWorkReportDAO workReportDAO;
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<MonthlyTimesheetDTO> getMonthlyTimesheets() {
|
||||
public List<PersonalTimesheetDTO> getPersonalTimesheets() {
|
||||
User user = UserUtil.getUserFromSession();
|
||||
if (!user.isBound()) {
|
||||
return Collections.emptyList();
|
||||
|
|
@ -68,22 +72,25 @@ public class MonthlyTimesheetsAreaModel implements IMonthlyTimesheetsAreaModel {
|
|||
|
||||
LocalDate activationDate = getActivationDate(user.getWorker());
|
||||
LocalDate currentDate = new LocalDate();
|
||||
return getMonthlyTimesheets(user.getWorker(), activationDate,
|
||||
currentDate.plusMonths(1));
|
||||
return getPersonalTimesheets(user.getWorker(), activationDate,
|
||||
currentDate.plusMonths(1), getPersonalTimesheetsPeriodicity());
|
||||
}
|
||||
|
||||
private List<MonthlyTimesheetDTO> getMonthlyTimesheets(Resource resource,
|
||||
LocalDate start, LocalDate end) {
|
||||
int months = Months.monthsBetween(start, end).getMonths();
|
||||
private List<PersonalTimesheetDTO> getPersonalTimesheets(Resource resource,
|
||||
LocalDate start, LocalDate end,
|
||||
PersonalTimesheetsPeriodicityEnum periodicity) {
|
||||
start = periodicity.getStart(start);
|
||||
end = periodicity.getEnd(end);
|
||||
int items = periodicity.getItemsBetween(start, end);
|
||||
|
||||
List<MonthlyTimesheetDTO> result = new ArrayList<MonthlyTimesheetDTO>();
|
||||
List<PersonalTimesheetDTO> result = new ArrayList<PersonalTimesheetDTO>();
|
||||
|
||||
// In decreasing order to provide a list sorted with the more recent
|
||||
// monthly timesheets at the beginning
|
||||
for (int i = months; i >= 0; i--) {
|
||||
LocalDate date = start.plusMonths(i);
|
||||
// personal timesheets at the beginning
|
||||
for (int i = items; i >= 0; i--) {
|
||||
LocalDate date = periodicity.getDateForItemFromDate(i, start);
|
||||
|
||||
WorkReport workReport = getWorkReport(resource, date);
|
||||
WorkReport workReport = getWorkReport(resource, date, periodicity);
|
||||
|
||||
EffortDuration hours = EffortDuration.zero();
|
||||
int tasksNumber = 0;
|
||||
|
|
@ -92,24 +99,29 @@ public class MonthlyTimesheetsAreaModel implements IMonthlyTimesheetsAreaModel {
|
|||
tasksNumber = getNumberOfOrderElementsWithTrackedTime(workReport);
|
||||
}
|
||||
|
||||
result.add(new MonthlyTimesheetDTO(date, workReport,
|
||||
getResourceCapcity(resource, date), hours, tasksNumber));
|
||||
result.add(new PersonalTimesheetDTO(date, workReport,
|
||||
getResourceCapcity(resource, date, periodicity), hours,
|
||||
tasksNumber));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private WorkReport getWorkReport(Resource resource, LocalDate date) {
|
||||
WorkReport workReport = workReportDAO.getMonthlyTimesheetWorkReport(
|
||||
resource, date);
|
||||
private WorkReport getWorkReport(Resource resource, LocalDate date,
|
||||
PersonalTimesheetsPeriodicityEnum periodicity) {
|
||||
WorkReport workReport = workReportDAO.getPersonalTimesheetWorkReport(
|
||||
resource, date, periodicity);
|
||||
forceLoad(workReport);
|
||||
return workReport;
|
||||
}
|
||||
|
||||
private EffortDuration getResourceCapcity(Resource resource, LocalDate date) {
|
||||
private EffortDuration getResourceCapcity(Resource resource,
|
||||
LocalDate date, PersonalTimesheetsPeriodicityEnum periodicity) {
|
||||
LocalDate start = periodicity.getStart(date);
|
||||
LocalDate end = periodicity.getEnd(date);
|
||||
|
||||
EffortDuration capacity = EffortDuration.zero();
|
||||
for (LocalDate day = date.dayOfMonth().withMinimumValue(); day
|
||||
.compareTo(date.dayOfMonth().withMaximumValue()) <= 0; day = day
|
||||
for (LocalDate day = start; day.compareTo(end) <= 0; day = day
|
||||
.plusDays(1)) {
|
||||
capacity = capacity.plus(resource.getCalendar().getCapacityOn(
|
||||
PartialDay.wholeDay(day)));
|
||||
|
|
@ -149,4 +161,11 @@ public class MonthlyTimesheetsAreaModel implements IMonthlyTimesheetsAreaModel {
|
|||
return orderElements.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
|
||||
return configurationDAO.getConfiguration()
|
||||
.getPersonalTimesheetsPeriodicity();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import static org.libreplan.web.I18nHelper._;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.common.Registry;
|
||||
import org.libreplan.web.common.IMessagesForUser;
|
||||
import org.libreplan.web.common.Level;
|
||||
import org.libreplan.web.common.MessagesForUser;
|
||||
|
|
@ -34,7 +35,7 @@ import org.zkoss.zk.ui.util.GenericForwardComposer;
|
|||
* Controller for user dashboard window.<br />
|
||||
*
|
||||
* At this moment it's only used to show a message to user after saving a
|
||||
* monthly timesheet.
|
||||
* personal timesheet.
|
||||
*
|
||||
* @author Manuel Rego Casasnovas <mrego@igalia.com>
|
||||
*/
|
||||
|
|
@ -54,10 +55,13 @@ public class UserDashboardController extends GenericForwardComposer {
|
|||
String timesheetSave = Executions.getCurrent().getParameter(
|
||||
"timesheet_saved");
|
||||
if (!StringUtils.isBlank(timesheetSave)) {
|
||||
String monthlyTimesheet = new LocalDate(timesheetSave)
|
||||
.toString("MMMM y");
|
||||
String personalTimesheet = PersonalTimesheetDTO.toString(Registry
|
||||
.getConfigurationDAO()
|
||||
.getConfigurationWithReadOnlyTransaction()
|
||||
.getPersonalTimesheetsPeriodicity(), new LocalDate(
|
||||
timesheetSave));
|
||||
messagesForUser.showMessage(Level.INFO,
|
||||
_("Monthly timesheet \"{0}\" saved", monthlyTimesheet));
|
||||
_("Personal timesheet \"{0}\" saved", personalTimesheet));
|
||||
}
|
||||
|
||||
String expenseSheetSaved = Executions.getCurrent().getParameter(
|
||||
|
|
|
|||
|
|
@ -239,9 +239,9 @@ public interface IWorkReportModel extends IIntegrationEntityModel {
|
|||
List<Worker> getBoundWorkers();
|
||||
|
||||
/**
|
||||
* Checks if a {@link WorkReport} is or not a monthly timesheet.
|
||||
* Checks if a {@link WorkReport} is or not a personal timesheet.
|
||||
*/
|
||||
boolean isMonthlyTimesheet(WorkReport workReport);
|
||||
boolean isPersonalTimesheet(WorkReport workReport);
|
||||
|
||||
WorkReportLine getFirstWorkReportLine();
|
||||
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@ public interface IWorkReportTypeModel extends IIntegrationEntityModel {
|
|||
|
||||
/**
|
||||
* Gets the {@link List} of {@link WorkReportType WorkReportTypes} except
|
||||
* the {@link WorkReportType} used for monthly timesheets.
|
||||
* the {@link WorkReportType} used for personal timesheets.
|
||||
*
|
||||
* @return A {@link List} of {@link WorkReportType}
|
||||
*/
|
||||
List<WorkReportType> getWorkReportTypesExceptMonthlyTimeSheets();
|
||||
List<WorkReportType> getWorkReportTypesExceptPersonalTimeSheets();
|
||||
|
||||
/**
|
||||
* Stores the current {@link WorkReportType}.
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import org.libreplan.web.common.components.NewDataSortableGrid;
|
|||
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
|
||||
import org.libreplan.web.common.entrypoints.EntryPointsHandler;
|
||||
import org.libreplan.web.common.entrypoints.IURLHandlerRegistry;
|
||||
import org.libreplan.web.users.dashboard.IMonthlyTimesheetController;
|
||||
import org.libreplan.web.users.dashboard.IPersonalTimesheetController;
|
||||
import org.zkoss.ganttz.IPredicate;
|
||||
import org.zkoss.ganttz.util.ComponentsFinder;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
|
|
@ -157,13 +157,13 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
private Datebox filterFinishDate;
|
||||
|
||||
@javax.annotation.Resource
|
||||
private IMonthlyTimesheetController monthlyTimesheetController;
|
||||
private IPersonalTimesheetController personalTimesheetController;
|
||||
|
||||
private Popup monthlyTimesheetsPopup;
|
||||
private Popup personalTimesheetsPopup;
|
||||
|
||||
private Datebox monthlyTimesheetsDatebox;
|
||||
private Datebox personalTimesheetsDatebox;
|
||||
|
||||
private BandboxSearch monthlyTimesheetsBandboxSearch;
|
||||
private BandboxSearch personalTimesheetsBandboxSearch;
|
||||
|
||||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
|
|
@ -171,7 +171,7 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
listWorkReportLines = (NewDataSortableGrid) createWindow
|
||||
.getFellowIfAny("listWorkReportLines");
|
||||
messagesForUser = new MessagesForUser(messagesContainer);
|
||||
showMessageIfMonthlyTimesheetWasSaved();
|
||||
showMessageIfPersonalTimesheetWasSaved();
|
||||
|
||||
comp.setAttribute("controller", this);
|
||||
goToList();
|
||||
|
|
@ -185,12 +185,12 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
handler.register(this, page);
|
||||
}
|
||||
|
||||
private void showMessageIfMonthlyTimesheetWasSaved() {
|
||||
private void showMessageIfPersonalTimesheetWasSaved() {
|
||||
String timesheetSave = Executions.getCurrent().getParameter(
|
||||
"timesheet_saved");
|
||||
if (!StringUtils.isBlank(timesheetSave)) {
|
||||
messagesForUser.showMessage(Level.INFO,
|
||||
_("Monthly timesheet saved"));
|
||||
_("Personal timesheet saved"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -598,8 +598,8 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
|
||||
@Override
|
||||
public void goToCreateForm(WorkReportType workReportType) {
|
||||
if (workReportType.isMonthlyTimesheetsType()) {
|
||||
monthlyTimesheetsPopup.open(listTypeToAssign);
|
||||
if (workReportType.isPersonalTimesheetsType()) {
|
||||
personalTimesheetsPopup.open(listTypeToAssign);
|
||||
} else {
|
||||
cameBackList = false;
|
||||
workReportModel.initCreate(workReportType);
|
||||
|
|
@ -617,8 +617,8 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
|
||||
@Override
|
||||
public void goToEditForm(WorkReport workReport) {
|
||||
if (workReportModel.isMonthlyTimesheet(workReport)) {
|
||||
goToEditMonthlyTimeSheet(workReport);
|
||||
if (workReportModel.isPersonalTimesheet(workReport)) {
|
||||
goToEditPersonalTimeSheet(workReport);
|
||||
} else {
|
||||
workReportModel.initEdit(workReport);
|
||||
createWindow.setTitle(_("Edit Timesheet"));
|
||||
|
|
@ -629,11 +629,11 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
}
|
||||
}
|
||||
|
||||
private void goToEditMonthlyTimeSheet(WorkReport workReport) {
|
||||
private void goToEditPersonalTimeSheet(WorkReport workReport) {
|
||||
workReportModel.initEdit(workReport);
|
||||
Date date = workReportModel.getFirstWorkReportLine().getDate();
|
||||
Resource resource = workReport.getResource();
|
||||
monthlyTimesheetController.goToCreateOrEditFormForResource(
|
||||
personalTimesheetController.goToCreateOrEditFormForResource(
|
||||
LocalDate.fromDateFields(date), resource);
|
||||
}
|
||||
|
||||
|
|
@ -682,12 +682,12 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
listTypeToAssign = (Listbox) window.getFellow("listTypeToAssign");
|
||||
filterStartDate = (Datebox) window.getFellow("filterStartDate");
|
||||
filterFinishDate = (Datebox) window.getFellow("filterFinishDate");
|
||||
monthlyTimesheetsPopup = (Popup) window
|
||||
.getFellow("monthlyTimesheetsPopup");
|
||||
monthlyTimesheetsDatebox = (Datebox) window
|
||||
.getFellow("monthlyTimesheetsDatebox");
|
||||
monthlyTimesheetsBandboxSearch = (BandboxSearch) window
|
||||
.getFellow("monthlyTimesheetsBandboxSearch");
|
||||
personalTimesheetsPopup = (Popup) window
|
||||
.getFellow("personalTimesheetsPopup");
|
||||
personalTimesheetsDatebox = (Datebox) window
|
||||
.getFellow("personalTimesheetsDatebox");
|
||||
personalTimesheetsBandboxSearch = (BandboxSearch) window
|
||||
.getFellow("personalTimesheetsBandboxSearch");
|
||||
clearFilterDates();
|
||||
}
|
||||
|
||||
|
|
@ -1616,20 +1616,20 @@ public class WorkReportCRUDController extends GenericForwardComposer implements
|
|||
return workReportModel.getBoundWorkers();
|
||||
}
|
||||
|
||||
public void createOrEditMonthlyTimesheet() {
|
||||
Date date = monthlyTimesheetsDatebox.getValue();
|
||||
public void createOrEditPersonalTimesheet() {
|
||||
Date date = personalTimesheetsDatebox.getValue();
|
||||
if (date == null) {
|
||||
throw new WrongValueException(monthlyTimesheetsDatebox,
|
||||
throw new WrongValueException(personalTimesheetsDatebox,
|
||||
_("Please set a date"));
|
||||
}
|
||||
Resource resource = (Resource) monthlyTimesheetsBandboxSearch
|
||||
Resource resource = (Resource) personalTimesheetsBandboxSearch
|
||||
.getSelectedElement();
|
||||
if (resource == null) {
|
||||
throw new WrongValueException(monthlyTimesheetsBandboxSearch,
|
||||
throw new WrongValueException(personalTimesheetsBandboxSearch,
|
||||
_("Please select a worker"));
|
||||
}
|
||||
|
||||
monthlyTimesheetController.goToCreateOrEditFormForResource(
|
||||
personalTimesheetController.goToCreateOrEditFormForResource(
|
||||
LocalDate.fromDateFields(date), resource);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public class WorkReportDTO {
|
|||
|
||||
WorkReportType workReportType = workReport.getWorkReportType();
|
||||
this.type = workReportType.getName();
|
||||
if (workReportType.isMonthlyTimesheetsType()) {
|
||||
if (workReportType.isPersonalTimesheetsType()) {
|
||||
this.type += " - " + workReport.getResource().getShortDescription();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -629,11 +629,11 @@ public class WorkReportModel extends IntegrationEntityModel implements
|
|||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean isMonthlyTimesheet(WorkReport workReport) {
|
||||
public boolean isPersonalTimesheet(WorkReport workReport) {
|
||||
try {
|
||||
return workReportTypeDAO.find(
|
||||
workReport.getWorkReportType().getId())
|
||||
.isMonthlyTimesheetsType();
|
||||
.isPersonalTimesheetsType();
|
||||
} catch (InstanceNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import org.libreplan.web.common.MessagesForUser;
|
|||
import org.libreplan.web.common.components.Autocomplete;
|
||||
import org.libreplan.web.common.components.bandboxsearch.BandboxSearch;
|
||||
import org.libreplan.web.security.SecurityUtils;
|
||||
import org.libreplan.web.users.dashboard.IMonthlyTimesheetController;
|
||||
import org.libreplan.web.users.dashboard.IPersonalTimesheetController;
|
||||
import org.zkoss.ganttz.IPredicate;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
|
|
@ -109,7 +109,7 @@ public class WorkReportQueryController extends GenericForwardComposer {
|
|||
private IWorkReportCRUDControllerEntryPoints workReportCRUD;
|
||||
|
||||
@javax.annotation.Resource
|
||||
private IMonthlyTimesheetController monthlyTimesheetController;
|
||||
private IPersonalTimesheetController personalTimesheetController;
|
||||
|
||||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
|
|
@ -329,9 +329,9 @@ public class WorkReportQueryController extends GenericForwardComposer {
|
|||
if (SecurityUtils.isSuperuserOrUserInRoles(UserRole.ROLE_TIMESHEETS)) {
|
||||
workReportCRUD.goToEditForm(workReport);
|
||||
} else if (SecurityUtils.isUserInRole(UserRole.ROLE_BOUND_USER)
|
||||
&& workReportModel.isMonthlyTimesheet(workReport)
|
||||
&& workReportModel.isPersonalTimesheet(workReport)
|
||||
&& belongsToCurrentUser(line)) {
|
||||
monthlyTimesheetController
|
||||
personalTimesheetController
|
||||
.goToCreateOrEditForm(line.getLocalDate());
|
||||
} else {
|
||||
messagesForUser.showMessage(Level.WARNING,
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public class WorkReportTypeCRUDController extends BaseCRUDController<WorkReportT
|
|||
private OrderedFieldsAndLabelsRowRenderer orderedFieldsAndLabesRowRenderer = new OrderedFieldsAndLabelsRowRenderer();
|
||||
|
||||
public List<WorkReportType> getWorkReportTypes() {
|
||||
return workReportTypeModel.getWorkReportTypesExceptMonthlyTimeSheets();
|
||||
return workReportTypeModel.getWorkReportTypesExceptPersonalTimeSheets();
|
||||
}
|
||||
|
||||
public WorkReportType getWorkReportType() {
|
||||
|
|
|
|||
|
|
@ -118,11 +118,11 @@ public class WorkReportTypeModel extends IntegrationEntityModel implements
|
|||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<WorkReportType> getWorkReportTypesExceptMonthlyTimeSheets() {
|
||||
public List<WorkReportType> getWorkReportTypesExceptPersonalTimeSheets() {
|
||||
List<WorkReportType> list = workReportTypeDAO.list(WorkReportType.class);
|
||||
try {
|
||||
list.remove(workReportTypeDAO
|
||||
.findUniqueByName(PredefinedWorkReportTypes.MONTHLY_TIMESHEETS
|
||||
.findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS
|
||||
.getName()));
|
||||
} catch (NonUniqueResultException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -151,9 +151,9 @@ public class WorkReportTypeModel extends IntegrationEntityModel implements
|
|||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public void initEdit(WorkReportType workReportType) {
|
||||
if (workReportType.isMonthlyTimesheetsType()) {
|
||||
if (workReportType.isPersonalTimesheetsType()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Monthly timesheets timesheet template cannot be edited");
|
||||
"Personal timesheets timesheet template cannot be edited");
|
||||
}
|
||||
|
||||
setListing(false);
|
||||
|
|
@ -220,9 +220,9 @@ public class WorkReportTypeModel extends IntegrationEntityModel implements
|
|||
@Override
|
||||
@Transactional
|
||||
public void confirmRemove(WorkReportType workReportType) {
|
||||
if (workReportType.isMonthlyTimesheetsType()) {
|
||||
if (workReportType.isPersonalTimesheetsType()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Monthly timesheets timesheet template cannot be removed");
|
||||
"Personal timesheets timesheet template cannot be removed");
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -69,10 +69,19 @@
|
|||
selectedElement="@{configurationController.defaultCalendar}" />
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Hours type for monthly timesheets')}" />
|
||||
<label value="${i18n:_('Hours type for personal timesheets')}" />
|
||||
<bandboxSearch
|
||||
finder="TypeOfWorkHoursBandboxFinder"
|
||||
selectedElement="@{configurationController.monthlyTimesheetsTypeOfWorkHours, access='both'}" />
|
||||
selectedElement="@{configurationController.personalTimesheetsTypeOfWorkHours, access='both'}" />
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Personal timesheets peridocity')}" />
|
||||
<listbox model="@{configurationController.personalTimesheetsPeriodicities}"
|
||||
itemRenderer="@{configurationController.personalTimesheetsPeriodicityRenderer}"
|
||||
selectedItem="@{configurationController.selectedPersonalTimesheetsPeriodicity}"
|
||||
disabled="@{configurationController.personalTimesheetsPeriodicityDisabled}"
|
||||
tooltiptext="@{configurationController.personalTimesheetsPeriodicityTooltip}"
|
||||
mold="select" />
|
||||
</row>
|
||||
<row>
|
||||
<label
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
<http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<groupbox apply="org.libreplan.web.users.dashboard.MonthlyTimesheetsAreaController">
|
||||
<caption label="${i18n:_('Monthly timesheets')}" />
|
||||
<groupbox apply="org.libreplan.web.users.dashboard.PersonalTimesheetsAreaController">
|
||||
<caption label="${i18n:_('Personal timesheets')}" />
|
||||
|
||||
<grid model="@{controller.monthlyTimesheets}" mold="paging"
|
||||
pageSize="10" rowRenderer="@{controller.monthlyTimesheetsRenderer}"
|
||||
<grid model="@{controller.personalTimesheets}" mold="paging"
|
||||
pageSize="10" rowRenderer="@{controller.personalTimesheetsRenderer}"
|
||||
sclass="clickable-rows">
|
||||
<columns sizable="true">
|
||||
<column label="${i18n:_('Date')}"
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<?page id="exceptionDayTypesList" title="${i18n:_('LibrePlan: Monthly timesheet')}" ?>
|
||||
<?page id="exceptionDayTypesList" title="${i18n:_('LibrePlan: Personal timesheet')}" ?>
|
||||
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
|
||||
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
|
||||
|
||||
|
|
@ -28,8 +28,8 @@
|
|||
<?link rel="stylesheet" type="text/css" href="/common/css/user_dashboard.css"?>
|
||||
|
||||
<zk>
|
||||
<window apply="org.libreplan.web.users.dashboard.MonthlyTimesheetController"
|
||||
self="@{define(content)}" title="${i18n:_('Monthly timesheet')}">
|
||||
<window apply="org.libreplan.web.users.dashboard.PersonalTimesheetController"
|
||||
self="@{define(content)}" title="${i18n:_('Personal timesheet')}">
|
||||
|
||||
<div id="messagesContainer" />
|
||||
|
||||
|
|
@ -48,22 +48,22 @@
|
|||
<rows>
|
||||
<row>
|
||||
<label value="${i18n:_('Date')}" />
|
||||
<hbox align="pack">
|
||||
<div visible="@{controller.currentUser}">
|
||||
<button id="previousMonth"
|
||||
image="/common/img/ico_step_left.png" sclass="icono"
|
||||
onClick="controller.previousMonth();"
|
||||
tooltiptext="${i18n:_('Previous')}"
|
||||
disabled="@{controller.firstMonth}" />
|
||||
</div>
|
||||
|
||||
<label value="@{controller.date}" />
|
||||
<div visible="@{controller.currentUser}">
|
||||
<button id="nextMonth"
|
||||
onClick="controller.nextMonth();" image="/common/img/ico_step_right.png"
|
||||
tooltiptext="${i18n:_('Next')}" sclass="icono"
|
||||
disabled="@{controller.lastMonth}" />
|
||||
</div></hbox>
|
||||
<hbox align="pack">
|
||||
<div visible="@{controller.currentUser}">
|
||||
<button id="previousPeriod"
|
||||
image="/common/img/ico_step_left.png" sclass="icono"
|
||||
onClick="controller.previousPeriod();"
|
||||
tooltiptext="${i18n:_('Previous')}"
|
||||
disabled="@{controller.firstPeriod}" />
|
||||
</div>
|
||||
<label value="@{controller.timesheetString}" />
|
||||
<div visible="@{controller.currentUser}">
|
||||
<button id="nextPeriod"
|
||||
onClick="controller.nextPeriod();" image="/common/img/ico_step_right.png"
|
||||
tooltiptext="${i18n:_('Next')}" sclass="icono"
|
||||
disabled="@{controller.lastPeriod}" />
|
||||
</div>
|
||||
</hbox>
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Resource')}" />
|
||||
|
|
@ -81,8 +81,8 @@
|
|||
</columns>
|
||||
<rows>
|
||||
<row visible="@{controller.hasOtherReports}">
|
||||
<label value="${i18n:_('Total monthly timesheet')}" />
|
||||
<label id="summaryTotalMonthlyTimesheet" />
|
||||
<label value="${i18n:_('Total personal timesheet')}" />
|
||||
<label id="summaryTotalPersonalTimesheet" />
|
||||
</row>
|
||||
<row visible="@{controller.hasOtherReports}">
|
||||
<label value="${i18n:_('Total other')}" />
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
<?link rel="stylesheet" type="text/css" href="/common/css/libreplan_zk.css"?>
|
||||
|
||||
<?component name="my-tasks-area" inline="true" macroURI="_myTasksArea.zul"?>
|
||||
<?component name="monthly-timesheets-area" inline="true" macroURI="_monthlyTimesheetsArea.zul"?>
|
||||
<?component name="personal-timesheets-area" inline="true" macroURI="_personalTimesheetsArea.zul"?>
|
||||
<?component name="expenses-area" inline="true" macroURI="_expensesArea.zul"?>
|
||||
|
||||
<zk>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
<my-tasks-area />
|
||||
|
||||
<monthly-timesheets-area />
|
||||
<personal-timesheets-area />
|
||||
|
||||
<expenses-area />
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@
|
|||
onClick="controller.onCreateNewWorkReport()"/>
|
||||
</hbox>
|
||||
</div>
|
||||
<popup id="monthlyTimesheetsPopup" width="300px">
|
||||
<popup id="personalTimesheetsPopup" width="300px">
|
||||
<grid>
|
||||
<columns>
|
||||
<column width="50px"/>
|
||||
|
|
@ -116,11 +116,11 @@
|
|||
<rows>
|
||||
<row>
|
||||
<label value="${i18n:_('Date')}" />
|
||||
<datebox id="monthlyTimesheetsDatebox" />
|
||||
<datebox id="personalTimesheetsDatebox" />
|
||||
</row>
|
||||
<row>
|
||||
<label value="${i18n:_('Worker')}" />
|
||||
<bandboxSearch id="monthlyTimesheetsBandboxSearch"
|
||||
<bandboxSearch id="personalTimesheetsBandboxSearch"
|
||||
finder="ResourceBandboxFinder"
|
||||
model="@{controller.boundWorkers}"
|
||||
widthBandbox="200px"
|
||||
|
|
@ -128,8 +128,8 @@
|
|||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<button onClick="controller.createOrEditMonthlyTimesheet();"
|
||||
label="${i18n:_('Go to monthly timesheet')}" />
|
||||
<button onClick="controller.createOrEditPersonalTimesheet();"
|
||||
label="${i18n:_('Go to personal timesheet')}" />
|
||||
</popup>
|
||||
</window>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import org.junit.runner.RunWith;
|
|||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.business.common.entities.IConfigurationBootstrap;
|
||||
import org.libreplan.business.common.entities.IMonthlyTimesheetsTypeOfWorkHoursBootstrap;
|
||||
import org.libreplan.business.common.entities.IPersonalTimesheetsTypeOfWorkHoursBootstrap;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.costcategories.daos.ITypeOfWorkHoursDAO;
|
||||
import org.libreplan.business.costcategories.entities.ITypeOfWorkHoursBootstrap;
|
||||
|
|
@ -86,7 +86,7 @@ public class TypeOfWorkHoursServiceTest {
|
|||
private ITypeOfWorkHoursBootstrap typeOfWorkHoursBootstrap;
|
||||
|
||||
@Autowired
|
||||
private IMonthlyTimesheetsTypeOfWorkHoursBootstrap monthlyTimesheetsTypeOfWorkHoursBootstrap;
|
||||
private IPersonalTimesheetsTypeOfWorkHoursBootstrap personalTimesheetsTypeOfWorkHoursBootstrap;
|
||||
|
||||
@Before
|
||||
public void loadRequiredData() {
|
||||
|
|
@ -96,7 +96,7 @@ public class TypeOfWorkHoursServiceTest {
|
|||
public Void execute() {
|
||||
configurationBootstrap.loadRequiredData();
|
||||
typeOfWorkHoursBootstrap.loadRequiredData();
|
||||
monthlyTimesheetsTypeOfWorkHoursBootstrap.loadRequiredData();
|
||||
personalTimesheetsTypeOfWorkHoursBootstrap.loadRequiredData();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue