/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.timesheet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import org.junit.Test;
import org.projectforge.access.AccessException;
import org.projectforge.common.DateHolder;
import org.projectforge.common.DatePrecision;
import org.projectforge.core.UserException;
import org.projectforge.task.TaskDO;
import org.projectforge.task.TaskDao;
import org.projectforge.task.TaskStatus;
import org.projectforge.test.TestBase;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
public class TimesheetTestFork extends TestBase
{
// private static final Logger log = Logger.getLogger(TaskTest.class);
TimesheetDao timesheetDao;
TaskDao taskDao;
private TransactionTemplate txTemplate;
DateHolder date = new DateHolder(new Date(), DatePrecision.MINUTE_15, Locale.GERMAN);
public void setTimesheetDao(final TimesheetDao timesheetDao)
{
this.timesheetDao = timesheetDao;
}
public void setTaskDao(final TaskDao taskDao)
{
this.taskDao = taskDao;
}
public void setTxTemplate(final TransactionTemplate txTemplate)
{
this.txTemplate = txTemplate;
}
@Test
public void hasSelectAccess()
{
final Serializable[] id = new Serializable[1];
txTemplate.execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status)
{
getInitTestDB().addTask("ts-hasSelectAccess-task", "root");
getInitTestDB().addUser("ts-hasSelectAccess-user");
final TimesheetDO ts = new TimesheetDO();
final long current = System.currentTimeMillis();
ts.setTask(initTestDB.getTask("ts-hasSelectAccess-task")).setUser(getUser("ts-hasSelectAccess-user")).setLocation("Office")
.setDescription("A lot of stuff done and more.").setStartTime(new Timestamp(current)).setStopTime(
new Timestamp(current + 2 * 60 * 60 * 1000));
id[0] = timesheetDao.internalSave(ts);
timesheetDao.internalSave(ts);
return null;
}
});
txTemplate.execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status)
{
logon(getUser("ts-hasSelectAccess-user"));
final TimesheetDO ts = timesheetDao.getById(id[0]); // Has no access, but is owner of this timesheet
assertEquals("Field should be hidden", TimesheetDao.HIDDEN_FIELD_MARKER, ts.getShortDescription());
assertEquals("Field should be hidden", TimesheetDao.HIDDEN_FIELD_MARKER, ts.getDescription());
assertEquals("Field should be hidden", TimesheetDao.HIDDEN_FIELD_MARKER, ts.getLocation());
return null;
}
});
txTemplate.execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status)
{
final TimesheetDO ts = timesheetDao.internalGetById(id[0]);
assertEquals("Field should not be overwritten", "A lot of stuff done and more.", ts.getShortDescription());
assertEquals("Field should not be overwritten", "A lot of stuff done and more.", ts.getDescription());
assertEquals("Field should not be overwritten", "Office", ts.getLocation());
return null;
}
});
}
@Test
public void saveAndModify()
{
getInitTestDB().addTask("saveAndModify-task", "root");
getInitTestDB().addUser("saveAndModify-user");
final TimesheetDO ts1 = new TimesheetDO();
final long current = System.currentTimeMillis();
ts1.setStartTime(new Timestamp(current)).setStopTime(new Timestamp(current + 2 * 60 * 60 * 1000));
try {
timesheetDao.internalSave(ts1);
fail("timesheet without task and/or user should not be possible.");
} catch (final Exception ex) {
}
ts1.setTask(getTask("saveAndModify-task"));
try {
timesheetDao.internalSave(ts1);
fail("timesheet without user should not be possible.");
} catch (final Exception ex) {
}
ts1.setTask(null).setUser(getUser("saveAndModify-user"));
try {
timesheetDao.internalSave(ts1);
fail("timesheet without task and/or user should not be possible.");
} catch (final Exception ex) {
}
ts1.setTask(getTask("saveAndModify-task")).setStartTime(new Timestamp(current)).setStopTime(new Timestamp(current + 2 * 60 * 60 * 1000));
timesheetDao.internalSave(ts1);
// ToDo: Check onSaveOrUpdate: kost2Id vs. task!
}
@Test
public void testOverlap()
{
logon(ADMIN);
getInitTestDB().addTask("timesheet", "root");
getInitTestDB().addUser("timesheet-user");
TimesheetDO ts1 = new TimesheetDO().setTask(getTask("timesheet")).setUser(getUser("timesheet-user"));
setTimeperiod(ts1, 21, 8, 0, 21, 16, 0); // 11/21 from 8:00 to 16:00
Serializable id = timesheetDao.save(ts1);
ts1 = timesheetDao.internalGetById(id);
final TimesheetDO ts2 = new TimesheetDO().setTask(getTask("timesheet")).setUser(getUser("timesheet-user"));
setTimeperiod(ts2, 21, 15, 52, 21, 18, 0); // 11/21 from 15:45 to 18:00
try {
timesheetDao.save(ts2); // Overlap with ts1!
fail();
} catch (final UserException ex) {
assertEquals("timesheet.error.timeperiodOverlapDetection", ex.getI18nKey());
}
setTimeperiod(ts2, 21, 7, 0, 21, 8, 15); // 11/21 from 07:00 to 08:15
try {
timesheetDao.save(ts2); // Overlap with ts1!
fail();
} catch (final UserException ex) {
assertEquals("timesheet.error.timeperiodOverlapDetection", ex.getI18nKey());
}
setTimeperiod(ts2, 21, 16, 0, 21, 18, 0); // 11/21 from 16:00 to 18:00
final Serializable id2 = timesheetDao.save(ts2); // No overlap, OK.
TimesheetDO ts3 = new TimesheetDO().setTask(getTask("timesheet")).setUser(getUser("timesheet-user"));
setTimeperiod(ts3, 21, 16, 0, 21, 18, 0); // 11/21 from 16:00 to 18:00
try {
timesheetDao.save(ts3); // Overlap with ts1!
fail();
} catch (final UserException ex) {
assertEquals("timesheet.error.timeperiodOverlapDetection", ex.getI18nKey());
}
txTemplate.execute(new TransactionCallback() {
public Object doInTransaction(final TransactionStatus status)
{
final TimesheetDO t = timesheetDao.internalGetById(id2);
timesheetDao.markAsDeleted(t); // Delete conflicting time sheet
return null;
}
});
id = timesheetDao.save(ts3); // No overlap, OK.
ts3 = timesheetDao.getById(id);
try {
timesheetDao.undelete(ts2); // Overlap with ts1!
fail();
} catch (final UserException ex) {
assertEquals("timesheet.error.timeperiodOverlapDetection", ex.getI18nKey());
}
}
@Test
public void testTimesheetProtection()
{
// Create test tasks:
getInitTestDB().addUser("tpt-user");
TaskDO task;
task = initTestDB.addTask("timesheetprotectiontest", "root");
task = initTestDB.addTask("tpt", "timesheetprotectiontest");
task = initTestDB.addTask("tpt.1", "tpt");
task = initTestDB.addTask("tpt.1.1", "tpt.1");
task = initTestDB.addTask("tpt.2", "tpt");
date.setDate(2008, Calendar.OCTOBER, 31, 0, 0, 0);
task.setProtectTimesheetsUntil(date.getDate());
taskDao.internalUpdate(task); // Without check access.
task = initTestDB.addTask("tpt.2.1", "tpt.2");
TimesheetDO sheet = new TimesheetDO();
sheet.setUser(getUser("tpt-user"));
System.out.println(sheet.getUserId());
sheet.setTask(getTask("tpt.2.1"));
setTimeperiod(sheet, 2008, Calendar.OCTOBER, 01, 7, 0, 21, 8, 15); // 10/01 from 07:00 to 08:15
try {
timesheetDao.save(sheet);
fail("AccessException caused by time sheet violation expected.");
} catch (final AccessException ex) {
// OK
}
setTimeperiod(sheet, 2008, Calendar.OCTOBER, 31, 23, 45, 31, 0, 15); // 10/30 from 23:45 to 00:15
try {
timesheetDao.save(sheet);
fail("AccessException caused by time sheet violation expected.");
} catch (final AccessException ex) {
// OK
}
setTimeperiod(sheet, 2008, Calendar.NOVEMBER, 1, 0, 0, 1, 2, 15); // 11/01 from 00:00 to 02:15
final Serializable id = timesheetDao.save(sheet);
sheet = timesheetDao.getById(id);
date.setDate(2008, Calendar.OCTOBER, 31, 23, 45, 0);
sheet.setStartTime(date.getTimestamp());
try {
timesheetDao.update(sheet);
fail("AccessException caused by time sheet violation expected.");
} catch (final AccessException ex) {
// OK
}
task = getTask("tpt.2");
date.setDate(2008, Calendar.NOVEMBER, 30, 0, 0, 0); // Change protection date, so time sheet is now protected.
task.setProtectTimesheetsUntil(date.getDate());
taskDao.internalUpdate(task); // Without check access.
sheet = timesheetDao.getById(id).setDescription("Hurzel"); // Should work, because start and stop time is not modified.
timesheetDao.update(sheet);
date.setDate(2008, Calendar.NOVEMBER, 1, 2, 0, 0);
sheet = timesheetDao.getById(id).setStopTime(date.getTimestamp());
try {
timesheetDao.update(sheet);
fail("AccessException caused by time sheet violation expected.");
} catch (final AccessException ex) {
// OK
}
sheet = timesheetDao.getById(id);
try {
timesheetDao.markAsDeleted(sheet);
fail("AccessException caused by time sheet violation expected.");
} catch (final AccessException ex) {
// OK
}
}
@Test
public void testTaskBookable()
{
initTestDB.addTask("taskBookable", "root");
final TaskDO task1 = initTestDB.addTask("dB.1", "taskBookable");
final TaskDO task2 = initTestDB.addTask("dB.2", "taskBookable");
initTestDB.addTask("dB.1.1", "dB.1");
getInitTestDB().addUser("ttb-user");
TimesheetDO sheet = new TimesheetDO().setUser(getUser("ttb-user")).setTask(getTask("dB.1.1"));
setTimeperiod(sheet, 2009, Calendar.OCTOBER, 01, 7, 0, 01, 8, 15); // 10/01 from 07:00 to 08:15
timesheetDao.save(sheet);
task1.setStatus(TaskStatus.C);
taskDao.internalUpdate(task1);
task2.setStatus(TaskStatus.C);
taskDao.internalUpdate(task2);
sheet = new TimesheetDO().setUser(getUser("ttb-user")).setTask(getTask("dB.1.1"));
setTimeperiod(sheet, 2009, Calendar.OCTOBER, 02, 7, 0, 02, 8, 15); // 10/02 from 07:00 to 08:15
try {
timesheetDao.save(sheet);
fail("Exception expected: Task should not be bookable because parent task is closed.");
} catch (final AccessException ex) {
// OK
}
sheet.setTask(getTask("dB.1"));
try {
timesheetDao.save(sheet);
fail("Exception expected: Task should not be bookable because parent task is closed.");
} catch (final AccessException ex) {
// OK
}
}
private void setTimeperiod(final TimesheetDO timesheet, final int fromDay, final int fromHour, final int fromMinute, final int toDay, final int toHour, final int toMinute)
{
setTimeperiod(timesheet, 1970, Calendar.NOVEMBER, fromDay, fromHour, fromMinute, toDay, toHour, toMinute);
}
private void setTimeperiod(final TimesheetDO timesheet, final int year, final int month, final int fromDay, final int fromHour, final int fromMinute, final int toDay, final int toHour,
final int toMinute)
{
date.setDate(year, month, fromDay, fromHour, fromMinute, 0);
timesheet.setStartTime(date.getTimestamp());
date.setDate(year, month, toDay, toHour, toMinute, 0);
timesheet.setStopTime(date.getTimestamp());
}
}