/* * This file is part of LibrePlan * * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e * Desenvolvemento Tecnolóxico de Galicia * Copyright (C) 2010-2011 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.web.test.ws.costcategories; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE; import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE; import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_FILE; import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE; import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import javax.xml.datatype.XMLGregorianCalendar; import org.hibernate.SessionFactory; import org.joda.time.LocalDate; import org.junit.Test; import org.junit.runner.RunWith; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.costcategories.daos.ICostCategoryDAO; import org.libreplan.business.costcategories.daos.IHourCostDAO; import org.libreplan.business.costcategories.daos.ITypeOfWorkHoursDAO; import org.libreplan.business.costcategories.entities.CostCategory; import org.libreplan.business.costcategories.entities.HourCost; import org.libreplan.business.costcategories.entities.TypeOfWorkHours; import org.libreplan.ws.common.api.InstanceConstraintViolationsDTO; import org.libreplan.ws.common.impl.DateConverter; import org.libreplan.ws.costcategories.api.CostCategoryDTO; import org.libreplan.ws.costcategories.api.CostCategoryListDTO; import org.libreplan.ws.costcategories.api.HourCostDTO; import org.libreplan.ws.costcategories.api.ICostCategoryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; /** * Tests for <code>ICostCategoryService</code>. * * @author Susana Montes Pedreira <smontes@wirelessgalicia.com> */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_FILE, WEBAPP_SPRING_CONFIG_TEST_FILE, WEBAPP_SPRING_SECURITY_CONFIG_FILE, WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE }) public class CostCategoryServiceTest { @Autowired private ICostCategoryService costCategoryService; @Autowired private ICostCategoryDAO costCategoryDAO; @Autowired private IHourCostDAO hourCostDAO; @Autowired private ITypeOfWorkHoursDAO typeOfWorkHoursDAO; @Autowired private SessionFactory sessionFactory; private final String typeOfWorkHoursCodeA = "code-A"; private final String typeOfWorkHoursCodeB = "code-B"; @Autowired private IAdHocTransactionService transactionService; @Test @Transactional @Rollback(false) public void createAPairTypeOfWorkHours() { givenTypeOfWorkHours(typeOfWorkHoursCodeA); givenTypeOfWorkHours(typeOfWorkHoursCodeB); } private void givenTypeOfWorkHours(String code) { TypeOfWorkHours typeOfWorkHours = TypeOfWorkHours.create(); typeOfWorkHours.setCode(code); typeOfWorkHours.setName("name" + UUID.randomUUID()); typeOfWorkHours.setDefaultPrice(BigDecimal.TEN); typeOfWorkHoursDAO.save(typeOfWorkHours); typeOfWorkHoursDAO.flush(); sessionFactory.getCurrentSession().evict(typeOfWorkHours); typeOfWorkHours.dontPoseAsTransientObjectAnymore(); } @Test @Transactional public void testAddAndGetCostCategories() { /* Build cost category (5 constraint violations) */ // Missing cost category name and enabled CostCategoryDTO cc1 = new CostCategoryDTO(null, true, new HashSet<>()); // Valid cost category DTO without hour cost CostCategoryDTO cc2 = new CostCategoryDTO("cc2", true, new HashSet<>()); // Valid cost category DTO with a hour cost Set<HourCostDTO> cc3_HourCostDTOs = new HashSet<>(); XMLGregorianCalendar initDate = DateConverter.toXMLGregorianCalendar(new Date()); HourCostDTO cc3_1_HourCostDTO = new HourCostDTO(new BigDecimal(3), initDate, initDate, typeOfWorkHoursCodeA); cc3_HourCostDTOs.add(cc3_1_HourCostDTO); CostCategoryDTO cc3 = new CostCategoryDTO("cc3", true, cc3_HourCostDTOs); // Valid cost category DTO with a invalid hour cost missing priceCost, initDate and type Set<HourCostDTO> cc4_HourCostDTOs = new HashSet<>(); HourCostDTO cc4_1_HourCostDTO = new HourCostDTO(null, null, null, null); cc4_HourCostDTOs.add(cc4_1_HourCostDTO); CostCategoryDTO cc4 = new CostCategoryDTO("cc4", true, cc4_HourCostDTOs); /* Cost category type list */ CostCategoryListDTO costCategoryListDTO = createCostCategoryListDTO(cc1, cc2, cc3, cc4); List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = costCategoryService .addCostCategories(costCategoryListDTO).instanceConstraintViolationsList; assertTrue(instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.size() == 2); assertTrue( instanceConstraintViolationsList.get(0).constraintViolations.toString(), instanceConstraintViolationsList.get(0).constraintViolations.size() == 1); // cc1 constraint violations assertTrue( instanceConstraintViolationsList.get(1).constraintViolations.toString(), instanceConstraintViolationsList.get(1).constraintViolations.size() == 3); // cc1 constraint violations assertFalse(costCategoryDAO.existsByCode(cc1.code)); assertTrue(costCategoryDAO.existsByCode(cc2.code)); assertTrue(costCategoryDAO.existsByCode(cc3.code)); assertFalse(costCategoryDAO.existsByCode(cc4.code)); try { CostCategory costCategory = costCategoryDAO.findByCode(cc3.code); assertTrue(costCategory.getHourCosts().size() == 1); } catch (InstanceNotFoundException e) { assertTrue(false); } } @Test public void testUpdateCostCategory() throws InstanceNotFoundException { // First one it creates Valid cost category DTO with a hour cost final String costCategoryCode = "code-CC"; final String hourCostCode = "code-HC"; Set<HourCostDTO> cc1_HourCostDTOs = new HashSet<>(); XMLGregorianCalendar initDate = DateConverter.toXMLGregorianCalendar(new Date()); final HourCostDTO cc1_1_HourCostDTO = new HourCostDTO(hourCostCode, new BigDecimal(3), initDate, initDate, typeOfWorkHoursCodeA); cc1_HourCostDTOs.add(cc1_1_HourCostDTO); final CostCategoryDTO cc1 = new CostCategoryDTO(costCategoryCode, "newCC1", true, cc1_HourCostDTOs); CostCategoryListDTO costCategoryListDTO = createCostCategoryListDTO(cc1); List<InstanceConstraintViolationsDTO> instanceConstraintViolationsList = costCategoryService .addCostCategories(costCategoryListDTO).instanceConstraintViolationsList; transactionService.runOnTransaction(new IOnTransaction<Void>() { @Override public Void execute() { costCategoryDAO.flush(); hourCostDAO.flush(); return null; } }); assertTrue(instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.size() == 0); transactionService.runOnTransaction(new IOnTransaction<Void>() { @Override public Void execute() { assertTrue(costCategoryDAO.existsByCode(cc1.code)); return null; } }); final CostCategory costCategory = transactionService.runOnTransaction(new IOnTransaction<CostCategory>() { @Override public CostCategory execute() { CostCategory cost; try { cost = costCategoryDAO.findByCode(cc1.code); cost.getHourCosts().size(); return cost; } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } } }); assertTrue(costCategory.getHourCosts().size() == 1); final HourCost hourCost = transactionService.runOnTransaction(new IOnTransaction<HourCost>() { @Override public HourCost execute() { try { HourCost cost = hourCostDAO .findByCode(hourCostCode); cost.getType().getCode(); return cost; } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } } }); LocalDate currentDate = LocalDate.fromDateFields(new Date()); assertTrue(hourCost.getInitDate().compareTo(currentDate) == 0); assertFalse(hourCost.getEndDate() == null); assertTrue(hourCost.getEndDate().compareTo(hourCost.getInitDate()) == 0); assertTrue(hourCost.getPriceCost().compareTo(new BigDecimal(3)) == 0); assertTrue(hourCost.getType().getCode().equalsIgnoreCase(typeOfWorkHoursCodeA)); transactionService.runOnTransaction(new IOnTransaction<Void>() { @Override public Void execute() { costCategoryDAO.flush(); sessionFactory.getCurrentSession().evict(costCategory); return null; } }); costCategory.dontPoseAsTransientObjectAnymore(); // Update the previous cost category Set<HourCostDTO> cc2_HourCostDTOs = new HashSet<>(); XMLGregorianCalendar initDate2 = DateConverter.toXMLGregorianCalendar(new Date()); XMLGregorianCalendar endDate2 = DateConverter.toXMLGregorianCalendar(getNextMonthDate()); HourCostDTO cc2_1_HourCostDTO = new HourCostDTO(hourCostCode, new BigDecimal(100), initDate2, endDate2, typeOfWorkHoursCodeB); cc2_HourCostDTOs.add(cc2_1_HourCostDTO); CostCategoryDTO cc2 = new CostCategoryDTO(costCategoryCode, "updateCC1", false, cc2_HourCostDTOs); /* Cost category type list */ costCategoryListDTO = createCostCategoryListDTO(cc2); instanceConstraintViolationsList = costCategoryService .addCostCategories(costCategoryListDTO).instanceConstraintViolationsList; assertTrue(instanceConstraintViolationsList.toString(), instanceConstraintViolationsList.size() == 0); transactionService.runOnTransaction(new IOnTransaction<Void>() { @Override public Void execute() { assertTrue(costCategoryDAO.existsByCode(cc1.code)); assertTrue(hourCostDAO.existsByCode(cc1_1_HourCostDTO.code)); return null; } }); final CostCategory costCategory2 = transactionService.runOnTransaction(new IOnTransaction<CostCategory>() { @Override public CostCategory execute() { CostCategory cost; try { cost = costCategoryDAO.findByCode(costCategoryCode); cost.getHourCosts().size(); return cost; } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } } }); // Check if the changes was updated assertTrue(costCategory2.getHourCosts().size() == 1); assertTrue(costCategory2.getName().equalsIgnoreCase("updateCC1")); assertFalse(costCategory2.getEnabled()); final HourCost hourCost2 = transactionService.runOnTransaction(new IOnTransaction<HourCost>() { @Override public HourCost execute() { try { HourCost cost = hourCostDAO.findByCode(cc1_1_HourCostDTO.code); cost.getType().getCode(); return cost; } catch (InstanceNotFoundException e) { throw new RuntimeException(e); } } }); LocalDate nextMonthDate = LocalDate.fromDateFields(getNextMonthDate()); assertTrue(hourCost2.getInitDate().compareTo(LocalDate.fromDateFields(new Date())) == 0); assertFalse(hourCost2.getEndDate() == null); assertTrue(hourCost2.getEndDate().compareTo(nextMonthDate) == 0); assertTrue(hourCost2.getPriceCost().compareTo(new BigDecimal(100)) == 0); assertTrue(hourCost2.getType().getCode().equalsIgnoreCase(typeOfWorkHoursCodeB)); } private Date getNextMonthDate() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(calendar.MONTH, 1); int date = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(calendar.MONTH); int year = calendar.get(Calendar.YEAR); calendar.set(year, month, date); return calendar.getTime(); } private CostCategoryListDTO createCostCategoryListDTO(CostCategoryDTO... costCategories) { List<CostCategoryDTO> costCategoryList = new ArrayList<>(); for (CostCategoryDTO c : costCategories) { costCategoryList.add(c); } return new CostCategoryListDTO(costCategoryList); } }