diff --git a/libreplan-business/src/main/java/org/libreplan/business/planner/daos/ISubcontractedTaskDataDAO.java b/libreplan-business/src/main/java/org/libreplan/business/planner/daos/ISubcontractedTaskDataDAO.java index 265d77030..86da35b8a 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/planner/daos/ISubcontractedTaskDataDAO.java +++ b/libreplan-business/src/main/java/org/libreplan/business/planner/daos/ISubcontractedTaskDataDAO.java @@ -24,6 +24,8 @@ package org.libreplan.business.planner.daos; import java.util.List; import org.libreplan.business.common.daos.IGenericDAO; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.orders.entities.OrderElement; import org.libreplan.business.planner.entities.SubcontractedTaskData; /** @@ -42,4 +44,6 @@ public interface ISubcontractedTaskDataDAO extends List getAllForMasterScenario(); + SubcontractedTaskData getSubcontratedTaskDataByOrderElement( + OrderElement orderElement) throws InstanceNotFoundException; } \ No newline at end of file diff --git a/libreplan-business/src/main/java/org/libreplan/business/planner/daos/SubcontractedTaskDataDAO.java b/libreplan-business/src/main/java/org/libreplan/business/planner/daos/SubcontractedTaskDataDAO.java index 757960f71..61b53651c 100644 --- a/libreplan-business/src/main/java/org/libreplan/business/planner/daos/SubcontractedTaskDataDAO.java +++ b/libreplan-business/src/main/java/org/libreplan/business/planner/daos/SubcontractedTaskDataDAO.java @@ -24,10 +24,13 @@ package org.libreplan.business.planner.daos; import java.util.ArrayList; import java.util.List; +import org.hibernate.Criteria; +import org.hibernate.criterion.Restrictions; import org.libreplan.business.common.daos.GenericDAOHibernate; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.orders.entities.TaskSource; import org.libreplan.business.planner.entities.SubcontractedTaskData; import org.libreplan.business.planner.entities.Task; import org.libreplan.business.planner.entities.TaskElement; @@ -99,4 +102,18 @@ public class SubcontractedTaskDataDAO extends return result; } + @Override + @Transactional(readOnly = true) + public SubcontractedTaskData getSubcontratedTaskDataByOrderElement( + OrderElement orderElement) throws InstanceNotFoundException { + Criteria c = getSession().createCriteria(TaskElement.class) + .createCriteria("taskSource","ts") + .createCriteria("schedulingData","data") + .add(Restrictions.eq("data.orderElement",orderElement)); + + TaskElement taskElement = (TaskElement) c.uniqueResult(); + return (taskElement != null && taskElement.isSubcontracted()) ? ((Task) taskElement) + .getSubcontractedTaskData() : null; + } + } \ No newline at end of file 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 646c4e6a4..b7fcc8020 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,6 +297,7 @@ public class CustomMenuController extends Div implements IMenuItemsRegister { } resourcesItems.add(subItem(_("Subcontracting"), "/subcontract/subcontractedTasks.zul", "", subItem(_("Subcontracted Tasks"), "/subcontract/subcontractedTasks.zul", ""), + subItem(_("Incoming communications from subcontractors"), "/subcontract/subcontractorComunications.zul",""), subItem(_("Report Progress"), "/subcontract/reportAdvances.zul", ""), subItem(_("Customer subcontracted projects communications"), "/subcontract/customerComunications.zul",""))); topItem(_("Resources"), "/resources/worker/worker.zul", "", resourcesItems); diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskConverter.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskConverter.java new file mode 100644 index 000000000..b8996cff7 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskConverter.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package org.libreplan.web.common.converters; + +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.planner.daos.ITaskElementDAO; +import org.libreplan.business.planner.entities.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +/** + * A {@link IConverter} for {@link Task}
+ * @author Susana Montes Pedreira + */ +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class TaskConverter implements IConverter { + + @Autowired + private ITaskElementDAO taskDAO; + + @Override + @Transactional(readOnly = true) + public Task asObject(String stringRepresentation) { + try { + return (Task) taskDAO.find(Long.parseLong(stringRepresentation)); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public String asString(Task entity) { + return entity.getId() + ""; + } + + @Override + public String asStringUngeneric(Object entity) { + return asString((Task) entity); + } + + @Override + public Class getType() { + return Task.class; + } + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskElementConverter.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskElementConverter.java new file mode 100644 index 000000000..8cbf74f7c --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/converters/TaskElementConverter.java @@ -0,0 +1,68 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2010-2011 Wireless Galicia, 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.common.converters; + +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.planner.daos.ITaskElementDAO; +import org.libreplan.business.planner.entities.TaskElement; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +/** + * A {@link IConverter} for {@link TaskElement}
+ * @author Susana Montes Pedreira + */ + +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class TaskElementConverter implements IConverter { + + @Autowired + private ITaskElementDAO taskElementDAO; + + @Override + public String asString(TaskElement entity) { + return entity.getId() + ""; + } + + @Override + public Class getType() { + return TaskElement.class; + } + + @Override + public String asStringUngeneric(Object entity) { + return asString((TaskElement) entity); + } + + @Override + @Transactional(readOnly = true) + public TaskElement asObject(String stringRepresentation) { + long id = Long.parseLong(stringRepresentation); + try { + return taskElementDAO.find(id); + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + } \ No newline at end of file diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/advances/AdvanceAssignmentPlanningController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/advances/AdvanceAssignmentPlanningController.java index 3ae28ea5b..fee5a0410 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/advances/AdvanceAssignmentPlanningController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/advances/AdvanceAssignmentPlanningController.java @@ -75,7 +75,6 @@ public class AdvanceAssignmentPlanningController extends GenericForwardComposer public void showWindow(IContextWithPlannerTask context, TaskElement task, PlanningState planningState) { - this.context = context; advanceAssignmentPlanningModel.initAdvancesFor(task, context, planningState); @@ -84,7 +83,7 @@ public class AdvanceAssignmentPlanningController extends GenericForwardComposer try { window.setTitle(getTitle()); Util.reloadBindings(window); - this.window.doModal(); + this.window.setMode("modal"); } catch (SuspendNotAllowedException e) { throw new RuntimeException(e); } catch (InterruptedException e) { diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningController.java index 089cbfa0f..f061776ad 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/order/OrderPlanningController.java @@ -63,6 +63,7 @@ import org.zkoss.ganttz.util.ProfilingLogFactory; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.util.Composer; +import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Checkbox; import org.zkoss.zul.Constraint; import org.zkoss.zul.Datebox; @@ -108,6 +109,8 @@ public class OrderPlanningController implements Composer { @Autowired private OrderCRUDController orderCRUDController; + private GenericForwardComposer currentControllerToShow; + private Order order; private TaskElement task; @@ -214,6 +217,7 @@ public class OrderPlanningController implements Composer { + (System.currentTimeMillis() - time) + " ms"); planner.updateSelectedZoomLevel(); showResorceAllocationIfIsNeeded(); + } } @@ -362,9 +366,17 @@ public class OrderPlanningController implements Composer { if ((foundTask != null) && (foundTaskElement != null)) { IContextWithPlannerTask contextTask = ContextWithPlannerTask .create(context, foundTask); - this.editTaskController - .showEditFormResourceAllocation(contextTask, - foundTaskElement, model.getPlanningState()); + if (this.getCurrentControllerToShow().equals( + getEditTaskController())) { + this.editTaskController.showEditFormResourceAllocation( + contextTask, foundTaskElement, + model.getPlanningState()); + } else if (this.getCurrentControllerToShow().equals( + this.getAdvanceAssignmentPlanningController())) { + getAdvanceAssignmentPlanningController().showWindow( + contextTask, foundTaskElement, + model.getPlanningState()); + } } } } @@ -377,4 +389,12 @@ public class OrderPlanningController implements Composer { return advanceAssignmentPlanningController; } + public void setCurrentControllerToShow(GenericForwardComposer currentControllerToShow) { + this.currentControllerToShow = currentControllerToShow; + } + + public GenericForwardComposer getCurrentControllerToShow() { + return currentControllerToShow; + } + } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/IGlobalViewEntryPoints.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/IGlobalViewEntryPoints.java index 7fe51aa39..3e8ea69cc 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/IGlobalViewEntryPoints.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/IGlobalViewEntryPoints.java @@ -22,6 +22,8 @@ package org.libreplan.web.planner.tabs; import org.libreplan.business.orders.entities.Order; import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.planner.entities.Task; +import org.libreplan.business.planner.entities.TaskElement; import org.libreplan.business.templates.entities.OrderTemplate; import org.libreplan.web.common.entrypoints.EntryPoint; import org.libreplan.web.common.entrypoints.EntryPoints; @@ -65,4 +67,7 @@ public interface IGlobalViewEntryPoints { @EntryPoint("create_order_from_template") void goToCreateotherOrderFromTemplate(OrderTemplate template); + + @EntryPoint({"order","task"}) + void goToAdvanceTask(Order order,TaskElement task); } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java index b3874e698..78e4b80d2 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/tabs/MultipleTabsPlannerController.java @@ -216,6 +216,7 @@ public class MultipleTabsPlannerController implements Composer, public void goToTaskResourceAllocation(Order order, TaskElement task) { orderPlanningController.setShowedTask(task); + orderPlanningController.setCurrentControllerToShow(orderPlanningController.getEditTaskController()); getTabsRegistry() .show(planningTab, changeModeTo(order)); } @@ -438,6 +439,15 @@ public class MultipleTabsPlannerController implements Composer, orderCRUDController.showCreateFormFromTemplate(template); } + @Override + public void goToAdvanceTask(Order order,TaskElement task) { + orderPlanningController.setShowedTask(task); + orderPlanningController + .setCurrentControllerToShow(orderPlanningController + .getAdvanceAssignmentPlanningController()); + getTabsRegistry().show(planningTab, changeModeTo(order)); + } + private IBeforeShowAction changeModeTo(final Order order) { return new IBeforeShowAction() { @Override diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/EditTaskController.java b/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/EditTaskController.java index babf31491..0fc4d1c98 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/EditTaskController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/EditTaskController.java @@ -185,7 +185,6 @@ public class EditTaskController extends GenericForwardComposer { planningState, messagesForUser); showLimitingResourcesTab(); } - } private void showSubcontractTab() { diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ISubcontractorComunicationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ISubcontractorComunicationModel.java new file mode 100644 index 000000000..a69ede783 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/ISubcontractorComunicationModel.java @@ -0,0 +1,49 @@ +/* + * 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 java.util.List; + +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.planner.entities.SubcontractedTaskData; +import org.libreplan.business.planner.entities.SubcontractorComunication; + +public interface ISubcontractorComunicationModel { + + void confirmSave(SubcontractorComunication customerComunication); + + List getSubcontractorComunicationWithoutReviewed(); + + List getSubcontractorAllComunications(); + + void setCurrentFilter(FilterComunicationEnum currentFilter); + + FilterComunicationEnum getCurrentFilter(); + + String getOrderCode(SubcontractedTaskData subcontractedTaskData); + + String getOrderName(SubcontractedTaskData subcontractedTaskData); + + Order getOrder(OrderElement orderElement); + +} diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationCRUDController.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationCRUDController.java new file mode 100644 index 000000000..0cf449f11 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationCRUDController.java @@ -0,0 +1,239 @@ +/* + * 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.ComunicationType; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.planner.entities.SubcontractedTaskData; +import org.libreplan.business.planner.entities.SubcontractorComunication; +import org.libreplan.business.planner.entities.SubcontractorComunicationValue; +import org.libreplan.business.planner.entities.Task; +import org.libreplan.business.planner.entities.TaskElement; +import org.libreplan.web.common.IMessagesForUser; +import org.libreplan.web.common.MessagesForUser; +import org.libreplan.web.common.Util; +import org.libreplan.web.planner.tabs.IGlobalViewEntryPoints; +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.Messagebox; +import org.zkoss.zul.Popup; +import org.zkoss.zul.Row; +import org.zkoss.zul.RowRenderer; +import org.zkoss.zul.SimpleListModel; + +/** + * Controller for CRUD actions over a {@link SubcontractorComunication} + * + * @author Susana Montes Pedreira + */ +@SuppressWarnings("serial") +public class SubcontractorComunicationCRUDController extends GenericForwardComposer { + + private static final org.apache.commons.logging.Log LOG = LogFactory + .getLog(SubcontractorComunicationCRUDController.class); + + private ISubcontractorComunicationModel subcontractorComunicationModel; + + private SubcontractorComunicationRenderer subcontractorComunicationRenderer = new SubcontractorComunicationRenderer();; + + protected IMessagesForUser messagesForUser; + + private Component messagesContainer; + + private Grid listing; + + private Grid listingValues; + + private Label labelValue; + + private Popup pp; + + @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(SubcontractorComunication subcontractorComunication) { + if(subcontractorComunication != null){ + TaskElement task = subcontractorComunication.getSubcontractedTaskData().getTask(); + OrderElement orderElement = task.getOrderElement(); + Order order = subcontractorComunicationModel.getOrder(orderElement); + globalView.goToAdvanceTask(order,task); + } + } + + public FilterComunicationEnum[] getFilterItems(){ + return FilterComunicationEnum.values(); + } + + public FilterComunicationEnum getCurrentFilterItem() { + return subcontractorComunicationModel.getCurrentFilter(); + } + + public void setCurrentFilterItem(FilterComunicationEnum selected) { + subcontractorComunicationModel.setCurrentFilter(selected); + + // update the subcontractor comunication list + listing.setModel(new SimpleListModel(getSubcontractorComunications())); + listing.invalidate(); + } + + protected void save(SubcontractorComunication subcontractorComunication) + throws ValidationException { + subcontractorComunicationModel.confirmSave(subcontractorComunication); + } + + public List getSubcontractorComunications() { + FilterComunicationEnum currentFilter = subcontractorComunicationModel.getCurrentFilter(); + switch(currentFilter){ + case ALL: return subcontractorComunicationModel.getSubcontractorAllComunications(); + case NOT_REVIEWED: return subcontractorComunicationModel.getSubcontractorComunicationWithoutReviewed(); + default: return subcontractorComunicationModel.getSubcontractorAllComunications(); + } + } + + public SubcontractorComunicationRenderer getSubcontractorComunicationRenderer() { + return subcontractorComunicationRenderer; + } + + private class SubcontractorComunicationRenderer implements + RowRenderer { + + @Override + public void render(Row row, Object data) { + SubcontractorComunication subcontractorComunication = (SubcontractorComunication) data; + row.setValue(subcontractorComunication); + + appendLabel(row, subcontractorComunication.getComunicationType().toString()); + appendLabel(row, subcontractorComunication.getSubcontractedTaskData().getTask().getName()); + appendLabel(row, getOrderName(subcontractorComunication.getSubcontractedTaskData())); + appendLabel(row, getOrderCode(subcontractorComunication.getSubcontractedTaskData())); + appendLabel(row, subcontractorComunication.getSubcontractedTaskData().getExternalCompany().getName()); + appendLabel(row, toString(subcontractorComunication.getComunicationDate())); + appendLabelWitTooltip(row,subcontractorComunication); + appendCheckbox(row, subcontractorComunication); + appendOperations(row, subcontractorComunication); + } + + private String toString(Date date) { + if (date == null) { + return ""; + } + + return new SimpleDateFormat("dd/MM/yyyy HH:mm").format(date); + } + + private String getOrderCode(SubcontractedTaskData subcontractedTaskData) { + return subcontractorComunicationModel.getOrderCode(subcontractedTaskData); + } + + private String getOrderName(SubcontractedTaskData subcontractedTaskData) { + return subcontractorComunicationModel.getOrderName(subcontractedTaskData); + } + + private String getLastValue( + SubcontractorComunication subcontractorComunication) { + SubcontractorComunicationValue value = subcontractorComunication + .getLastSubcontratorComunicationValues(); + return (value != null) ? value.toString() : ""; + } + + private void appendLabel(Row row, String label) { + row.appendChild(new Label(label)); + } + + private void appendLabelWitTooltip(final Row row,final SubcontractorComunication subcontractorComunication) { + String lastValue = getLastValue(subcontractorComunication); + final Label compLabel = new Label(lastValue); + + compLabel.setTooltip(pp); + compLabel.addEventListener(Events.ON_MOUSE_OVER, + new EventListener() { + @Override + public void onEvent(Event arg0) throws Exception { + List model = subcontractorComunication + .getSubcontratorComunicationValues(); + listingValues.setModel(new SimpleListModel(model)); + listingValues.invalidate(); + } + }); + row.appendChild(compLabel); + } + + private void appendCheckbox(Row row, + final SubcontractorComunication subcontractorComunication) { + final Checkbox checkBoxReviewed = new Checkbox(); + checkBoxReviewed.setChecked(subcontractorComunication.getReviewed()); + + checkBoxReviewed.addEventListener(Events.ON_CHECK, + new EventListener() { + + @Override + public void onEvent(Event arg0) throws Exception { + subcontractorComunication.setReviewed(checkBoxReviewed.isChecked()); + save(subcontractorComunication); + } + + }); + + row.appendChild(checkBoxReviewed); + } + + private void appendOperations(Row row, + final SubcontractorComunication subcontractorComunication) { + Button buttonEdit = new Button(_("edit")); + buttonEdit.addEventListener(Events.ON_CLICK, new EventListener() { + + @Override + public void onEvent(Event arg0) throws Exception { + goToEdit(subcontractorComunication); + } + + }); + row.appendChild(buttonEdit); + } + } + +} \ No newline at end of file diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationModel.java new file mode 100644 index 000000000..ff62a0f60 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/subcontract/SubcontractorComunicationModel.java @@ -0,0 +1,128 @@ +/* + * 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 java.util.List; + +import org.libreplan.business.orders.daos.IOrderDAO; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderElement; +import org.libreplan.business.planner.daos.ISubcontractorComunicationDAO; +import org.libreplan.business.planner.entities.SubcontractedTaskData; +import org.libreplan.business.planner.entities.SubcontractorComunication; +import org.libreplan.business.planner.entities.SubcontractorComunicationValue; +import org.libreplan.business.planner.entities.Task; +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/subcontractorComunication.zul") +public class SubcontractorComunicationModel implements ISubcontractorComunicationModel{ + + @Autowired + private ISubcontractorComunicationDAO subcontractorComunicationDAO; + + @Autowired + IOrderDAO orderDAO; + + private FilterComunicationEnum currentFilter = FilterComunicationEnum.NOT_REVIEWED; + + @Override + @Transactional + public void confirmSave(SubcontractorComunication subcontractorComunication){ + subcontractorComunicationDAO.save(subcontractorComunication); + } + + @Override + @Transactional + public List getSubcontractorAllComunications(){ + List list = subcontractorComunicationDAO.getAll(); + forceLoadAssociatedData(list); + return list; + } + + @Override + @Transactional + public List getSubcontractorComunicationWithoutReviewed(){ + List list = subcontractorComunicationDAO.getAllNotReviewed(); + forceLoadAssociatedData(list); + return list; + } + + private void forceLoadAssociatedData(List subcontractorComunicationList){ + if (subcontractorComunicationList != null) { + for (SubcontractorComunication subcontractorComunication : subcontractorComunicationList) { + subcontractorComunication.getSubcontractedTaskData().getExternalCompany().getName(); + subcontractorComunication.getSubcontractedTaskData().getTask().getName(); + subcontractorComunication.getSubcontractedTaskData().getTask().getOrderElement().getName(); + subcontractorComunication.getLastSubcontratorComunicationValues().getDate(); + } + } + } + + private void forceLoadAssociatedDataValue(List subcontractorComunicationValueList){ + if (subcontractorComunicationValueList != null) { + for (SubcontractorComunicationValue value : subcontractorComunicationValueList) { + value.getDate(); + } + } + } + + @Override + @Transactional(readOnly = true) + public String getOrderCode(SubcontractedTaskData subcontractedTaskData) { + Task task = subcontractedTaskData.getTask(); + OrderElement orderElement = orderDAO.loadOrderAvoidingProxyFor(task + .getOrderElement()); + return orderElement.getOrder().getCode(); + } + + @Override + @Transactional(readOnly = true) + public String getOrderName(SubcontractedTaskData subcontractedTaskData) { + Task task = subcontractedTaskData.getTask(); + OrderElement orderElement = orderDAO.loadOrderAvoidingProxyFor(task + .getOrderElement()); + return orderElement.getOrder().getName(); + } + + @Override + public void setCurrentFilter(FilterComunicationEnum currentFilter) { + this.currentFilter = currentFilter; + } + + @Override + public FilterComunicationEnum getCurrentFilter() { + return currentFilter; + } + + @Override + @Transactional(readOnly = true) + public Order getOrder(OrderElement orderElement) { + return (orderDAO.loadOrderAvoidingProxyFor(orderElement)).getOrder(); + } +} \ No newline at end of file diff --git a/libreplan-webapp/src/main/java/org/libreplan/ws/subcontract/impl/ReportAdvancesServiceREST.java b/libreplan-webapp/src/main/java/org/libreplan/ws/subcontract/impl/ReportAdvancesServiceREST.java index 030218bd9..7def9bab2 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/ws/subcontract/impl/ReportAdvancesServiceREST.java +++ b/libreplan-webapp/src/main/java/org/libreplan/ws/subcontract/impl/ReportAdvancesServiceREST.java @@ -24,12 +24,15 @@ package org.libreplan.ws.subcontract.impl; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.xml.datatype.XMLGregorianCalendar; import org.apache.commons.lang.StringUtils; import org.libreplan.business.advance.bootstrap.PredefinedAdvancedTypes; @@ -41,11 +44,18 @@ import org.libreplan.business.advance.exceptions.DuplicateValueTrueReportGlobalA import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.common.exceptions.ValidationException; import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO; +import org.libreplan.business.externalcompanies.entities.ComunicationType; import org.libreplan.business.externalcompanies.entities.ExternalCompany; 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.planner.daos.ISubcontractedTaskDataDAO; +import org.libreplan.business.planner.daos.ISubcontractorComunicationDAO; +import org.libreplan.business.planner.entities.SubcontractedTaskData; +import org.libreplan.business.planner.entities.SubcontractorComunication; +import org.libreplan.business.planner.entities.SubcontractorComunicationValue; +import org.libreplan.business.planner.entities.Task; import org.libreplan.business.scenarios.bootstrap.PredefinedScenarios; import org.libreplan.business.scenarios.entities.OrderVersion; import org.libreplan.business.scenarios.entities.Scenario; @@ -76,6 +86,12 @@ public class ReportAdvancesServiceREST implements IReportAdvancesService { @Autowired private IOrderElementDAO orderElementDAO; + @Autowired + private ISubcontractedTaskDataDAO subcontractedTaskDataDAO; + + @Autowired + private ISubcontractorComunicationDAO subcontractorComunicationDAO; + @Autowired private IOrderDAO orderDAO; @@ -190,6 +206,17 @@ public class ReportAdvancesServiceREST implements IReportAdvancesService { orderElement.validate(); orderElementDAO.save(orderElement); + + /* + * If the order element is subcontrated then create the + * subcontrated comunication for the subcontrated task data to + * which the order element belongs. + */ + createSubcontractorComunication( + orderElement, + orderElementWithAdvanceMeasurementsDTO.advanceMeasurements); + + } catch (ValidationException e) { instanceConstraintViolationsDTO = ConstraintViolationConverter .toDTO(Util.generateInstanceId(1, @@ -211,6 +238,39 @@ public class ReportAdvancesServiceREST implements IReportAdvancesService { instanceConstraintViolationsList); } + public void createSubcontractorComunication(OrderElement orderElement, + Set advanceMeasurementDTOs) + throws InstanceNotFoundException { + if (orderElement != null + && orderElement.getTaskSource() != null + && orderElement.getTaskSource().getTask().isSubcontracted()){ + Task task = (Task) orderElement.getTaskSource().getTask(); + SubcontractedTaskData subcontractedTaskData = task + .getSubcontractedTaskData(); + if (subcontractedTaskData != null) { + SubcontractorComunication subcontractorComunication = SubcontractorComunication + .create(subcontractedTaskData, + ComunicationType.REPORT_ADVANCE, new Date(), + false); + + for (AdvanceMeasurementDTO advanceMeasurementDTO : advanceMeasurementDTOs) { + // add subcontractorComunicationValue + addSubcontractorComunicationValue(advanceMeasurementDTO, + subcontractorComunication); + } + subcontractorComunicationDAO.save(subcontractorComunication); + } + } + } + + private void addSubcontractorComunicationValue(AdvanceMeasurementDTO advanceMeasurementDTO, SubcontractorComunication subcontractorComunication ){ + Date dateValue = DateConverter.toDate(advanceMeasurementDTO.date); + SubcontractorComunicationValue value = SubcontractorComunicationValue + .create(dateValue, advanceMeasurementDTO.value); + subcontractorComunication.getSubcontratorComunicationValues() + .add(value); + } + private void updateAdvancePercentage(OrderVersion orderVersion, OrderElement orderElement) { orderElement.useSchedulingDataFor(orderVersion); diff --git a/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul b/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul index 79c08b6c7..df788525a 100644 --- a/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul +++ b/libreplan-webapp/src/main/webapp/subcontract/customerComunications.zul @@ -19,7 +19,7 @@ along with this program. If not, see . --> - + diff --git a/libreplan-webapp/src/main/webapp/subcontract/subcontractorComunications.zul b/libreplan-webapp/src/main/webapp/subcontract/subcontractorComunications.zul new file mode 100644 index 000000000..ea5aaa381 --- /dev/null +++ b/libreplan-webapp/src/main/webapp/subcontract/subcontractorComunications.zul @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/libreplan-webapp/src/test/java/org/libreplan/web/test/ws/subcontract/ReportAdvancesServiceTest.java b/libreplan-webapp/src/test/java/org/libreplan/web/test/ws/subcontract/ReportAdvancesServiceTest.java index 384d1ae1a..1838d8bdc 100644 --- a/libreplan-webapp/src/test/java/org/libreplan/web/test/ws/subcontract/ReportAdvancesServiceTest.java +++ b/libreplan-webapp/src/test/java/org/libreplan/web/test/ws/subcontract/ReportAdvancesServiceTest.java @@ -36,6 +36,7 @@ import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -54,13 +55,26 @@ import org.libreplan.business.advance.entities.DirectAdvanceAssignment; import org.libreplan.business.common.IAdHocTransactionService; import org.libreplan.business.common.IOnTransaction; import org.libreplan.business.common.daos.IConfigurationDAO; +import org.libreplan.business.common.daos.IGenericDAO; +import org.libreplan.business.common.entities.Configuration; import org.libreplan.business.common.exceptions.InstanceNotFoundException; import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO; import org.libreplan.business.externalcompanies.entities.ExternalCompany; import org.libreplan.business.orders.daos.IOrderDAO; +import org.libreplan.business.orders.daos.IOrderElementDAO; +import org.libreplan.business.orders.entities.HoursGroup; 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.orders.entities.SchedulingDataForVersion; +import org.libreplan.business.orders.entities.TaskSource; +import org.libreplan.business.orders.entities.TaskSource.TaskSourceSynchronization; +import org.libreplan.business.planner.daos.ISubcontractedTaskDataDAO; +import org.libreplan.business.planner.daos.ISubcontractorComunicationDAO; +import org.libreplan.business.planner.daos.ITaskElementDAO; +import org.libreplan.business.planner.daos.ITaskSourceDAO; +import org.libreplan.business.planner.entities.SubcontractedTaskData; +import org.libreplan.business.planner.entities.Task; import org.libreplan.business.scenarios.IScenarioManager; import org.libreplan.business.scenarios.entities.OrderVersion; import org.libreplan.web.orders.OrderModelTest; @@ -70,6 +84,7 @@ import org.libreplan.ws.subcontract.api.IReportAdvancesService; import org.libreplan.ws.subcontract.api.OrderElementWithAdvanceMeasurementsDTO; import org.libreplan.ws.subcontract.api.OrderElementWithAdvanceMeasurementsListDTO; import org.springframework.beans.factory.annotation.Autowired; +import org.libreplan.business.planner.entities.SubcontractorComunication; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.annotation.Transactional; @@ -122,6 +137,9 @@ public class ReportAdvancesServiceTest { @Autowired private IOrderDAO orderDAO; + @Autowired + private IOrderElementDAO orderElementDAO; + @Autowired private IConfigurationDAO configurationDAO; @@ -134,8 +152,25 @@ public class ReportAdvancesServiceTest { @Autowired private IScenarioManager scenarioManager; - private ExternalCompany getSubcontractorExternalCompanySaved(String name, - String nif) { + @Autowired + private ISubcontractorComunicationDAO subcontractorComunicationDAO; + + @Autowired + private ISubcontractedTaskDataDAO subcontractorTaskDataDAO; + + private HoursGroup associatedHoursGroup; + + @Autowired + private ITaskSourceDAO taskSourceDAO; + + @Autowired + private ITaskElementDAO taskElementDAO; + + @Autowired + private ISubcontractedTaskDataDAO subcontractedTaskDataDAO; + + private ExternalCompany getExternalCompany(String name, + String nif){ ExternalCompany externalCompany = ExternalCompany.create(name, nif); externalCompany.setSubcontractor(true); @@ -148,6 +183,18 @@ public class ReportAdvancesServiceTest { return externalCompany; } + private ExternalCompany getSubcontractorExternalCompanySaved() { + return transactionService + .runOnAnotherTransaction(new IOnTransaction() { + @Override + public ExternalCompany execute() { + return getExternalCompany("Company" + + UUID.randomUUID().toString(), UUID + .randomUUID().toString()); + } + }); + } + @Test public void validAdvancesReport() { Order order = givenOrder(); @@ -184,6 +231,47 @@ public class ReportAdvancesServiceTest { } } + @Test + public void validAdvancesReportToSubcontratedOrderElement() { + int previousComunications = subcontractorComunicationDAO.getAll().size(); + OrderLine orderLine = createOrderLine(); + String orderElementCode = orderLine.getCode(); + + Map values = givenValidMapValues(1, 0, + BigDecimal.ZERO); + + OrderElementWithAdvanceMeasurementsListDTO orderElementWithAdvanceMeasurementsListDTO = givenOrderElementWithAdvanceMeasurementsListDTO( + orderElementCode, values); + SubcontractorComunication subcontractorComunication = SubcontractorComunication.create(); + reportAdvancesService + .updateAdvances(orderElementWithAdvanceMeasurementsListDTO); + + Order foundOrder = orderDAO.findExistingEntity(orderLine.getOrder().getId()); + assertNotNull(foundOrder); + assertThat(foundOrder.getChildren().size(), equalTo(1)); + + OrderElement orderElement = foundOrder.getChildren().get(0); + assertNotNull(orderElement); + + DirectAdvanceAssignment directAdvanceAssignmentSubcontractor = orderElement + .getDirectAdvanceAssignmentSubcontractor(); + assertNotNull(directAdvanceAssignmentSubcontractor); + assertTrue(directAdvanceAssignmentSubcontractor + .getReportGlobalAdvance()); + assertThat(directAdvanceAssignmentSubcontractor + .getAdvanceMeasurements().size(), equalTo(1)); + + for (Entry entry : values.entrySet()) { + AdvanceMeasurement advanceMeasurement = directAdvanceAssignmentSubcontractor + .getAdvanceMeasurements().first(); + assertThat(advanceMeasurement.getDate(), equalTo(entry.getKey())); + assertThat(advanceMeasurement.getValue(), equalTo(entry.getValue())); + } + + int currentComunications = subcontractorComunicationDAO.getAll().size(); + assertThat((previousComunications+1), equalTo(currentComunications)); + } + @Test public void validAdvancesReportWithSeveralDates() { Order order = givenOrder(); @@ -233,8 +321,7 @@ public class ReportAdvancesServiceTest { orderElementWithAdvanceMeasurementsDTO.advanceMeasurements = givenAdvanceMeasurementDTOs(values); - ExternalCompany externalCompany = getSubcontractorExternalCompanySaved( - "Company", "company-nif"); + ExternalCompany externalCompany = getSubcontractorExternalCompanySaved(); return new OrderElementWithAdvanceMeasurementsListDTO(externalCompany .getNif(), Arrays @@ -289,8 +376,10 @@ public class ReportAdvancesServiceTest { OrderVersion version = OrderModelTest.setupVersionUsing( scenarioManager, order); order.useSchedulingDataFor(version); + OrderLine orderLine = OrderLine .createOrderLineWithUnfixedPercentage(1000); + orderLine.useSchedulingDataFor(version); order.add(orderLine); orderLine.setCode(UUID.randomUUID().toString()); orderLine.setName("Order line name"); @@ -304,4 +393,54 @@ public class ReportAdvancesServiceTest { } } + private OrderLine createOrderLine(){ + return transactionService + .runOnAnotherTransaction(new IOnTransaction() { + @Override + public OrderLine execute() { + Order order = givenValidOrderAlreadyStored(); + OrderLine orderLine = (OrderLine) order.getChildren().get(0); + createValidSubcontractedTaskData("subcotrated_task_"+UUID.randomUUID().toString(), orderLine); + return orderLine; + } + }); + } + + private Task createValidTask(OrderLine orderLine) { + associatedHoursGroup = new HoursGroup(); + associatedHoursGroup.setCode("hours-group-code-" + UUID.randomUUID()); + + orderLine.addHoursGroup(associatedHoursGroup); + SchedulingDataForVersion schedulingDataForVersion = orderLine + .getCurrentSchedulingDataForVersion(); + + TaskSource taskSource = TaskSource.create(schedulingDataForVersion, + Arrays.asList(associatedHoursGroup)); + + orderLine.getCurrentSchedulingData().requestedCreationOf(taskSource); + + TaskSourceSynchronization mustAdd = TaskSource.mustAdd(taskSource); + mustAdd.apply(TaskSource.persistTaskSources(taskSourceDAO)); + + Task task = (Task) taskSource.getTask(); + return task; + } + + public SubcontractedTaskData createValidSubcontractedTaskData(final String name, final OrderLine orderLine) { + Task task = createValidTask(orderLine); + SubcontractedTaskData subcontractedTaskData = SubcontractedTaskData + .create(task); + subcontractedTaskData.setExternalCompany(getSubcontractorExternalCompanySaved()); + + task.setSubcontractedTaskData(subcontractedTaskData); + taskElementDAO.save(task); + task.dontPoseAsTransientObjectAnymore(); + taskElementDAO.flush(); + + sessionFactory.getCurrentSession().evict(task); + sessionFactory.getCurrentSession().evict(subcontractedTaskData); + + subcontractedTaskDataDAO.save(subcontractedTaskData); + return subcontractedTaskData; + } }