Create a list with all the communications received from subcontractors

FEA: ItEr75S30SubcontractorIncommingCommunicationsLists
This commit is contained in:
Susana Montes Pedreira 2011-11-15 10:13:02 +01:00
parent 1e214e328d
commit c92de60de2
17 changed files with 897 additions and 11 deletions

View file

@ -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<SubcontractedTaskData> getAllForMasterScenario();
SubcontractedTaskData getSubcontratedTaskDataByOrderElement(
OrderElement orderElement) throws InstanceNotFoundException;
}

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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} <br />
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class TaskConverter implements IConverter<Task> {
@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<Task> getType() {
return Task.class;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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} <br />
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class TaskElementConverter implements IConverter<TaskElement> {
@Autowired
private ITaskElementDAO taskElementDAO;
@Override
public String asString(TaskElement entity) {
return entity.getId() + "";
}
@Override
public Class<TaskElement> 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);
}
}
}

View file

@ -75,7 +75,6 @@ public class AdvanceAssignmentPlanningController extends GenericForwardComposer
public void showWindow(IContextWithPlannerTask<TaskElement> 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) {

View file

@ -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<TaskElement> 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;
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -185,7 +185,6 @@ public class EditTaskController extends GenericForwardComposer {
planningState, messagesForUser);
showLimitingResourcesTab();
}
}
private void showSubcontractTab() {

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<SubcontractorComunication> getSubcontractorComunicationWithoutReviewed();
List<SubcontractorComunication> getSubcontractorAllComunications();
void setCurrentFilter(FilterComunicationEnum currentFilter);
FilterComunicationEnum getCurrentFilter();
String getOrderCode(SubcontractedTaskData subcontractedTaskData);
String getOrderName(SubcontractedTaskData subcontractedTaskData);
Order getOrder(OrderElement orderElement);
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <smontes@wirelessgalicia.com>
*/
@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<SubcontractorComunication> 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<SubcontractorComunicationValue> 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);
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<SubcontractorComunication> getSubcontractorAllComunications(){
List<SubcontractorComunication> list = subcontractorComunicationDAO.getAll();
forceLoadAssociatedData(list);
return list;
}
@Override
@Transactional
public List<SubcontractorComunication> getSubcontractorComunicationWithoutReviewed(){
List<SubcontractorComunication> list = subcontractorComunicationDAO.getAllNotReviewed();
forceLoadAssociatedData(list);
return list;
}
private void forceLoadAssociatedData(List<SubcontractorComunication> 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<SubcontractorComunicationValue> 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();
}
}

View file

@ -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<AdvanceMeasurementDTO> 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);

View file

@ -19,7 +19,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<?page title="${i18n:_('NavalPlan: Customer subcontracted projects communications')}"?>
<?page title="${i18n:_('LibrePlan: Customer subcontracted projects communications')}"?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/libreplan.css"?>
<?link rel="stylesheet" type="text/css" href="/common/css/libreplan_zk.css"?>

View file

@ -0,0 +1,79 @@
<!--
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 <http://www.gnu.org/licenses/>.
-->
<?page title="${i18n:_('LibrePlan: Incoming communications from subcontractors ')}"?>
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/common/layout/template.zul"?>
<?link rel="stylesheet" type="text/css" href="/common/css/libreplan.css"?>
<?link rel="stylesheet" type="text/css" href="/common/css/libreplan_zk.css"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<?taglib uri="/WEB-INF/tld/i18n.tld" prefix="i18n"?>
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<zk>
<window self="@{define(content)}"
apply="org.libreplan.web.subcontract.SubcontractorComunicationCRUDController"
title="${i18n:_('Subcontractor communications List')}">
<vbox id="messagesContainer" />
<div align="right">
<label class="subtitulo" value="${i18n:_('Show :')}" />
<listbox id="listFilter" mold="select" rows="1"
model="@{controller.filterItems}"
selectedItem="@{controller.currentFilterItem}"
itemRenderer="org.libreplan.web.common.EnumsListitemRenderer">
</listbox>
</div>
<separator bar="false" spacing="20px" orient="horizontal"/>
<grid id="listing"
model="@{controller.subcontractorComunications}"
rowRenderer="@{controller.subcontractorComunicationRenderer}"
mold="paging" pageSize="10" fixedLayout="true">
<columns>
<column label="${i18n:_('Communication Type')}" align="center" width="140px" sort="auto(lower(comunicationType))"/>
<column label="${i18n:_('Subcontrated task')}" align="center" sort="auto(lower(subcontractedTaskData.task.name))"/>
<column label="${i18n:_('Project name')}" width="150px" align="center" sort="auto(lower(subcontractedTaskData.task.orderElement.name))"/>
<column label="${i18n:_('Project Code')}" width="150px" align="center" sort="auto(lower(subcontractedTaskData.task.orderElement.code))"/>
<column label="${i18n:_('Company')}" width="150px" align="center" sort="auto(lower(subcontractedTaskData.externalCompany.name))"/>
<column label="${i18n:_('Communication Date')}" width="150px" align="center" sort="auto(lower(comunicationDate))"/>
<column label="${i18n:_('Value')}" width="200px" align="center" sort="auto(lower(lastSubcontratorComunicationValueDate))"/>
<column label="${i18n:_('Reviewed')}" width="80px" align="center"/>
<column label="${i18n:_('Operations')}" width="80px" align="center"/>
</columns>
</grid>
<popup id="pp">
<grid id="listingValues" width="300px" fixedLayout="true">
<columns>
<column label="${i18n:_('Date')}" width="150px" sort="auto(date)" sortDirection="descending"/>
<column label="${i18n:_('Progress')}" width="150px" sort="auto(progress)" sortDirection="descending"/>
</columns>
<rows>
<row self="@{each='value'}" value="@{value}">
<label value="@{value.date,converter='org.libreplan.web.common.typeconverters.DateConverter'}" />
<label value="@{value.progress}"/>
</row>
</rows>
</grid>
</popup>
</window>
</zk>

View file

@ -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<ExternalCompany>() {
@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<LocalDate, BigDecimal> 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<LocalDate, BigDecimal> 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<OrderLine>() {
@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;
}
}