ItEr22S08CUAltaCalendarioLaboralItEr21S10: Support for creation of basic calendars.

This commit is contained in:
Manuel Rego Casasnovas 2009-08-19 09:12:44 +02:00 committed by Óscar González Fernández
parent 3577620603
commit e1f863e282
10 changed files with 489 additions and 66 deletions

View file

@ -7,7 +7,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
import org.navalplanner.business.common.BaseEntity;
@ -78,6 +77,10 @@ public class BaseCalendar extends BaseEntity implements IValidable {
return name;
}
public Map<Integer, Integer> getHoursPerDay() {
return hoursPerDay;
}
public Integer getHours(Days day) {
if ((getHoursForDay(day) == null) && (parent != null)) {
return parent.getHours(day);
@ -338,11 +341,7 @@ public class BaseCalendar extends BaseEntity implements IValidable {
* calendar restrictions.
*/
public Integer getWorkableHoursPerWeek(Date date) {
DateTime week = new DateTime(date);
DateTime init = week.dayOfWeek().withMinimumValue();
DateTime end = week.dayOfWeek().withMaximumValue();
return getWorkableHours(init.toDate(), end.toDate());
return getWorkableHoursPerWeek(new LocalDate(date));
}
/**
@ -358,14 +357,6 @@ public class BaseCalendar extends BaseEntity implements IValidable {
@Override
public void checkValid() throws ValidationException {
if (parent == null) {
if (isNullSomeDay()) {
throw new ValidationException(
"Daily hours could not have the default value "
+ "if the calendar is not derivated");
}
}
if ((nextCalendar == null) && (expiringDate != null)) {
throw new ValidationException("A next calendar should exist "
+ "if current calendar has a expiring date fixed");
@ -376,15 +367,6 @@ public class BaseCalendar extends BaseEntity implements IValidable {
}
}
private boolean isNullSomeDay() {
for (Integer hours : hoursPerDay.values()) {
if (hours == null) {
return true;
}
}
return false;
}
/**
* Creates a new {@link BaseCalendar} derived from the current calendar. The
* new calendar will be the child of the current calendar.

View file

@ -20,11 +20,11 @@
<element column="HOURS" type="integer" />
</map>
<one-to-one name="parent" class="BaseCalendar" access="field"/>
<many-to-one name="parent" class="BaseCalendar" access="field"/>
<one-to-one name="previousCalendar" class="BaseCalendar" access="field"/>
<many-to-one name="previousCalendar" class="BaseCalendar" unique="true" />
<one-to-one name="nextCalendar" class="BaseCalendar" access="field"/>
<many-to-one name="nextCalendar" class="BaseCalendar" unique="true" />
<property name="expiringDate" access="field"
type="org.joda.time.contrib.hibernate.PersistentLocalDate"/>

View file

@ -1,6 +1,8 @@
package org.navalplanner.business.test.calendars.daos;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@ -80,4 +82,33 @@ public class BaseCalendarDAOTest {
}
@Test
public void saveNextCalendar() {
BaseCalendar calendar = BaseCalendarTest.createBasicCalendar();
baseCalendarDAO.save(calendar);
BaseCalendar nextCalendar = calendar.newVersion();
baseCalendarDAO.save(nextCalendar);
try {
BaseCalendar savedCalendar = baseCalendarDAO.find(calendar.getId());
assertThat(savedCalendar.getPreviousCalendar(), nullValue());
assertThat(savedCalendar.getNextCalendar(), notNullValue());
assertThat(savedCalendar.getNextCalendar(), equalTo(nextCalendar));
BaseCalendar savedNextCalendar = baseCalendarDAO
.find(nextCalendar
.getId());
assertThat(savedNextCalendar.getPreviousCalendar(), notNullValue());
assertThat(savedNextCalendar.getNextCalendar(), nullValue());
assertThat(savedNextCalendar.getPreviousCalendar(),
equalTo(calendar));
} catch (InstanceNotFoundException e) {
fail("It should not throw an exception");
}
}
}

View file

@ -87,12 +87,6 @@ public class BaseCalendarTest {
}
}
@Test(expected = ValidationException.class)
public void testInvalidCalendar() throws ValidationException {
BaseCalendar calendar = new BaseCalendar();
calendar.checkValid();
}
@Test
public void testGetWorkableHoursBasic() {
BaseCalendar calendar = createBasicCalendar();
@ -435,16 +429,14 @@ public class BaseCalendarTest {
assertTrue(calendarFixture.isDefault(Days.SUNDAY));
}
@Test(expected = ValidationException.class)
public void testDefaultValues() throws ValidationException {
@Test
public void testDefaultValues() {
BaseCalendar calendar = createBasicCalendar();
assertFalse(calendar.isDefault(Days.MONDAY));
calendar.setDefault(Days.MONDAY);
assertTrue(calendar.isDefault(Days.MONDAY));
calendar.checkValid();
}
@Test

View file

@ -1,8 +1,12 @@
package org.navalplanner.web.calendars;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.BaseCalendar.DayType;
import org.navalplanner.business.calendars.entities.BaseCalendar.Days;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
@ -10,7 +14,16 @@ import org.navalplanner.web.common.MessagesForUser;
import org.navalplanner.web.common.OnlyOneVisible;
import org.navalplanner.web.common.Util;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.Intbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.api.Window;
/**
@ -38,6 +51,8 @@ public class BaseCalendarCRUDController extends GenericForwardComposer {
private Component messagesContainer;
private HoursPerDayRenderer hoursPerDayRenderer = new HoursPerDayRenderer();
public List<BaseCalendar> getBaseCalendars() {
return baseCalendarModel.getBaseCalendars();
}
@ -66,6 +81,7 @@ public class BaseCalendarCRUDController extends GenericForwardComposer {
public void goToEditForm(BaseCalendar baseCalendar) {
baseCalendarModel.initEdit(baseCalendar);
selectDay(new Date());
getVisibility().showOnly(editWindow);
Util.reloadBindings(editWindow);
}
@ -119,13 +135,9 @@ public class BaseCalendarCRUDController extends GenericForwardComposer {
messagesForUser.showMessage(Level.INFO, "removed " + name);
}
public void goToEditForm() {
getVisibility().showOnly(editWindow);
Util.reloadBindings(editWindow);
}
public void goToCreateForm() {
baseCalendarModel.initCreate();
selectDay(new Date());
getVisibility().showOnly(createWindow);
Util.reloadBindings(createWindow);
}
@ -138,4 +150,125 @@ public class BaseCalendarCRUDController extends GenericForwardComposer {
return visibility;
}
public void selectDay(Date date) {
baseCalendarModel.selectDay(date);
reloadCurrentWindow();
}
public String getTypeOfDay() {
DayType typeOfDay = baseCalendarModel.getTypeOfDay();
if (typeOfDay == null) {
return "";
}
switch (typeOfDay) {
case ANCESTOR_EXCEPTION:
return "Derived excpetion";
case OWN_EXCEPTION:
return "Exception";
case ZERO_HOURS:
return "Not working day";
case NORMAL:
default:
return "Normal";
}
}
public Integer getHoursOfDay() {
return baseCalendarModel.getHoursOfDay();
}
public void createException(Integer hours) {
// TODO check hours parameter is >= 0
baseCalendarModel.createException(hours);
reloadCurrentWindow();
}
public List<Days> getHoursPerDay() {
return Arrays.asList(Days.values());
}
public boolean isNotExceptional() {
return !baseCalendarModel.isExceptional();
}
public void removeException() {
baseCalendarModel.removeException();
reloadCurrentWindow();
}
public HoursPerDayRenderer getHoursPerDayRenderer() {
return hoursPerDayRenderer;
}
public class HoursPerDayRenderer implements ListitemRenderer {
@Override
public void render(Listitem item, Object data) throws Exception {
final Days day = (Days) data;
Listcell labelListcell = new Listcell();
labelListcell.appendChild(new Label(day.toString()));
item.appendChild(labelListcell);
Listcell hoursListcell = new Listcell();
Intbox hoursIntbox = Util.bind(new Intbox(),
new Util.Getter<Integer>() {
@Override
public Integer get() {
return baseCalendarModel.getHours(day);
}
}, new Util.Setter<Integer>() {
@Override
public void set(Integer value) {
baseCalendarModel.setHours(day,
value);
}
});
hoursIntbox.addEventListener(Events.ON_CHANGE, new EventListener() {
@Override
public void onEvent(Event event) throws Exception {
reloadCurrentWindow();
}
});
hoursListcell.appendChild(hoursIntbox);
item.appendChild(hoursListcell);
if (baseCalendarModel.isDerived()) {
Listcell defaultListcell = new Listcell();
defaultListcell.appendChild(Util.bind(new Checkbox(),
new Util.Getter<Boolean>() {
@Override
public Boolean get() {
return baseCalendarModel.isDefault(day);
}
}, new Util.Setter<Boolean>() {
@Override
public void set(Boolean value) {
baseCalendarModel.setDefault(day);
}
}));
item.appendChild(defaultListcell);
}
}
}
private void reloadCurrentWindow() {
if (baseCalendarModel.isEditing()) {
Util.reloadBindings(editWindow);
} else {
Util.reloadBindings(createWindow);
}
}
}

View file

@ -1,5 +1,6 @@
package org.navalplanner.web.calendars;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.Validate;
@ -7,6 +8,9 @@ import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.calendars.daos.IBaseCalendarDAO;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.ExceptionDay;
import org.navalplanner.business.calendars.entities.BaseCalendar.DayType;
import org.navalplanner.business.calendars.entities.BaseCalendar.Days;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,6 +34,8 @@ public class BaseCalendarModel implements IBaseCalendarModel {
*/
private BaseCalendar baseCalendar;
private Date selectedDate;
private boolean editing = false;
private ClassValidator<BaseCalendar> baseCalendarValidator = new ClassValidator<BaseCalendar>(
@ -67,6 +73,12 @@ public class BaseCalendarModel implements IBaseCalendarModel {
Validate.notNull(baseCalendar);
this.baseCalendar = getFromDB(baseCalendar);
forceLoadExceptionDays();
}
private void forceLoadExceptionDays() {
baseCalendar.getHoursPerDay().size();
baseCalendar.getExceptions().size();
}
private BaseCalendar getFromDB(BaseCalendar baseCalendar) {
@ -102,6 +114,97 @@ public class BaseCalendarModel implements IBaseCalendarModel {
return this.editing;
}
@Override
public void selectDay(Date date) {
this.selectedDate = date;
}
@Override
@Transactional(readOnly = true)
public Integer getHoursOfDay() {
if (baseCalendar == null) {
return null;
}
return baseCalendar.getWorkableHours(selectedDate);
}
@Override
@Transactional(readOnly = true)
public DayType getTypeOfDay() {
if (baseCalendar == null) {
return null;
}
return baseCalendar.getType(selectedDate);
}
@Override
@Transactional(readOnly = true)
public void createException(Integer hours) {
if (getTypeOfDay().equals(DayType.OWN_EXCEPTION)) {
baseCalendar.updateExceptionDay(selectedDate, hours);
} else {
ExceptionDay day = ExceptionDay.create(selectedDate, hours);
baseCalendar.addExceptionDay(day);
}
}
@Override
public Integer getHours(Days day) {
if (baseCalendar == null) {
return null;
}
return baseCalendar.getHours(day);
}
@Override
public Boolean isDefault(Days day) {
if (baseCalendar == null) {
return false;
}
return baseCalendar.isDefault(day);
}
@Override
public void setDefault(Days day) {
if (baseCalendar != null) {
baseCalendar.setDefault(day);
}
}
@Override
public void setHours(Days day, Integer hours) {
if (baseCalendar != null) {
baseCalendar.setHours(day, hours);
}
}
@Override
public boolean isExceptional() {
if (baseCalendar == null) {
return false;
}
ExceptionDay day = baseCalendar.getOwnExceptionDay(selectedDate);
return (day != null);
}
@Override
public void removeException() {
baseCalendar.removeExceptionDay(selectedDate);
}
@Override
public boolean isDerived() {
if (baseCalendar == null) {
return false;
}
return baseCalendar.isDerived();
}
/*
* Final conversation steps
@ -116,6 +219,7 @@ public class BaseCalendarModel implements IBaseCalendarModel {
throw new ValidationException(invalidValues);
}
baseCalendar.checkValid();
baseCalendarDAO.save(baseCalendar);
}

View file

@ -1,8 +1,11 @@
package org.navalplanner.web.calendars;
import java.util.Date;
import java.util.List;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.BaseCalendar.DayType;
import org.navalplanner.business.calendars.entities.BaseCalendar.Days;
import org.navalplanner.business.common.exceptions.ValidationException;
/**
@ -61,6 +64,27 @@ public interface IBaseCalendarModel {
boolean isEditing();
void selectDay(Date date);
DayType getTypeOfDay();
Integer getHoursOfDay();
void createException(Integer hours);
Integer getHours(Days day);
void setHours(Days day, Integer hours);
Boolean isDefault(Days day);
void setDefault(Days day);
boolean isExceptional();
void removeException();
boolean isDerived();
/*
* Final conversation steps

View file

@ -1,24 +1,76 @@
<window id="${arg.top_id}" title="${arg.title}">
<tabbox>
<tabs>
<tab label="Edition"></tab>
</tabs>
<tabpanels>
<tabpanel>
<grid fixedLayout="false">
<rows>
<row>
<label value="Name" />
<textbox value="@{controller.baseCalendar.name}" />
</row>
</rows>
</grid>
</tabpanel>
</tabpanels>
</tabbox>
<window id="${arg.top_id}" title="${arg.title}" border="normal">
<button onClick="controller.save();"
label="${arg.save_button_label}" />
<button onClick="controller.cancel();"
label="${arg.cancel_button_label}" />
</window>
<vbox>
<hbox>
<vbox>
<hbox>
<label value="Name" />
<textbox value="@{controller.baseCalendar.name}" />
</hbox>
<hbox>
<label value="Type" />
<vbox>
<label value="Normal" if="${!controller.isDerived}" />
<label value="Derived" if="${controller.isDerived}" />
<combobox if="${controller.isDerived}"
model="@{controller.baseCalendars}">
<comboitem self="@{each='baseCalnedar'}" value="@{baseCalnedar}"
label="@{baseCalnedar.name}" />
</combobox>
</vbox>
</hbox>
<listbox id="hoursPerDay"
model="@{controller.getHoursPerDay}"
itemRenderer="@{controller.hoursPerDayRenderer}">
<listhead>
<listheader label="Day of week" />
<listheader label="Hours" />
<listheader label="By default" />
</listhead>
</listbox>
</vbox>
<vbox id="dayInformation">
<calendar id="calendarWidget"
onChange="controller.selectDay(calendarWidget.value);" />
<hbox>
<label value="Type of day" />
<label value="@{controller.typeOfDay}" />
</hbox>
<hbox>
<label value="Hours of day" />
<label value="@{controller.hoursOfDay}" />
</hbox>
<hbox>
<vbox>
<button label="Create exception"
onClick="controller.createException(exceptionHours.value);" />
<button disabled="@{controller.isNotExceptional}"
label="Remove exception"
onClick="controller.removeException();" />
</vbox>
<intbox id="exceptionHours" value="0" />
</hbox>
</vbox>
</hbox>
<hbox>
<button onClick="controller.save();"
label="${arg.save_button_label}" />
<button onClick="controller.cancel();"
label="${arg.cancel_button_label}" />
</hbox>
</vbox>
</window>

View file

@ -15,9 +15,9 @@
apply="org.navalplanner.web.calendars.BaseCalendarCRUDController">
<vbox id="messagesContainer"></vbox>
<list top_id="listWindow" />
<edition top_id="createWindow" title="Create"
<edition top_id="createWindow" title="Create Calendar"
save_button_label="Save" cancel_button_label="Cancel" />
<edition top_id="editWindow" title="Edit Advance Type Data"
<edition top_id="editWindow" title="Edit Calendar"
save_button_label="Save" cancel_button_label="Cancel" />
<window visible="@{controller.confirmingRemove}"
id="confirmRemove" title="Confirmation" sizable="true"

View file

@ -0,0 +1,105 @@
package org.navalplanner.web.calendars;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.navalplanner.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE;
import static org.navalplanner.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.calendars.entities.BaseCalendar;
import org.navalplanner.business.calendars.entities.BaseCalendar.Days;
import org.navalplanner.business.common.exceptions.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
/**
* Tests for {@link BaseCalendarModel}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE })
@Transactional
public class BaseCalendarModelTest {
@Autowired
private IBaseCalendarModel baseCalendarModel;
@Test
public void testCreateAndSave() {
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(0));
baseCalendarModel.initCreate();
BaseCalendar baseCalendar = baseCalendarModel.getBaseCalendar();
setHours(baseCalendar, 8);
try {
baseCalendarModel.confirmSave();
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(1));
assertThat(baseCalendarModel.getBaseCalendars().get(0).getId(),
equalTo(baseCalendar.getId()));
assertThat(baseCalendarModel.getBaseCalendars().get(0).getHours(
Days.MONDAY), equalTo(8));
} catch (ValidationException e) {
fail("It should not throw an exception");
}
}
private void setHours(BaseCalendar baseCalendar, Integer hours) {
baseCalendar.setHours(Days.MONDAY, hours);
baseCalendar.setHours(Days.TUESDAY, hours);
baseCalendar.setHours(Days.WEDNESDAY, hours);
baseCalendar.setHours(Days.THURSDAY, hours);
baseCalendar.setHours(Days.FRIDAY, hours);
baseCalendar.setHours(Days.SATURDAY, hours);
baseCalendar.setHours(Days.SUNDAY, hours);
}
@Test
public void testEditAndSave() {
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(0));
saveOneCalendar();
BaseCalendar baseCalendar = baseCalendarModel.getBaseCalendars().get(0);
baseCalendarModel.initEdit(baseCalendar);
setHours(baseCalendar, 4);
try {
baseCalendarModel.confirmSave();
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(1));
assertThat(baseCalendarModel.getBaseCalendars().get(0).getId(),
equalTo(baseCalendar.getId()));
assertThat(baseCalendarModel.getBaseCalendars().get(0).getHours(
Days.MONDAY), equalTo(4));
} catch (ValidationException e) {
fail("It should not throw an exception");
}
}
private void saveOneCalendar() {
baseCalendarModel.initCreate();
setHours(baseCalendarModel.getBaseCalendar(), 8);
try {
baseCalendarModel.confirmSave();
} catch (ValidationException e) {
fail("It should not throw an exception");
}
}
@Test
public void testRemove() {
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(0));
saveOneCalendar();
BaseCalendar baseCalendar = baseCalendarModel.getBaseCalendars().get(0);
baseCalendarModel.initRemove(baseCalendar);
baseCalendarModel.confirmRemove();
assertThat(baseCalendarModel.getBaseCalendars().size(), equalTo(0));
}
}