diff --git a/libreplan-business/src/main/java/org/libreplan/business/expensesheet/entities/ExpenseSheet.java b/libreplan-business/src/main/java/org/libreplan/business/expensesheet/entities/ExpenseSheet.java
index faa3543ba..dd88474af 100644
--- a/libreplan-business/src/main/java/org/libreplan/business/expensesheet/entities/ExpenseSheet.java
+++ b/libreplan-business/src/main/java/org/libreplan/business/expensesheet/entities/ExpenseSheet.java
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
+import org.apache.commons.lang.StringUtils;
import org.hibernate.validator.AssertTrue;
import org.hibernate.validator.Min;
import org.hibernate.validator.NotEmpty;
@@ -34,6 +35,7 @@ import org.libreplan.business.common.IHumanIdentifiable;
import org.libreplan.business.common.IntegrationEntity;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.entities.EntitySequence;
+import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.expensesheet.daos.IExpenseSheetDAO;
/**
@@ -198,4 +200,22 @@ public class ExpenseSheet extends IntegrationEntity implements IHumanIdentifiabl
return getCode() + (description != null ? description : "");
}
+ public ExpenseSheetLine getExpenseSheetLineByCode(String code)
+ throws InstanceNotFoundException {
+
+ if (StringUtils.isBlank(code)) {
+ throw new InstanceNotFoundException(code,
+ ExpenseSheetLine.class.getName());
+ }
+
+ for (ExpenseSheetLine l : this.expenseSheetLines) {
+ if (l.getCode().equalsIgnoreCase(StringUtils.trim(code))) {
+ return l;
+ }
+ }
+
+ throw new InstanceNotFoundException(code,
+ ExpenseSheetLine.class.getName());
+ }
+
}
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetDTO.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetDTO.java
new file mode 100644
index 000000000..54762a053
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetDTO.java
@@ -0,0 +1,69 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.api;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.libreplan.business.expensesheet.entities.ExpenseSheet;
+import org.libreplan.ws.common.api.IntegrationEntityDTO;
+
+/**
+ * DTO for {@link ExpenseSheet} entity.
+ *
+ * @author Susana Montes Pedreira
+ */
+@XmlRootElement(name = "expense-sheet")
+public class ExpenseSheetDTO extends IntegrationEntityDTO {
+
+ public final static String ENTITY_TYPE = "expense-sheet";
+
+ @XmlAttribute
+ public String description;
+
+ @XmlElementWrapper(name = "expense-sheet-line-list")
+ @XmlElement(name = "expense-sheet-line")
+ public List lines = new ArrayList();
+
+ public ExpenseSheetDTO() {
+ }
+
+ public ExpenseSheetDTO(String code, String description,
+ List lines) {
+ super(code);
+ this.description = description;
+ this.lines = lines;
+ }
+
+ public ExpenseSheetDTO(String description, List lines) {
+ this(generateCode(), description, lines);
+ }
+
+ @Override
+ public String getEntityType() {
+ return ENTITY_TYPE;
+ }
+
+}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetLineDTO.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetLineDTO.java
new file mode 100644
index 000000000..5441bc641
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetLineDTO.java
@@ -0,0 +1,80 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.api;
+
+import java.math.BigDecimal;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.libreplan.business.expensesheet.entities.ExpenseSheet;
+import org.libreplan.ws.common.api.IntegrationEntityDTO;
+
+/**
+ * DTO for {@link ExpenseSheet} entity.
+ *
+ * @author Susana Montes Pedreira
+ */
+@XmlRootElement(name = "expense-sheet-line")
+public class ExpenseSheetLineDTO extends IntegrationEntityDTO {
+
+ public final static String ENTITY_TYPE = "expense-sheet-line";
+
+ @XmlAttribute
+ public String concept;
+
+ @XmlAttribute
+ public BigDecimal value;
+
+ @XmlAttribute
+ public String resource;
+
+ @XmlAttribute(name = "task")
+ public String orderElement;
+
+ @XmlAttribute
+ public XMLGregorianCalendar date;
+
+ public ExpenseSheetLineDTO() {
+ }
+
+ public ExpenseSheetLineDTO(String code, String concept, BigDecimal value, String resource,
+ String orderElement, XMLGregorianCalendar date) {
+ super(code);
+ this.concept = concept;
+ this.value = value;
+ this.resource = resource;
+ this.orderElement = orderElement;
+ this.date = date;
+ }
+
+ public ExpenseSheetLineDTO(String concept, BigDecimal value, String resource,
+ String orderElement,
+ XMLGregorianCalendar date) {
+ this(generateCode(), concept, value, resource, orderElement, date);
+ }
+
+ @Override
+ public String getEntityType() {
+ return ENTITY_TYPE;
+ }
+
+}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetListDTO.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetListDTO.java
new file mode 100644
index 000000000..525cd1ade
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/ExpenseSheetListDTO.java
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.api;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * DTO for a list of {@link ExpensesSheet} entities.
+ *
+ * @author Susana Montes Pedreira
+ */
+@XmlRootElement(name = "expense-sheet-list")
+public class ExpenseSheetListDTO {
+
+ @XmlElement(name = "expense-sheet")
+ public List expenseSheets = new ArrayList();
+
+ public ExpenseSheetListDTO() {
+ }
+
+ public ExpenseSheetListDTO(List expenseSheets) {
+ this.expenseSheets = expenseSheets;
+ }
+}
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/IExpenseSheetService.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/IExpenseSheetService.java
new file mode 100644
index 000000000..31ab45013
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/api/IExpenseSheetService.java
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.api;
+
+import javax.ws.rs.core.Response;
+
+import org.libreplan.business.expensesheet.entities.ExpenseSheet;
+import org.libreplan.ws.common.api.InstanceConstraintViolationsListDTO;
+
+/**
+ * Service for managing {@link ExpenseSheet} entities.
+ *
+ * @author Susana Montes Pedreira
+ */
+public interface IExpenseSheetService {
+
+ ExpenseSheetListDTO getExpenseSheets();
+
+ InstanceConstraintViolationsListDTO addExpenseSheets(
+ ExpenseSheetListDTO expenseSheetListDTO);
+
+ Response getLabel(String code);
+
+}
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetConverter.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetConverter.java
new file mode 100644
index 000000000..37829a48d
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetConverter.java
@@ -0,0 +1,264 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.commons.lang.StringUtils;
+import org.joda.time.LocalDate;
+import org.libreplan.business.common.Registry;
+import org.libreplan.business.common.exceptions.InstanceNotFoundException;
+import org.libreplan.business.common.exceptions.ValidationException;
+import org.libreplan.business.expensesheet.entities.ExpenseSheet;
+import org.libreplan.business.expensesheet.entities.ExpenseSheetLine;
+import org.libreplan.business.orders.entities.OrderElement;
+import org.libreplan.business.resources.entities.Resource;
+import org.libreplan.ws.common.impl.DateConverter;
+import org.libreplan.ws.expensesheets.api.ExpenseSheetDTO;
+import org.libreplan.ws.expensesheets.api.ExpenseSheetLineDTO;
+import org.libreplan.ws.expensesheets.api.ExpenseSheetListDTO;
+
+/**
+ * Converter from/to {@link ExpenseSheet} related entities to/from DTOs.
+ *
+ * @author Susana Montes Pedreira
+ */
+public final class ExpenseSheetConverter {
+
+ private ExpenseSheetConverter() {
+ }
+
+ public final static ExpenseSheetListDTO toDTO(Collection expenseSheets) {
+ List expenseSheetDTOs = new ArrayList();
+
+ for (ExpenseSheet expenseSheet : expenseSheets) {
+ expenseSheetDTOs.add(toDTO(expenseSheet));
+ }
+
+ return new ExpenseSheetListDTO(expenseSheetDTOs);
+ }
+
+ public final static ExpenseSheetDTO toDTO(ExpenseSheet expenseSheet) {
+ String code = expenseSheet.getCode();
+ if (StringUtils.isBlank(code)) {
+ throw new ValidationException("missing code in the expense sheet");
+ }
+
+ List lineDTOs = new ArrayList();
+
+ if (expenseSheet.getExpenseSheetLines() == null
+ || expenseSheet.getExpenseSheetLines().isEmpty()) {
+ throw new ValidationException(
+ "the expense sheet must have least a expense sheet line.");
+ }
+
+ for (ExpenseSheetLine line : expenseSheet.getExpenseSheetLines()) {
+ lineDTOs.add(toDTO(line));
+ }
+
+ return new ExpenseSheetDTO(code, expenseSheet.getDescription(),
+ lineDTOs);
+ }
+
+ private static ExpenseSheetLineDTO toDTO(ExpenseSheetLine line) {
+ if (line != null) {
+
+ String code = line.getCode();
+ if (StringUtils.isBlank(code)) {
+ throw new ValidationException(
+ "missing code in the expense sheet line");
+ }
+
+ BigDecimal value = line.getValue();
+ if (value != null && value.compareTo(BigDecimal.ZERO) > 0) {
+
+ }
+ String resourceCode = null;
+ if (line.getResource() != null) {
+ resourceCode = line.getResource().getCode();
+ }
+
+ String orderElementCode = null;
+ if (line.getOrderElement() != null) {
+ orderElementCode = line.getOrderElement().getCode();
+ } else {
+ throw new ValidationException(
+ "missing order element code in a expense sheet line");
+ }
+
+ XMLGregorianCalendar date = null;
+ if (line.getDate() != null) {
+ date = DateConverter.toXMLGregorianCalendar(line.getDate());
+ } else {
+ throw new ValidationException(
+ "missing date in a expense sheet line");
+ }
+
+ return new ExpenseSheetLineDTO(code, line.getConcept(), value,
+ resourceCode, orderElementCode, date);
+ } else {
+ throw new ValidationException(
+ "the expense sheet line is not initialized");
+ }
+ }
+
+ public final static ExpenseSheet toEntity(ExpenseSheetDTO expenseSheetDTO) {
+ ExpenseSheet expenseSheet = ExpenseSheet.create();
+ expenseSheet.setCode(expenseSheetDTO.code);
+ expenseSheet.setDescription(expenseSheetDTO.description);
+
+ for (ExpenseSheetLineDTO lineDTO : expenseSheetDTO.lines) {
+ expenseSheet.add(toEntity(lineDTO, expenseSheet));
+ }
+
+ return expenseSheet;
+ }
+
+ private static ExpenseSheetLine toEntity(ExpenseSheetLineDTO lineDTO, ExpenseSheet expenseSheet) {
+ String code = lineDTO.code;
+ if(StringUtils.isBlank(code)){
+ throw new ValidationException("missing code expense sheet line");
+ }
+
+ BigDecimal value = lineDTO.value;
+ String concept = lineDTO.concept;
+
+ LocalDate date = null;
+ if (lineDTO.date != null) {
+ date = DateConverter.toLocalDate(lineDTO.date);
+ }
+
+ String orderElementCode = lineDTO.orderElement;
+ OrderElement orderElement = null;
+ try{
+ orderElement = Registry.getOrderElementDAO().findByCode(
+ orderElementCode);
+ }catch (InstanceNotFoundException e) {
+ throw new ValidationException(
+ "There is no order element with this code");
+ }
+
+ ExpenseSheetLine line = ExpenseSheetLine.create(value, concept, date,
+ orderElement);
+ line.setExpenseSheet(expenseSheet);
+ line.setCode(code);
+
+ if(lineDTO.resource != null){
+ String resourceCode = lineDTO.resource;
+ try{
+ Resource resource = Registry.getResourceDAO().findByCode(resourceCode);
+ line.setResource(resource);
+ }catch (InstanceNotFoundException e) {
+ throw new ValidationException(
+ "There is no resource with this code");
+ }
+ }
+
+ return line;
+ }
+
+ public final static void updateExpenseSheet(ExpenseSheet expenseSheet,
+ ExpenseSheetDTO expenseSheetDTO) throws ValidationException {
+
+ if (StringUtils.isBlank(expenseSheetDTO.code)) {
+ throw new ValidationException("missing code in a expense sheet.");
+ }
+
+ if (!StringUtils.isBlank(expenseSheetDTO.description)) {
+ expenseSheet.setDescription(expenseSheetDTO.description);
+ }
+ /*
+ * 1: Update the existing expense sheet line or add new expense sheet
+ * line.
+ */
+ for (ExpenseSheetLineDTO lineDTO : expenseSheetDTO.lines) {
+
+ /* Step 1.1: requires each expense sheet line DTO to have a code. */
+ if (StringUtils.isBlank(lineDTO.code)) {
+ throw new ValidationException(
+ "missing code in a expense sheet line");
+ }
+
+ try {
+ ExpenseSheetLine line = expenseSheet
+ .getExpenseSheetLineByCode(lineDTO.code);
+ updateExpenseSheetLine(line, lineDTO);
+ } catch (InstanceNotFoundException e) {
+ expenseSheet.add(toEntity(lineDTO, expenseSheet));
+ }
+ }
+ }
+
+ public final static void updateExpenseSheetLine(ExpenseSheetLine line,
+ ExpenseSheetLineDTO lineDTO) throws ValidationException {
+
+ /*
+ * 1: Update the concept
+ */
+ if (lineDTO.concept != null) {
+ line.setConcept(lineDTO.concept);
+ }
+ /*
+ * 2: Update the value
+ */
+ if (lineDTO.value != null) {
+ line.setValue(lineDTO.value);
+ }
+
+ /*
+ * 3: Update the order element
+ */
+ String orderElementCode = lineDTO.orderElement;
+ if (!StringUtils.isBlank(orderElementCode)) {
+ try {
+ OrderElement orderElement = Registry.getOrderElementDAO()
+ .findUniqueByCode(orderElementCode);
+ line.setOrderElement(orderElement);
+ } catch (InstanceNotFoundException e) {
+ throw new ValidationException("There is no task with this code");
+ }
+ }
+
+ /* Step 3.1: Update the date. */
+ if (lineDTO != null) {
+ LocalDate date = DateConverter.toLocalDate(lineDTO.date);
+ line.setDate(date);
+ }
+
+ /* Step 3.4: Update the resource. */
+ if (lineDTO.resource != null) {
+ try {
+ Resource resource = Registry.getResourceDAO().findByCode(
+ lineDTO.resource);
+ line.setResource(resource);
+ } catch (InstanceNotFoundException e) {
+ throw new ValidationException(
+ "There is no resource with this code");
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetServiceREST.java b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetServiceREST.java
new file mode 100644
index 000000000..f61a57cd9
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/ws/expensesheets/impl/ExpenseSheetServiceREST.java
@@ -0,0 +1,163 @@
+/*
+ * 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 .
+ */
+
+package org.libreplan.ws.expensesheets.impl;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import org.libreplan.business.common.IOnTransaction;
+import org.libreplan.business.common.daos.IIntegrationEntityDAO;
+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.entities.ExpenseSheet;
+import org.libreplan.business.orders.daos.ISumExpensesDAO;
+import org.libreplan.ws.common.api.InstanceConstraintViolationsListDTO;
+import org.libreplan.ws.common.impl.GenericRESTService;
+import org.libreplan.ws.common.impl.RecoverableErrorException;
+import org.libreplan.ws.expensesheets.api.ExpenseSheetDTO;
+import org.libreplan.ws.expensesheets.api.ExpenseSheetListDTO;
+import org.libreplan.ws.expensesheets.api.IExpenseSheetService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * REST-based implementation of {@link IExpenseSheetService}.
+ *
+ * @author Susana Montes Pedreira
+ */
+@Path("/expenses/")
+@Produces("application/xml")
+@Service("expenseSheetServiceREST")
+public class ExpenseSheetServiceREST extends
+ GenericRESTService implements
+ IExpenseSheetService {
+
+ @Autowired
+ private ISumExpensesDAO sumExpensesDAO;
+
+ @Autowired
+ private IExpenseSheetDAO expenseSheetDAO;
+
+ /**
+ * It saves (inserts or updates) an entity DTO by using a new transaction.
+ *
+ * @throws ValidationException if validations are not passed
+ * @throws RecoverableErrorException if a recoverable error occurs
+ * @author Susana Montes Pedreira
+ *
+ */
+ protected void insertOrUpdate(final ExpenseSheetDTO entityDTO)
+ throws ValidationException, RecoverableErrorException {
+ /*
+ * NOTE: ValidationException and RecoverableErrorException are runtime
+ * exceptions. In consequence, if any of them occurs, transaction is
+ * automatically rolled back.
+ */
+
+ IOnTransaction save = new IOnTransaction() {
+
+ @Override
+ public Void execute() {
+
+ ExpenseSheet entity = null;
+ IIntegrationEntityDAO entityDAO = getIntegrationEntityDAO();
+
+ /* Insert or update? */
+ try {
+ entity = entityDAO.findByCode(entityDTO.code);
+ updateEntity(entity, entityDTO);
+ } catch (InstanceNotFoundException e) {
+ entity = toEntity(entityDTO);
+ }
+
+ /*
+ * Validate and save (insert or update) the entity.
+ */
+ entity.validate();
+ sumExpensesDAO
+ .updateRelatedSumExpensesWithExpenseSheetLineSet(entity
+ .getExpenseSheetLines());
+ entity.updateCalculatedProperties();
+
+ entityDAO.saveWithoutValidating(entity);
+
+ return null;
+
+ }
+
+ };
+
+ transactionService.runOnAnotherTransaction(save);
+ }
+
+ @Override
+ @POST
+ @Consumes("application/xml")
+ @Transactional
+ public InstanceConstraintViolationsListDTO addExpenseSheets(
+ ExpenseSheetListDTO expenseSheetListDTO) {
+ return save(expenseSheetListDTO.expenseSheets);
+ }
+
+ @Override
+ protected IIntegrationEntityDAO getIntegrationEntityDAO() {
+ return expenseSheetDAO;
+ }
+
+ @Override
+ protected ExpenseSheetDTO toDTO(ExpenseSheet entity) {
+ return ExpenseSheetConverter.toDTO(entity);
+ }
+
+ @Override
+ protected ExpenseSheet toEntity(ExpenseSheetDTO entityDTO)
+ throws ValidationException, RecoverableErrorException {
+ return ExpenseSheetConverter.toEntity(entityDTO);
+ }
+
+ @Override
+ @GET
+ @Path("/{code}/")
+ @Transactional(readOnly = true)
+ public Response getLabel(@PathParam("code") String code) {
+ return getDTOByCode(code);
+ }
+
+ @Override
+ protected void updateEntity(ExpenseSheet entity, ExpenseSheetDTO entityDTO)
+ throws ValidationException, RecoverableErrorException {
+ ExpenseSheetConverter.updateExpenseSheet(entity, entityDTO);
+
+ }
+
+ @Override
+ @GET
+ @Transactional(readOnly = true)
+ public ExpenseSheetListDTO getExpenseSheets() {
+ return new ExpenseSheetListDTO(findAll());
+ }
+}
diff --git a/libreplan-webapp/src/main/resources/libreplan-webapp-spring-config.xml b/libreplan-webapp/src/main/resources/libreplan-webapp-spring-config.xml
index 42a3cbd6e..b04e89a33 100644
--- a/libreplan-webapp/src/main/resources/libreplan-webapp-spring-config.xml
+++ b/libreplan-webapp/src/main/resources/libreplan-webapp-spring-config.xml
@@ -72,6 +72,7 @@
+