diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java index c653ea8f4..689a6c488 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionType.java @@ -1,19 +1,20 @@ package org.navalplanner.business.resources.entities; +import java.util.Set; + import org.apache.commons.lang.builder.EqualsBuilder; import org.hibernate.validator.NotEmpty; -import org.navalplanner.business.resources.entities.ResourceEnum; import org.navalplanner.business.resources.services.CriterionTypeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; - /** * Base implementation of {@link ICriterionType}
+ * @author Diego Pino García */ @Component - public class CriterionType implements ICriterionType { +public class CriterionType implements ICriterionType { private Long id; @@ -36,6 +37,8 @@ import org.springframework.stereotype.Component; private ResourceEnum resource = ResourceEnum.getDefault(); + private Set criterions; + public CriterionType() { } @@ -44,13 +47,9 @@ import org.springframework.stereotype.Component; this.name = name; } - public CriterionType( - String name, - boolean allowHierarchy, - boolean allowSimultaneousCriterionsPerResource, - boolean allowAdding, - boolean allowEditing, - ResourceEnum resource) { + public CriterionType(String name, boolean allowHierarchy, + boolean allowSimultaneousCriterionsPerResource, + boolean allowAdding, boolean allowEditing, ResourceEnum resource) { this.allowHierarchy = allowHierarchy; this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource; @@ -61,13 +60,11 @@ import org.springframework.stereotype.Component; } public static CriterionType asCriterionType(ICriterionType criterionType) { - return new CriterionType( - criterionType.getName(), - criterionType.allowHierarchy(), - criterionType.allowSimultaneousCriterionsPerResource(), - criterionType.allowAdding(), - criterionType.allowEditing(), - CriterionType.getResource(criterionType)); + return new CriterionType(criterionType.getName(), criterionType + .allowHierarchy(), criterionType + .allowSimultaneousCriterionsPerResource(), criterionType + .allowAdding(), criterionType.allowEditing(), CriterionType + .getResource(criterionType)); } private static ResourceEnum getResource(ICriterionType criterionType) { @@ -89,6 +86,14 @@ import org.springframework.stereotype.Component; return name; } + public Set getCriterions() { + return criterions; + } + + public void setCriterions(Set criterions) { + this.criterions = criterions; + } + @Override public boolean allowHierarchy() { return allowHierarchy; @@ -119,11 +124,10 @@ import org.springframework.stereotype.Component; } public static Criterion createCriterion( - PredefinedCriterionTypes predefinedCriterionType, - String name) { + PredefinedCriterionTypes predefinedCriterionType, String name) { - CriterionType criterionType = CriterionType. - asCriterionType(predefinedCriterionType); + CriterionType criterionType = CriterionType + .asCriterionType(predefinedCriterionType); return Criterion.withNameAndType(name, criterionType); } @@ -169,9 +173,8 @@ import org.springframework.stereotype.Component; CriterionType criterionType = (CriterionType) o; - return new EqualsBuilder() - .append(criterionType.getName(), this.getName()) - .isEquals(); + return new EqualsBuilder().append(criterionType.getName(), + this.getName()).isEquals(); } @Override diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReport.java b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReport.java index 28a29c57b..cbce7c500 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReport.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReport.java @@ -1,6 +1,7 @@ package org.navalplanner.business.workreports.entities; import java.util.Date; +import java.util.HashSet; import java.util.Set; /** @@ -8,68 +9,78 @@ import java.util.Set; */ public class WorkReport { - private Long id; + private Long id; - @SuppressWarnings("unused") - private long version; + @SuppressWarnings("unused") + private long version; - Date date; + Date date; - String place; + String place; - WorkReportType workReportType; + String responsible; - Set workReportLines; + WorkReportType workReportType; - public WorkReport() { + Set workReportLines = new HashSet(); - } + public WorkReport() { - public WorkReport(Date date, String place, WorkReportType workReportType, - Set workReportLines) { - this.date = date; - this.place = place; - this.workReportType = workReportType; - this.workReportLines = workReportLines; - } + } - public Long getId() { - return id; - } + public WorkReport(Date date, String place, WorkReportType workReportType, + Set workReportLines) { + this.date = date; + this.place = place; + this.workReportType = workReportType; + this.workReportLines = workReportLines; + } - public long getVersion() { - return version; - } + public Long getId() { + return id; + } - public Date getDate() { - return date; - } + public long getVersion() { + return version; + } - public void setDate(Date date) { - this.date = date; - } + public Date getDate() { + return date; + } - public String getPlace() { - return place; - } + public void setDate(Date date) { + this.date = date; + } - public void setPlace(String place) { - this.place = place; - } + public String getPlace() { + return place; + } - public WorkReportType getWorkReportType() { - return workReportType; - } + public void setPlace(String place) { + this.place = place; + } - public void setWorkReportType(WorkReportType workReportType) { - this.workReportType = workReportType; - } + public String getResponsible() { + return responsible; + } - public Set getWorkReportLines() { - return workReportLines; - } + public void setResponsible(String responsible) { + this.responsible = responsible; + } - public void setWorkReportLines(Set workReportLines) { - this.workReportLines = workReportLines; - } + public WorkReportType getWorkReportType() { + return workReportType; + } + + public void setWorkReportType(WorkReportType workReportType) { + this.workReportType = workReportType; + } + + public Set getWorkReportLines() { + return workReportLines; + } + + public void setWorkReportLines(Set workReportLines) { + this.workReportLines = workReportLines; + } } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportLine.java b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportLine.java index eac3c71c5..899abb4b4 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportLine.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportLine.java @@ -1,5 +1,6 @@ package org.navalplanner.business.workreports.entities; +import java.util.HashSet; import java.util.Set; import org.navalplanner.business.orders.entities.OrderElement; @@ -25,7 +26,7 @@ public class WorkReportLine { WorkReport workReport; - Set criterions; + Set criterions = new HashSet(); public WorkReportLine() { diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportType.java b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportType.java index 15002faf8..3d188c82c 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportType.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/workreports/entities/WorkReportType.java @@ -9,31 +9,31 @@ import org.navalplanner.business.resources.entities.CriterionType; */ public class WorkReportType { - private Long id; + private Long id; - @SuppressWarnings("unused") - private long version; + @SuppressWarnings("unused") + private long version; - String name; + String name; - Set criterionTypes; + Set criterionTypes; - public WorkReportType() { + public WorkReportType() { - } + } - public WorkReportType(String name, Set criterionTypes) { - this.name = name; - this.criterionTypes = criterionTypes; - } + public WorkReportType(String name, Set criterionTypes) { + this.name = name; + this.criterionTypes = criterionTypes; + } - public Long getId() { - return id; - } + public Long getId() { + return id; + } - public long getVersion() { - return version; - } + public long getVersion() { + return version; + } public String getName() { return name; @@ -50,11 +50,4 @@ public class WorkReportType { public void setCriterionTypes(Set criterionTypes) { this.criterionTypes = criterionTypes; } - - public void forceLoadCriterionTypes() { - for (CriterionType criterionType : criterionTypes) { - criterionType.getName(); - } - } - } diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml index 31b6fd397..9a07cef14 100644 --- a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml +++ b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml @@ -62,6 +62,10 @@ org.navalplanner.business.resources.entities.ResourceEnum + + + + diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/workreports/entities/WorkReports.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/workreports/entities/WorkReports.hbm.xml index 6f6c4d009..5aef862b4 100644 --- a/navalplanner-business/src/main/resources/org/navalplanner/business/workreports/entities/WorkReports.hbm.xml +++ b/navalplanner-business/src/main/resources/org/navalplanner/business/workreports/entities/WorkReports.hbm.xml @@ -26,10 +26,11 @@ + - + diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/OnlyOneVisible.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/OnlyOneVisible.java index d5d26924a..fdc22db90 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/OnlyOneVisible.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/OnlyOneVisible.java @@ -20,7 +20,9 @@ public class OnlyOneVisible { public void showOnly(Component component) { for (Component c : components) { - c.setVisible(component != null && c.equals(component)); + if (c != null) { + c.setVisible(component != null && c.equals(component)); + } } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/converters/WorkReportTypeConverter.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/converters/WorkReportTypeConverter.java new file mode 100644 index 000000000..bf18e1dec --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/converters/WorkReportTypeConverter.java @@ -0,0 +1,65 @@ +package org.navalplanner.web.common.converters; + +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.CriterionType; +import org.navalplanner.business.workreports.daos.IWorkReportTypeDAO; +import org.navalplanner.business.workreports.entities.WorkReportType; +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; + +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class WorkReportTypeConverter implements Converter { + + @Autowired + private IWorkReportTypeDAO workReportTypeDAO; + + @Override + @Transactional(readOnly = true) + public WorkReportType asObject(String stringRepresentation) { + long id = Long.parseLong(stringRepresentation); + try { + WorkReportType workReportType = workReportTypeDAO.find(id); + forceLoadCriterionTypes(workReportType); + return workReportType; + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public String asString(WorkReportType entity) { + return entity.getId().toString(); + } + + @Override + public String asStringUngeneric(Object entity) { + return asString((WorkReportType) entity); + } + + @Override + public Class getType() { + return WorkReportType.class; + } + + /** + * Load @{link CriterionType} and its @{link Criterion} + * + * @param workReportType + */ + private void forceLoadCriterionTypes(WorkReportType workReportType) { + // Load CriterionType + for (CriterionType criterionType : workReportType.getCriterionTypes()) { + criterionType.getId(); + // Load Criterion + for (Criterion criterion : criterionType.getCriterions()) { + criterion.getId(); + } + } + } + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportCRUDControllerEntryPoints.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportCRUDControllerEntryPoints.java new file mode 100644 index 000000000..5b458fd41 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportCRUDControllerEntryPoints.java @@ -0,0 +1,13 @@ +package org.navalplanner.web.workreports; + +import org.navalplanner.business.workreports.entities.WorkReportType; +import org.navalplanner.web.common.entrypoints.EntryPoint; +import org.navalplanner.web.common.entrypoints.EntryPoints; + +@EntryPoints(page = "/workreports/workReport.zul", registerAs = "workReportCRUD") +public interface IWorkReportCRUDControllerEntryPoints { + + @EntryPoint("edit") + public abstract void goToCreateForm(WorkReportType workReportType); + +} \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportModel.java new file mode 100644 index 000000000..5a30d4bc1 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportModel.java @@ -0,0 +1,72 @@ +package org.navalplanner.web.workreports; + +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.business.resources.entities.Worker; +import org.navalplanner.business.workreports.entities.WorkReport; +import org.navalplanner.business.workreports.entities.WorkReportType; + +/** + * Contract for {@link WorkRerportType} + * + * @author Diego Pino García + */ +public interface IWorkReportModel { + + /** + * Gets the current {@link WorkReport}. + * + * @return A {@link WorkReport} + */ + WorkReport getWorkReport(); + + /** + * Stores the current {@link WorkReport}. + * + * @throws ValidationException + * If validation fails + */ + void save() throws ValidationException; + + /** + * Makes some operations needed before create a new {@link WorkReport}. + */ + void prepareForCreate(WorkReportType workReportType); + + /** + * Makes some operations needed before edit a {@link WorkReport}. + * + * @param workReport + * The object to be edited + */ + void prepareEditFor(WorkReport workReport); + + /** + * Finds an @{link OrdrElement} by code + * + * @param code + * @return + */ + OrderElement findOrderElement(String code); + + /** + * Find a @{link Worker} by nif + * + * @param nif + * @return + * @throws InstanceNotFoundException + */ + Worker findWorker(String nif) throws InstanceNotFoundException; + + /** + * Converts @{link Resource} to @{link Worker} + * + * @param resource + * @return + * @throws InstanceNotFoundException + */ + Worker asWorker(Resource resource) throws InstanceNotFoundException; + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeCRUDControllerEntryPoints.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeCRUDControllerEntryPoints.java new file mode 100644 index 000000000..b4671e263 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeCRUDControllerEntryPoints.java @@ -0,0 +1,12 @@ +package org.navalplanner.web.workreports; + +import org.navalplanner.web.common.entrypoints.EntryPoint; +import org.navalplanner.web.common.entrypoints.EntryPoints; + +@EntryPoints(page = "/workreports/workReportTypes.zul", registerAs = "workReportTypeCRUD") +public interface IWorkReportTypeCRUDControllerEntryPoints { + + @EntryPoint("list") + public abstract void goToList(); + +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeModel.java index 54aff666d..3bf9fcf40 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/IWorkReportTypeModel.java @@ -55,7 +55,7 @@ public interface IWorkReportTypeModel { * @param workReportType * The object to be edited */ - void prepareEditFor(WorkReportType workReportType); + void prepareForEdit(WorkReportType workReportType); /** * Makes some operations needed before remove a {@link WorkReportType}. diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportCRUDController.java new file mode 100644 index 000000000..68a4ac619 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportCRUDController.java @@ -0,0 +1,444 @@ +package org.navalplanner.web.workreports; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.business.orders.entities.Order; +import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.CriterionType; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.business.resources.entities.Worker; +import org.navalplanner.business.workreports.entities.WorkReport; +import org.navalplanner.business.workreports.entities.WorkReportLine; +import org.navalplanner.business.workreports.entities.WorkReportType; +import org.navalplanner.web.common.IMessagesForUser; +import org.navalplanner.web.common.Level; +import org.navalplanner.web.common.MessagesForUser; +import org.navalplanner.web.common.OnlyOneVisible; +import org.navalplanner.web.common.Util; +import org.navalplanner.web.common.entrypoints.IURLHandlerRegistry; +import org.navalplanner.web.common.entrypoints.URLHandler; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.WrongValueException; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.Column; +import org.zkoss.zul.Columns; +import org.zkoss.zul.Grid; +import org.zkoss.zul.Intbox; +import org.zkoss.zul.Listbox; +import org.zkoss.zul.Listitem; +import org.zkoss.zul.Row; +import org.zkoss.zul.RowRenderer; +import org.zkoss.zul.Rows; +import org.zkoss.zul.Textbox; +import org.zkoss.zul.api.Window; + +/** + * Controller for CRUD actions over a {@link WorkReport} + * + * @author Diego Pino García + */ +public class WorkReportCRUDController extends GenericForwardComposer implements + IWorkReportCRUDControllerEntryPoints { + + private Window createWindow; + + private IWorkReportModel workReportModel; + + private IURLHandlerRegistry URLHandlerRegistry; + + private OnlyOneVisible visibility; + + private IMessagesForUser messagesForUser; + + private Component messagesContainer; + + private IWorkReportTypeCRUDControllerEntryPoints workReportTypeCRUD; + + private WorkReportListRenderer workReportListRenderer = new WorkReportListRenderer(); + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + messagesForUser = new MessagesForUser(messagesContainer); + comp.setVariable("controller", this, true); + final URLHandler handler = URLHandlerRegistry + .getRedirectorFor(IWorkReportCRUDControllerEntryPoints.class); + handler.registerListener(this, page); + // Shows a blank page until createWindow is completely rendered + getVisibility().showOnly(null); + } + + private OnlyOneVisible getVisibility() { + return (visibility == null) ? new OnlyOneVisible(createWindow) + : visibility; + } + + public void save() { + try { + workReportModel.save(); + messagesForUser.showMessage(Level.ERROR, + "Parte de traballo gardado"); + } catch (ValidationException e) { + messagesForUser.showInvalidValues(e); + } + } + + public void cancel() { + System.out.println("### Cancel"); + workReportTypeCRUD.goToList(); + } + + public void goToCreateForm(WorkReportType workReportType) { + workReportModel.prepareForCreate(workReportType); + appendCriterionTypesToColumns(getCriterionTypes()); + getVisibility().showOnly(createWindow); + Util.reloadBindings(createWindow); + } + + private Set getCriterionTypes() { + return getWorkReportType().getCriterionTypes(); + } + + private WorkReportType getWorkReportType() { + return getWorkReport().getWorkReportType(); + } + + public WorkReport getWorkReport() { + return workReportModel.getWorkReport(); + } + + /** + * Appends a set of {@link CriterionType} to columns header + */ + private void appendCriterionTypesToColumns(Set criterionTypes) { + Grid grid = (Grid) createWindow.getFellow("listWorkReportLines"); + for (CriterionType criterionType : criterionTypes) { + appendCriterionTypeToColumns(criterionType, grid.getColumns()); + } + } + + /** + * Appends a new {@link CriterionType} to columns header + */ + private void appendCriterionTypeToColumns(CriterionType criterionType, + Columns columns) { + Column column = new Column(criterionType.getName()); + column.setParent(columns); + } + + /** + * Adds a new {@link WorkReportLine} to the list of rows + * + * @param rows + */ + public void addWorkReportLine(Rows rows) { + WorkReportLine workReportLine = new WorkReportLine(); + getWorkReportLines().add(workReportLine); + rows.appendChild(createRow(workReportLine)); + } + + public Set getWorkReportLines() { + return (getWorkReport() != null) ? getWorkReport().getWorkReportLines() + : new HashSet(); + } + + /** + * Returns a new row bound to to a {@link WorkReportLine} + * + * A row consists of a several textboxes plus several listboxes, one for + * every {@link CriterionType} associated with current @{link WorkReport} + * + * @param workReportLine + * @return + */ + private Row createRow(WorkReportLine workReportLine) { + Row row = new Row(); + + // Bind workReportLine to row + row.setValue(workReportLine); + + appendTextboxResource(row); + appendTextboxOrder(row); + appendIntboxNumHours(row); + + for (CriterionType criterionType : getCriterionTypes()) { + appendListboxCriterionType(criterionType, row); + } + + return row; + } + + /** + * Append a Textbox @{link Resource} to row + * + * @param row + */ + private void appendTextboxResource(Row row) { + Textbox txtResource = new Textbox(); + bindTextboxResource(txtResource, (WorkReportLine) row.getValue()); + row.appendChild(txtResource); + } + + /** + * Binds Textbox @{link Resource} to a {@link WorkReportLine} + * {@link Resource} + * + * @param txtResource + * @param workReportLine + */ + private void bindTextboxResource(final Textbox txtResource, + final WorkReportLine workReportLine) { + Util.bind(txtResource, new Util.Getter() { + + @Override + public String get() { + return (workReportLine.getResource() != null) ? ((Worker) workReportLine + .getResource()).getNif() + : ""; + } + + }, new Util.Setter() { + + @Override + public void set(String value) { + if (value.length() > 0) { + Worker worker; + try { + worker = workReportModel.findWorker(value); + } catch (InstanceNotFoundException e) { + throw new WrongValueException(txtResource, + "Worker not found"); + } + workReportLine.setResource(worker); + } + } + }); + } + + /** + * Append a Textbox @{link Order} to row + * + * @param row + */ + private void appendTextboxOrder(Row row) { + Textbox txtOrder = new Textbox(); + bindTextboxOrder(txtOrder, (WorkReportLine) row.getValue()); + row.appendChild(txtOrder); + } + + /** + * Binds Textbox @{link Order} to a {@link WorkReportLine} {@link Order} + * + * @param txtOrder + * @param workReportLine + */ + private void bindTextboxOrder(final Textbox txtOrder, + final WorkReportLine workReportLine) { + Util.bind(txtOrder, new Util.Getter() { + + @Override + public String get() { + return (workReportLine.getOrderElement() != null) ? workReportLine + .getOrderElement().getCode() + : ""; + } + + }, new Util.Setter() { + + @Override + public void set(String value) { + if (value.length() > 0) { + OrderElement orderElement = workReportModel + .findOrderElement(value); + if (orderElement == null) { + throw new WrongValueException(txtOrder, + "OrderElement not found"); + } + workReportLine.setOrderElement(orderElement); + } + } + }); + } + + /** + * Append a Intbox numHours to row + * + * @param row + */ + private void appendIntboxNumHours(Row row) { + Intbox intNumHours = new Intbox(); + bindIntboxNumHours(intNumHours, (WorkReportLine) row.getValue()); + row.appendChild(intNumHours); + } + + /** + * Binds Intbox numHours to a {@link WorkReportLine} numHours + * + * @param intNumHours + * @param workReportLine + */ + private void bindIntboxNumHours(final Intbox intNumHours, + final WorkReportLine workReportLine) { + Util.bind(intNumHours, new Util.Getter() { + + @Override + public Integer get() { + return workReportLine.getNumHours(); + } + + }, new Util.Setter() { + + @Override + public void set(Integer value) { + workReportLine.setNumHours(value); + } + }); + } + + /** + * Appends a {@link CriterionType} listbox to row + * + * @param criterionType + * @param row + */ + private void appendListboxCriterionType(final CriterionType criterionType, + Row row) { + WorkReportLine workReportLine = (WorkReportLine) row.getValue(); + Listbox listBox = createListboxCriterionType(criterionType, + getSelectedCriterion(workReportLine, criterionType)); + bindListboxCriterionType(criterionType, listBox, workReportLine); + row.appendChild(listBox); + } + + /** + * Determines which {@link Criterion} of @{link CriterionType} is selected + * in a @{link WorkReportLine} + * + * Notice that in a list of {@link Criterion} belonging to a @{link + * WorkReportLine}, only one {@link Criterion} for each + * {@link CriterionType} is possible + * + * @param workReportLine + * @param criterionType + */ + private Criterion getSelectedCriterion(WorkReportLine workReportLine, + CriterionType criterionType) { + for (Criterion criterion : workReportLine.getCriterions()) { + if (criterionType.equals(criterion.getType())) { + return criterion; + } + } + + return null; + } + + /** + * Create a listbox of {@link Criterion} for a {@link CriterionType} + * + * @param criterionType + * @param workReportLine + * needed to determine which {@link Criterion} should be set to + * selected + * @return + */ + private Listbox createListboxCriterionType(CriterionType criterionType, + Criterion selectedCriterion) { + Listbox listBox = new Listbox(); + listBox.setRows(1); + listBox.setMold("select"); + + // Add empty option to list + List criterions = new ArrayList(criterionType + .getCriterions()); + criterions.add(0, new Criterion(" ", criterionType)); + + // Adds a new item to list for each criterion + for (Criterion criterion : criterions) { + Listitem listItem = new Listitem(); + listItem.setLabel(criterion.getName()); + listItem.setValue(criterion); + listItem.setParent(listBox); + + if (criterion.equals(selectedCriterion)) { + listBox.setSelectedItem(listItem); + } + } + + return listBox; + } + + /** + * Updates the list of {@link Criterion} of a {@link WorkReportLine} when a + * new @{link Criterion} is selected + * + * @param criterionType + * needed to determine which {@link Criterion} inside the list + * should be updated + * @param listBox + * @param workReportLine + */ + private void bindListboxCriterionType(final CriterionType criterionType, + final Listbox listBox, final WorkReportLine workReportLine) { + listBox.addEventListener("onSelect", new EventListener() { + + @Override + public void onEvent(Event arg0) throws Exception { + Listitem listItem = listBox.getSelectedItem(); + + // There only can be one criterion for each criterion type + for (Criterion criterion : workReportLine.getCriterions()) { + if (criterionType.equals(criterion.getType())) { + workReportLine.getCriterions().remove(criterion); + } + } + workReportLine.getCriterions().add( + (Criterion) listItem.getValue()); + } + }); + } + + public WorkReportListRenderer getRenderer() { + return workReportListRenderer; + } + + /** + * RowRenderer for a @{WorkReportLine} element + * + * @author Diego Pino García + * + */ + public class WorkReportListRenderer implements RowRenderer { + + @Override + public void render(Row row, Object data) throws Exception { + WorkReportLine workReportLine = (WorkReportLine) data; + + // Convert Resource to Worker + if (workReportLine.getResource() instanceof Resource) { + workReportLine.setResource(workReportModel + .asWorker(workReportLine.getResource())); + } + + row.setValue(workReportLine); + + // Create textboxes + appendTextboxResource(row); + appendTextboxOrder(row); + appendIntboxNumHours(row); + + // Get criterion types for each row and append to it + // CriterionTypes + for (CriterionType criterionType : getCriterionTypes()) { + appendListboxCriterionType(criterionType, row); + } + } + } +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportModel.java new file mode 100644 index 000000000..bd10d9ab5 --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportModel.java @@ -0,0 +1,154 @@ +package org.navalplanner.web.workreports; + +import org.apache.commons.lang.Validate; +import org.hibernate.validator.ClassValidator; +import org.hibernate.validator.InvalidValue; +import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.business.orders.daos.OrderElementDao; +import org.navalplanner.business.orders.entities.OrderElement; +import org.navalplanner.business.resources.daos.impl.WorkerDaoHibernate; +import org.navalplanner.business.resources.entities.Criterion; +import org.navalplanner.business.resources.entities.CriterionType; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.business.resources.entities.Worker; +import org.navalplanner.business.workreports.daos.WorkReportDAO; +import org.navalplanner.business.workreports.entities.WorkReport; +import org.navalplanner.business.workreports.entities.WorkReportLine; +import org.navalplanner.business.workreports.entities.WorkReportType; +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; + +/** + * Model for UI operations related to {@link WorkReport}. + * + * @author Diego Pino García + */ +@Service +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class WorkReportModel implements IWorkReportModel { + + private WorkReport workReport; + + private ClassValidator workReportValidator = new ClassValidator( + WorkReport.class); + + @Autowired + private WorkReportDAO workReportDAO; + + @Autowired + private OrderElementDao orderElementDAO; + + @Autowired + private WorkerDaoHibernate workerDAO; + + private boolean editing = false; + + @Override + public WorkReport getWorkReport() { + return workReport; + } + + @Override + @Transactional(readOnly = true) + public void prepareForCreate(WorkReportType workReportType) { + editing = false; + workReport = new WorkReport(); + workReport.setWorkReportType(workReportType); + } + + @Override + @Transactional(readOnly = true) + public void prepareEditFor(WorkReport workReport) { + editing = true; + Validate.notNull(workReport); + workReport = getFromDB(workReport); + } + + @Transactional(readOnly = true) + private WorkReport getFromDB(WorkReport workReport) { + return getFromDB(workReport.getId()); + } + + @Transactional(readOnly = true) + private WorkReport getFromDB(Long id) { + try { + WorkReport workReport = workReportDAO.find(id); + forceLoadEntities(workReport); + return workReport; + } catch (InstanceNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Load entities that will be needed in the conversation + * + * @param workReport + */ + private void forceLoadEntities(WorkReport workReport) { + // Load WorkReportType + workReport.getWorkReportType().getName(); + + // Load CriterionTypes + for (CriterionType criterionType : workReport.getWorkReportType() + .getCriterionTypes()) { + criterionType.getId(); + // Load Criterions + for (Criterion criterion : criterionType.getCriterions()) { + criterion.getId(); + } + } + + // Load WorkReportLines + for (WorkReportLine workReportLine : workReport.getWorkReportLines()) { + workReportLine.getId(); + workReportLine.getResource().getId(); + workReportLine.getOrderElement().getId(); + + // Load Criterions + for (Criterion criterion : workReportLine.getCriterions()) { + criterion.getId(); + } + } + } + + @Override + @Transactional + public void save() throws ValidationException { + InvalidValue[] invalidValues = workReportValidator + .getInvalidValues(workReport); + if (invalidValues.length > 0) { + throw new ValidationException(invalidValues); + } + workReportDAO.save(workReport); + } + + @Override + @Transactional + public OrderElement findOrderElement(String orderCode) { + String[] parts = orderCode.split("-"); + OrderElement parent = orderElementDAO.findByCode(parts[0]); + for (int i = 1; i < parts.length && parent != null; i++) { + OrderElement child = orderElementDAO.findByCode(parent, parts[i]); + parent = child; + } + + return parent; + } + + @Override + @Transactional + public Worker findWorker(String nif) throws InstanceNotFoundException { + return workerDAO.findUniqueByNif(nif); + } + + @Override + @Transactional + public Worker asWorker(Resource resource) throws InstanceNotFoundException { + return workerDAO.find(resource.getId()); + } +} diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeCRUDController.java index 2f9868364..20d4e972b 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeCRUDController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeCRUDController.java @@ -13,6 +13,8 @@ import org.navalplanner.web.common.MessagesForUser; import org.navalplanner.web.common.OnlyOneVisible; import org.navalplanner.web.common.Util; import org.navalplanner.web.common.components.TwoWaySelector; +import org.navalplanner.web.common.entrypoints.IURLHandlerRegistry; +import org.navalplanner.web.common.entrypoints.URLHandler; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.api.Window; @@ -22,7 +24,8 @@ import org.zkoss.zul.api.Window; * * @author Manuel Rego Casasnovas */ -public class WorkReportTypeCRUDController extends GenericForwardComposer { +public class WorkReportTypeCRUDController extends GenericForwardComposer + implements IWorkReportTypeCRUDControllerEntryPoints { private Window listWindow; @@ -42,6 +45,10 @@ public class WorkReportTypeCRUDController extends GenericForwardComposer { private Component messagesContainer; + private IWorkReportCRUDControllerEntryPoints workReportCRUD; + + private IURLHandlerRegistry URLHandlerRegistry; + public List getWorkReportTypes() { return workReportTypeModel.getWorkReportTypes(); } @@ -79,11 +86,14 @@ public class WorkReportTypeCRUDController extends GenericForwardComposer { super.doAfterCompose(comp); messagesForUser = new MessagesForUser(messagesContainer); comp.setVariable("controller", this, true); + final URLHandler handler = URLHandlerRegistry + .getRedirectorFor(IWorkReportTypeCRUDControllerEntryPoints.class); + handler.registerListener(this, page); getVisibility().showOnly(listWindow); } public void cancel() { - goToList(); + // TODO: Check if hoursgroup has criterions } public void goToList() { @@ -92,7 +102,7 @@ public class WorkReportTypeCRUDController extends GenericForwardComposer { } public void goToEditForm(WorkReportType workReportType) { - workReportTypeModel.prepareEditFor(workReportType); + workReportTypeModel.prepareForEdit(workReportType); getVisibility().showOnly(editWindow); Util.reloadBindings(editWindow); } @@ -178,4 +188,8 @@ public class WorkReportTypeCRUDController extends GenericForwardComposer { return visibility; } + public void goToEditNewWorkReportForm(WorkReportType workReportType) { + workReportCRUD.goToCreateForm(workReportType); + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeModel.java index 7fd37abb2..c58ff6def 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/workreports/WorkReportTypeModel.java @@ -68,12 +68,11 @@ public class WorkReportTypeModel implements IWorkReportTypeModel { @Override @Transactional(readOnly = true) - public void prepareEditFor(WorkReportType workReportType) { + public void prepareForEdit(WorkReportType workReportType) { editing = true; Validate.notNull(workReportType); this.workReportType = getFromDB(workReportType); - this.workReportType.forceLoadCriterionTypes(); } @Override diff --git a/navalplanner-webapp/src/main/webapp/workreports/_editWorkReport.zul b/navalplanner-webapp/src/main/webapp/workreports/_editWorkReport.zul new file mode 100644 index 000000000..b8578a9d2 --- /dev/null +++ b/navalplanner-webapp/src/main/webapp/workreports/_editWorkReport.zul @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + @@ -22,4 +27,4 @@ - \ No newline at end of file + diff --git a/navalplanner-webapp/src/main/webapp/workreports/workReport.zul b/navalplanner-webapp/src/main/webapp/workreports/workReport.zul new file mode 100644 index 000000000..e76d14859 --- /dev/null +++ b/navalplanner-webapp/src/main/webapp/workreports/workReport.zul @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + +