diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java
index af9ad7954..646c4e6a4 100644
--- a/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/CustomMenuController.java
@@ -297,7 +297,8 @@ public class CustomMenuController extends Div implements IMenuItemsRegister {
}
resourcesItems.add(subItem(_("Subcontracting"), "/subcontract/subcontractedTasks.zul", "",
subItem(_("Subcontracted Tasks"), "/subcontract/subcontractedTasks.zul", ""),
- subItem(_("Report Progress"), "/subcontract/reportAdvances.zul", "")));
+ subItem(_("Report Progress"), "/subcontract/reportAdvances.zul", ""),
+ subItem(_("Customer subcontracted projects communications"), "/subcontract/customerComunications.zul","")));
topItem(_("Resources"), "/resources/worker/worker.zul", "", resourcesItems);
if (isScenariosVisible()) {
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationCRUDController.java
new file mode 100644
index 000000000..74688fe94
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationCRUDController.java
@@ -0,0 +1,196 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * 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 .
+ */
+
+package org.libreplan.web.subcontract;
+
+import static org.libreplan.web.I18nHelper._;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.logging.LogFactory;
+import org.libreplan.business.common.exceptions.ValidationException;
+import org.libreplan.business.externalcompanies.entities.CustomerComunication;
+import org.libreplan.business.materials.entities.MaterialStatusEnum;
+import org.libreplan.business.orders.entities.Order;
+import org.libreplan.business.workreports.entities.PositionInWorkReportEnum;
+import org.libreplan.web.common.IMessagesForUser;
+import org.libreplan.web.common.MessagesForUser;
+import org.libreplan.web.planner.tabs.IGlobalViewEntryPoints;
+import org.zkoss.ganttz.timetracker.zoom.ZoomLevel;
+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.Button;
+import org.zkoss.zul.Checkbox;
+import org.zkoss.zul.Grid;
+import org.zkoss.zul.Label;
+import org.zkoss.zul.ListModel;
+import org.zkoss.zul.Listbox;
+import org.zkoss.zul.Row;
+import org.zkoss.zul.RowRenderer;
+import org.zkoss.zul.SimpleListModel;
+
+/**
+ * Controller for CRUD actions over a {@link CustomerComunication}
+ *
+ * @author Susana Montes Pedreira
+ */
+@SuppressWarnings("serial")
+public class CustomerComunicationCRUDController extends GenericForwardComposer {
+
+ private static final org.apache.commons.logging.Log LOG = LogFactory
+ .getLog(CustomerComunicationCRUDController.class);
+
+ private ICustomerComunicationModel customerComunicationModel;
+
+ private CustomerComunicationRenderer customerComunicationRenderer = new CustomerComunicationRenderer();;
+
+ protected IMessagesForUser messagesForUser;
+
+ private Component messagesContainer;
+
+ private Grid listing;
+
+ @Resource
+ private IGlobalViewEntryPoints globalView;
+
+ @Override
+ public void doAfterCompose(Component comp) throws Exception {
+ super.doAfterCompose(comp);
+ comp.setAttribute("controller", this);
+ messagesForUser = new MessagesForUser(messagesContainer);
+ }
+
+ public void goToEdit(CustomerComunication customerComunication) {
+ if(customerComunication != null && customerComunication.getOrder() != null){
+ Order order = customerComunication.getOrder();
+ globalView.goToOrderDetails(order);
+ }
+ }
+
+ public FilterCustomerComunicationEnum[] getFilterItems(){
+ return FilterCustomerComunicationEnum.values();
+ }
+
+ public FilterCustomerComunicationEnum getCurrentFilterItem() {
+ return customerComunicationModel.getCurrentFilter();
+ }
+
+ public void setCurrentFilterItem(FilterCustomerComunicationEnum selected) {
+ customerComunicationModel.setCurrentFilter(selected);
+
+ // update the customer comunication list
+ listing.setModel(new SimpleListModel(getCustomerComunications()));
+ listing.invalidate();
+ }
+
+ protected void save(CustomerComunication customerComunication)
+ throws ValidationException {
+ customerComunicationModel.confirmSave(customerComunication);
+ }
+
+ public List getCustomerComunications() {
+ FilterCustomerComunicationEnum currentFilter = customerComunicationModel.getCurrentFilter();
+ switch(currentFilter){
+ case ALL: return customerComunicationModel.getCustomerAllComunications();
+ case NOT_REVIEWED: return customerComunicationModel.getCustomerComunicationWithoutReviewed();
+ default: return customerComunicationModel.getCustomerAllComunications();
+ }
+ }
+
+ public CustomerComunicationRenderer getCustomerComunicationRenderer() {
+ return customerComunicationRenderer;
+ }
+
+ private class CustomerComunicationRenderer implements
+ RowRenderer {
+
+ @Override
+ public void render(Row row, Object data) {
+ CustomerComunication customerComunication = (CustomerComunication) data;
+ row.setValue(customerComunication);
+
+ appendLabel(row, customerComunication.getComunicationType()
+ .toString());
+ appendLabel(row, customerComunication.getOrder().getName());
+ appendLabel(row, toString(customerComunication.getDeadline()));
+ appendLabel(row, customerComunication.getOrder().getCode());
+ appendLabel(row, customerComunication.getOrder()
+ .getCustomerReference());
+ appendLabel(row,
+ toString(customerComunication.getComunicationDate()));
+ appendCheckbox(row, customerComunication);
+ appendOperations(row, customerComunication);
+ }
+
+ private String toString(Date date) {
+ if (date == null) {
+ return "";
+ }
+
+ return new SimpleDateFormat("dd/MM/yyyy HH:mm").format(date);
+ }
+
+ private void appendLabel(Row row, String label) {
+ row.appendChild(new Label(label));
+ }
+
+ private void appendCheckbox(Row row,
+ final CustomerComunication customerComunication) {
+ final Checkbox checkBoxReviewed = new Checkbox();
+ checkBoxReviewed.setChecked(customerComunication.getReviewed());
+
+ checkBoxReviewed.addEventListener(Events.ON_CHECK,
+ new EventListener() {
+
+ @Override
+ public void onEvent(Event arg0) throws Exception {
+ customerComunication.setReviewed(checkBoxReviewed.isChecked());
+ save(customerComunication);
+ }
+
+ });
+
+ row.appendChild(checkBoxReviewed);
+ }
+
+ private void appendOperations(Row row,
+ final CustomerComunication customerComunication) {
+ Button buttonEdit = new Button(_("edit"));
+ buttonEdit.addEventListener(Events.ON_CLICK, new EventListener() {
+
+ @Override
+ public void onEvent(Event arg0) throws Exception {
+ goToEdit(customerComunication);
+ }
+
+ });
+ row.appendChild(buttonEdit);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationModel.java
new file mode 100644
index 000000000..bc8f6ede9
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/CustomerComunicationModel.java
@@ -0,0 +1,63 @@
+package org.libreplan.web.subcontract;
+
+import java.util.List;
+
+import org.libreplan.business.externalcompanies.daos.ICustomerComunicationDAO;
+import org.libreplan.business.externalcompanies.entities.CustomerComunication;
+import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+@OnConcurrentModification(goToPage = "/subcontract/customerComunication.zul")
+public class CustomerComunicationModel implements ICustomerComunicationModel{
+
+ @Autowired
+ private ICustomerComunicationDAO customerComunicationDAO;
+
+ private FilterCustomerComunicationEnum currentFilter = FilterCustomerComunicationEnum.NOT_REVIEWED;
+
+ @Override
+ @Transactional
+ public void confirmSave(CustomerComunication customerComunication){
+ customerComunicationDAO.save(customerComunication);
+ }
+
+ @Override
+ @Transactional
+ public List getCustomerAllComunications(){
+ List list = customerComunicationDAO.getAll();
+ forceLoadAssociatedOrder(list);
+ return list;
+ }
+
+ @Override
+ @Transactional
+ public List getCustomerComunicationWithoutReviewed(){
+ List list = customerComunicationDAO.getAllNotReviewed();
+ forceLoadAssociatedOrder(list);
+ return list;
+ }
+
+ private void forceLoadAssociatedOrder(List customerComunicationList){
+ if (customerComunicationList != null) {
+ for (CustomerComunication customerComunication : customerComunicationList) {
+ customerComunication.getOrder().getName();
+ }
+ }
+ }
+
+ @Override
+ public void setCurrentFilter(FilterCustomerComunicationEnum currentFilter) {
+ this.currentFilter = currentFilter;
+ }
+
+ @Override
+ public FilterCustomerComunicationEnum getCurrentFilter() {
+ return currentFilter;
+ }
+}
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/FilterCustomerComunicationEnum.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/FilterCustomerComunicationEnum.java
new file mode 100644
index 000000000..89681f5fe
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/FilterCustomerComunicationEnum.java
@@ -0,0 +1,54 @@
+/*
+ * This file is part of NavalPlan
+ *
+ * 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 .
+ */
+
+package org.libreplan.web.subcontract;
+
+/**
+ * Enum to filter the {@link CustomerComunication} list.
+ *
+ * @author Susana Montes Pedreira
+ */
+ public enum FilterCustomerComunicationEnum {
+ ALL(_("All")),
+ NOT_REVIEWED(_("Not Reviewed"));
+
+ /**
+ * Forces to mark the string as needing translation
+ */
+ private static String _(String string) {
+ return string;
+ }
+
+ private String displayName;
+
+ private FilterCustomerComunicationEnum(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public static FilterCustomerComunicationEnum getDefault() {
+ return ALL;
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+ }
\ No newline at end of file
diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ICustomerComunicationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ICustomerComunicationModel.java
new file mode 100644
index 000000000..a80cdbf20
--- /dev/null
+++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ICustomerComunicationModel.java
@@ -0,0 +1,19 @@
+package org.libreplan.web.subcontract;
+
+import java.util.List;
+
+import org.libreplan.business.externalcompanies.entities.CustomerComunication;
+
+public interface ICustomerComunicationModel {
+
+ void confirmSave(CustomerComunication customerComunication);
+
+ List getCustomerComunicationWithoutReviewed();
+
+ List getCustomerAllComunications();
+
+ void setCurrentFilter(FilterCustomerComunicationEnum currentFilter);
+
+ FilterCustomerComunicationEnum getCurrentFilter();
+
+}
diff --git a/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul b/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul
new file mode 100644
index 000000000..2faca2e88
--- /dev/null
+++ b/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file