/* * This file is part of LibrePlan * * Copyright (C) 2012 WirelessGalicia, 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.test.expensesheet.daos; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE; import static org.libreplan.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE; import java.math.BigDecimal; import java.util.Date; import java.util.UUID; import org.joda.time.LocalDate; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.libreplan.business.calendars.daos.IBaseCalendarDAO; import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.common.exceptions.ValidationException; import org.libreplan.business.expensesheet.daos.IExpenseSheetDAO; import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO; import org.libreplan.business.expensesheet.entities.ExpenseSheet; import org.libreplan.business.expensesheet.entities.ExpenseSheetLine; import org.libreplan.business.orders.daos.IOrderDAO; import org.libreplan.business.orders.daos.IOrderElementDAO; import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.orders.entities.OrderLine; import org.libreplan.business.resources.daos.IResourceDAO; import org.libreplan.business.resources.entities.Worker; import org.libreplan.business.scenarios.IScenarioManager; import org.libreplan.business.scenarios.bootstrap.IScenariosBootstrap; import org.libreplan.business.scenarios.entities.OrderVersion; import org.libreplan.business.test.calendars.entities.BaseCalendarTest; import org.libreplan.business.test.planner.daos.ResourceAllocationDAOTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, BUSINESS_SPRING_CONFIG_TEST_FILE }) /** * Test for {@link org.libreplan.business.expensesheet.daos.ExpenseSheetDAO}. * * @author Susana Montes Pedreira <smontes@wirelessgalicia.com> */ public class ExpenseSheetTestDAO { @Before public void loadRequiredData() { transactionService.runOnAnotherTransaction(new IOnTransaction<Void>() { @Override public Void execute() { scenariosBootstrap.loadRequiredData(); return null; } }); } @Autowired private IScenariosBootstrap scenariosBootstrap; @Autowired private IAdHocTransactionService transactionService; @Autowired IExpenseSheetLineDAO expenseSheetLineDAO; @Autowired IExpenseSheetDAO expenseSheetDAO; @Autowired IOrderElementDAO orderElementDAO; @Autowired IOrderDAO orderDAO; @Autowired IResourceDAO resourceDAO; @Autowired private IBaseCalendarDAO calendarDAO; @Autowired private IScenarioManager scenarioManager; @Test @Transactional public void testInSpringContainer() { assertNotNull(orderDAO); assertNotNull(calendarDAO); assertNotNull(orderElementDAO); assertNotNull(expenseSheetDAO); } private Order createValidOrder(String name) { Order order = Order.create(); order.setName(name); order.setCode(UUID.randomUUID().toString()); order.setInitDate(new Date()); BaseCalendar basicCalendar = BaseCalendarTest.createBasicCalendar(); calendarDAO.save(basicCalendar); OrderVersion orderVersion = ResourceAllocationDAOTest.setupVersionUsing(scenarioManager, order); order.useSchedulingDataFor(orderVersion); return order; } private Worker givenValidWorker() { Worker worker = Worker.create(); worker.setFirstName("First name"); worker.setSurname("Surname"); worker.setNif("NIF" + UUID.randomUUID().toString()); return worker; } private OrderElement givenOrderElement(String orderLineCode) { Order order = createValidOrder(orderLineCode + "-order-1"); OrderLine line = OrderLine.create(); line.setCode(orderLineCode); line.setName(orderLineCode + "-name-1"); line.setInitDate(new Date()); order.add(line); return line; } @Test(expected = ValidationException.class) @Transactional public void invalidExpenseSheetWithoutLines() { ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("UUID.randomUUID().toString()"); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); fail("it must throw a exception because the total is empty"); } catch (ValidationException e) { } expense.updateTotal(); expenseSheetDAO.save(expense); expenseSheetDAO.flush(); fail("it must throw a exception because the expense sheet has not lines"); } @Test(expected = ValidationException.class) @Transactional public void validExpenseSheetWithInvalidExpenseSheetLineData() { // Check out the expenseSheet without lines ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("code-expense-sheet-1"); // orderElement empty OrderElement orderElement = null; // A expense sheet with valid value,date but without order element ExpenseSheetLine line1 = ExpenseSheetLine.create(BigDecimal.ZERO, "concept", new LocalDate(), orderElement); line1.setExpenseSheet(expense); expense.add(line1); expenseSheetDAO.save(expense); expenseSheetDAO.flush(); fail("it must throw a exception. The order element not specified"); } @Test @Transactional public void validExpenseSheetWithInvalidValuesInLines() { // Create the expenseSheet without lines ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("code-expense-sheet-1"); // orderElement empty OrderElement orderElement = this.givenOrderElement("order-element-2"); // A expense sheet with valid date and order element, but invalid value ExpenseSheetLine line1 = ExpenseSheetLine.create(null, "concept", new LocalDate(), orderElement); // Add the line to the expense sheet line1.setExpenseSheet(expense); expense.add(line1); try { expenseSheetDAO.save(expense); fail("it must throw a exception. The value is not specified in the expense sheet line."); } catch (ValidationException e) { } line1.setValue(new BigDecimal(-3)); try { expenseSheetDAO.save(expense); fail("it must throw a exception. The total is invalid because it is less than 0."); } catch (ValidationException e) { } ExpenseSheetLine line2 = ExpenseSheetLine.create(BigDecimal.TEN, "concept", new LocalDate(), orderElement); // Add other line to the expense sheet line2.setExpenseSheet(expense); expense.add(line2); try { expenseSheetDAO.save(expense); fail("it must throw a exception. The value of the line 1 is invalid because it is less than 0."); } catch (ValidationException e) { } // But if you change the value line1.setValue(BigDecimal.ONE); try { expenseSheetDAO.save(expense); assertThat(expense.getTotal(), equalTo(new BigDecimal(11))); } catch (ValidationException e) { fail("it must not throw a exception."); } } @Test @Transactional public void validExpenseSheetWithInvalidDateInLines() { // Create the expenseSheet without lines ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("code-expense-sheet-1"); // orderElement empty OrderElement orderElement = this.givenOrderElement("order-element-2"); // A expense sheet with valid date and order element, but invalid value ExpenseSheetLine line1 = ExpenseSheetLine.create(BigDecimal.ONE, "concept", null, orderElement); // Add the line to the expense sheet line1.setExpenseSheet(expense); expense.add(line1); try { expenseSheetDAO.save(expense); fail("it must throw a exception. The date is not specified in the expense sheet line."); } catch (ValidationException e) { } LocalDate today = new LocalDate(); line1.setDate(today); assertThat(expense.getFirstExpense(), equalTo(today)); assertThat(expense.getLastExpense(), equalTo(today)); // Add other line with other date LocalDate tomorrow = new LocalDate().plusDays(1); ExpenseSheetLine line2 = ExpenseSheetLine.create(BigDecimal.ONE, "concept", tomorrow, orderElement); line2.setExpenseSheet(expense); expense.add(line2); assertThat(expense.getFirstExpense(), equalTo(today)); assertThat(expense.getLastExpense(), equalTo(tomorrow)); try { expenseSheetDAO.save(expense); } catch (ValidationException e) { fail("it must not throw a exception."); } } @Test @Transactional public void validExpenseSheetData() { // Check out the expenseSheet without lines int previousExpenses = expenseSheetDAO.getAll().size(); ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("code-expense-sheet-1"); // Check out the orderElement String orderLineCode = "order-line-code"; OrderElement orderElement = givenSavedOrderElement(orderLineCode); // Check out the resource Worker worker = givenSavedValidWorker(); // Add line 1 with a resource LocalDate today = new LocalDate(); ExpenseSheetLine line1 = ExpenseSheetLine.create(BigDecimal.ONE, "concept 1", today, orderElement); line1.setResource(worker); line1.setExpenseSheet(expense); expense.add(line1); // Add line 2 without resource LocalDate tomorrow = new LocalDate().plusDays(1); ExpenseSheetLine line2 = ExpenseSheetLine.create(BigDecimal.ONE, "concept 2", tomorrow, orderElement); line2.setExpenseSheet(expense); expense.add(line2); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); // Check out the expense sheet ExpenseSheet expenseSheet = expenseSheetDAO.getAll().get(previousExpenses); assertNotNull(expenseSheet.getCode()); assertThat(expenseSheet.getCode(), equalTo("code-expense-sheet-1")); assertThat(expenseSheet.getTotal(), equalTo(new BigDecimal(2))); assertThat(expenseSheet.getFirstExpense(), equalTo(today)); assertThat(expenseSheet.getLastExpense(), equalTo(tomorrow)); assertThat(expenseSheet.getExpenseSheetLines().size(), equalTo(2)); // Check out the expense sheet lines ExpenseSheetLine savedLine1 = expenseSheet.getExpenseSheetLines().last(); ExpenseSheetLine savedLine2 = expenseSheet.getExpenseSheetLines().first(); assertThat(savedLine1.getConcept(), equalTo("concept 1")); assertThat(savedLine1.getDate(), equalTo(today)); assertThat(savedLine1.getValue(), equalTo(BigDecimal.ONE)); assertNotNull(savedLine1.getOrderElement()); assertNotNull(savedLine1.getResource()); assertNotNull(savedLine1.getCode()); assertThat(savedLine2.getConcept(), equalTo("concept 2")); assertThat(savedLine2.getDate(), equalTo(tomorrow)); assertThat(savedLine2.getValue(), equalTo(BigDecimal.ONE)); assertNotNull(savedLine2.getOrderElement()); assertNotNull(savedLine2.getCode()); } private Worker givenSavedValidWorker() { Worker worker = givenValidWorker(); resourceDAO.save(worker); resourceDAO.flush(); return worker; } private OrderElement givenSavedOrderElement(String orderLineCode) { OrderElement orderElement = givenOrderElement(orderLineCode); orderElementDAO.save(orderElement); orderElementDAO.flush(); return orderElement; } @Test @Transactional public void testSaveTwoExpenseSheetWithTheSameCode() { int previousExpenses = expenseSheetDAO.getAll().size(); // Create a valid order element String orderLineCode = "order-line-code"; OrderElement orderElement = givenSavedOrderElement(orderLineCode); ExpenseSheet expense = getValidExpenseSheet("code-expense-sheet-1", orderElement); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); // Check out the expense sheet ExpenseSheet expenseSheet = expenseSheetDAO.getAll().get(previousExpenses); assertNotNull(expenseSheet.getCode()); assertThat(expenseSheet.getCode(), equalTo("code-expense-sheet-1")); // Create other expense sheet with one line ExpenseSheet expense2 = getValidExpenseSheet("code-expense-sheet-1", orderElement); try { expenseSheetDAO.save(expense2); expenseSheetDAO.flush(); fail("it must throw a exception"); } catch (Exception e) { } } private ExpenseSheet getValidExpenseSheet(String code, OrderElement orderElement) { ExpenseSheet expense = ExpenseSheet.create(); expense.setCode(code); // Add line 1 LocalDate today = new LocalDate(); ExpenseSheetLine line1 = ExpenseSheetLine.create(BigDecimal.ONE, "concept 1", today, orderElement); line1.setExpenseSheet(expense); expense.add(line1); return expense; } @Test @Transactional public void testSaveTwoValidExpenseSheets() { int previousExpenses = expenseSheetDAO.getAll().size(); // Create a valid orderElement String orderLineCode = "order-line-code"; OrderElement orderElement = givenSavedOrderElement(orderLineCode); ExpenseSheet expense = getValidExpenseSheet("code-expense-sheet-1", orderElement); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); // Check out the expense sheet ExpenseSheet expenseSheet = expenseSheetDAO.getAll().get(previousExpenses); assertNotNull(expenseSheet.getCode()); assertThat(expenseSheet.getCode(), equalTo("code-expense-sheet-1")); // Create other expense sheet with one line ExpenseSheet expense2 = getValidExpenseSheet("code-expense-sheet-2", orderElement); try { expenseSheetDAO.save(expense2); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 2)); // Check out the expense sheet try { ExpenseSheet expenseSheet2 = expenseSheetDAO.findByCode("code-expense-sheet-2"); assertNotNull(expenseSheet2); assertThat(expenseSheet2.getExpenseSheetLines().size(), equalTo(1)); } catch (InstanceNotFoundException e) { fail("it must not throw a exception"); } } @Test(expected = ValidationException.class) @Transactional public void testSaveExpenseSheetWithoutCode() { ExpenseSheet expense = ExpenseSheet.create(); expense.setCode(null); try { expenseSheetDAO.save(expense); } catch (DataIntegrityViolationException e) { throw new ValidationException(e.getMessage()); } } @Test @Transactional public void testRemoveExpenseSheet() throws InstanceNotFoundException { int previousExpenses = expenseSheetDAO.getAll().size(); int previousExpenseLines = expenseSheetLineDAO.findAll().size(); // Create a valid order element String orderLineCode = "order-line-code"; OrderElement orderElement = givenSavedOrderElement(orderLineCode); ExpenseSheet expense = getValidExpenseSheet("code-expense-sheet-1", orderElement); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); assertThat(expenseSheetLineDAO.findAll().size(), equalTo(previousExpenseLines + 1)); expenseSheetDAO.remove(expense.getId()); expenseSheetDAO.flush(); assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses)); assertThat(expenseSheetLineDAO.findAll().size(), equalTo(previousExpenseLines)); } @Test @Transactional public void testRemoveExpenseSheetLine() { int previousExpenseLines = expenseSheetLineDAO.findAll().size(); int previousExpenses = expenseSheetDAO.getAll().size(); ExpenseSheet expense = ExpenseSheet.create(); expense.setCode("code-expense-sheet-1"); // Check out the orderElement String orderLineCode = "order-line-code"; OrderElement orderElement = givenSavedOrderElement(orderLineCode); // Check out the resource Worker worker = givenSavedValidWorker(); // Add line 1 with a resource LocalDate today = new LocalDate(); ExpenseSheetLine line1 = ExpenseSheetLine.create(BigDecimal.ONE, "concept 1", today, orderElement); line1.setResource(worker); line1.setExpenseSheet(expense); expense.add(line1); // Add line 2 without resource LocalDate tomorrow = new LocalDate().plusDays(1); ExpenseSheetLine line2 = ExpenseSheetLine.create(BigDecimal.ONE, "concept 2", tomorrow, orderElement); line2.setCode("code-line-2"); line2.setExpenseSheet(expense); expense.add(line2); try { expenseSheetDAO.save(expense); expenseSheetDAO.flush(); } catch (ValidationException e) { fail("it must not throw a exception"); } assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); try { ExpenseSheet expenseSheet = expenseSheetDAO.findByCode("code-expense-sheet-1"); assertNotNull(expenseSheet); assertThat(expenseSheet.getExpenseSheetLines().size(), equalTo(2)); assertThat(expenseSheetLineDAO.findAll().size(), equalTo(previousExpenseLines + 2)); expenseSheet.remove(line2); expenseSheetDAO.save(expenseSheet); expenseSheetDAO.flush(); assertThat(expenseSheetDAO.getAll().size(), equalTo(previousExpenses + 1)); assertThat(expenseSheetLineDAO.findAll().size(), equalTo(previousExpenseLines + 1)); } catch (InstanceNotFoundException e) { fail("It must not throw a exception"); } } }