From 10719470a31517150a9a7789e6b8002cfbe43fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Javier=20Mart=C3=ADnez?= Date: Tue, 23 Apr 2024 09:48:40 +0200 Subject: [PATCH] Feature/estimated cost (#172) * Change total estimated cost variable name and create field estimated cost --- pom.xml | 2 +- .../autentia/tnt/businessobject/Project.java | 203 +++++++++--------- .../tnt/dao/search/ProjectSearch.java | 54 ++++- .../tnt/businessobject/config/Project.hbm.xml | 2 + .../autentia/tnt/bean/admin/ProjectBean.java | 33 +++ .../tnt/resources/messages_en.properties | 9 +- .../tnt/resources/messages_es.properties | 11 +- .../tnt/resources/messages_pt.properties | 11 +- .../main/webapp/pages/admin/editProject.jsp | 72 ++++--- 9 files changed, 257 insertions(+), 140 deletions(-) diff --git a/pom.xml b/pom.xml index 57455364..117a6f91 100644 --- a/pom.xml +++ b/pom.xml @@ -63,7 +63,7 @@ 8.0.32 - 1.26.0 + 1.39.0 https://maven.pkg.github.com/autentia/tntconcept-api diff --git a/tntconcept-core/src/main/java/com/autentia/tnt/businessobject/Project.java b/tntconcept-core/src/main/java/com/autentia/tnt/businessobject/Project.java index 5e7710f6..165d9522 100755 --- a/tntconcept-core/src/main/java/com/autentia/tnt/businessobject/Project.java +++ b/tntconcept-core/src/main/java/com/autentia/tnt/businessobject/Project.java @@ -38,13 +38,13 @@ * @author alumno * */ -public class Project implements Serializable, ITransferObject +public class Project implements Serializable, ITransferObject { /** Serial version field */ private static final long serialVersionUID = -1L; private static final Log log = LogFactory.getLog(Project.class); - - + + /** * Test if a project is finished as of now * @return true if project is finished @@ -52,8 +52,8 @@ public class Project implements Serializable, ITransferObject public boolean isFinished(){ return !open; } - - + + /* project - generated by stajanov (do not edit/delete) */ @@ -63,190 +63,192 @@ public boolean isFinished(){ // Fields - - - + + + private Integer id; - - + + private Date startDate; - - + + private Date endDate; - - + + private Boolean open; - - + + private String name; - - + + private String description; - - + + private Boolean billable; - - + + private Integer ownerId; - - + + private Integer departmentId; - - + + private Date insertDate; - - + + private Date updateDate; - - - + + + private Organization client; private Offer offer; - - + + private Set roles = new HashSet(); - - + + private Set costs = new HashSet(); - + + private BigDecimal estimatedCost; + private User user; - + // Setters and getters - - - + + + public Integer getId() { return id; } - + public void setId( Integer id ) { this.id = id; } - - - + + + public Date getStartDate() { return startDate; } public void setStartDate( Date startDate ) { this.startDate = startDate; } - - - + + + public Date getEndDate() { return endDate; } public void setEndDate( Date endDate ) { this.endDate = endDate; } - - - + + + public Boolean getOpen() { return open; } public void setOpen( Boolean open ) { this.open = open; } - - - + + + public String getName() { return name; } public void setName( String name ) { this.name = name; } - - - + + + public String getDescription() { return description; } public void setDescription( String description ) { this.description = description; } - - - + + + public Boolean getBillable() { return billable; } public void setBillable( Boolean billable ) { this.billable = billable; } - - - + + + public Integer getOwnerId() { return ownerId; } public void setOwnerId( Integer ownerId ) { this.ownerId = ownerId; } - - - + + + public Integer getDepartmentId() { return departmentId; } public void setDepartmentId( Integer departmentId ) { this.departmentId = departmentId; } - - - + + + public Date getInsertDate() { return insertDate; } private void setInsertDate( Date insertDate ) { this.insertDate = insertDate; } - - - + + + public Date getUpdateDate() { return updateDate; } private void setUpdateDate( Date updateDate ) { this.updateDate = updateDate; } - - - + + + public Organization getClient() { return client; } public void setClient( Organization client ) { this.client = client; } - - + + public Set getRoles() { return roles; } public void setRoles( Set roles ) { this.roles = roles; } - - + + public Set getCosts() { return costs; } @@ -254,6 +256,11 @@ public void setCosts( Set costs ) { this.costs = costs; } + + public BigDecimal getEstimatedCost() { return estimatedCost; } + + public void setEstimatedCost(BigDecimal estimatedCost) { this.estimatedCost = estimatedCost; } + public Offer getOffer() { return offer; } @@ -266,28 +273,28 @@ public void setOffer(Offer offer) { public boolean equals( Object that ) { try { - if (that == null) + if (that == null) return false; - else + else return this.getId().equals( ((Project)that).getId() ); } catch (Exception e) { return false; } } - + @Override public int hashCode() { if(this.getId()==null) return super.hashCode(); - else + else return this.getId().intValue(); } /* project - generated by stajanov (do not edit/delete) */ - + public BigDecimal getTotalCost(){ BigDecimal ret = new BigDecimal(0); - + if( getCosts()!=null ){ for( ProjectCost cost : getCosts() ){ BigDecimal c = cost.getCost(); @@ -305,7 +312,7 @@ public BigDecimal getTotalCost(){ } } } - + return ret; } @@ -313,11 +320,11 @@ public List getOwnersId() { // TODO Auto-generated method stub return null; } - + /** * @return Return the total worked time in minutes */ - + public long getWorkedHours(){ long total = 0; if (this.getRoles()!=null){ @@ -329,9 +336,9 @@ public long getWorkedHours(){ } } } - return total; + return total; } - + public long getExpectedHours(){ long total = 0; if (this.getRoles()!=null){ @@ -339,13 +346,13 @@ public long getExpectedHours(){ total += role.getExpectedHours(); } } - return total; + return total; } - + public double getPercentageWorked(){ double expected = this.getExpectedHours(); double worked = (double)this.getWorkedHours()/60; - + if (worked == 0){ return 0; } else if (expected == 0){ @@ -354,11 +361,11 @@ public double getPercentageWorked(){ return worked/expected; } } - + public double getPercentageCosts(){ double finalcost = this.getCostPerProject().doubleValue(); double expected = this.getTotalCost().doubleValue(); - + if (finalcost == 0){ return 0; } else if (expected == 0){ @@ -367,20 +374,20 @@ public double getPercentageCosts(){ return finalcost/expected; } } - + public BigDecimal getCostPerProject(){ BigDecimal total = new BigDecimal(0); Set roles = this.getRoles(); - + if (roles != null){ for (ProjectRole role : roles){ Set activities = role.getActivities(); if (activities != null){ for (Activity activity : activities){ - BigDecimal converse = new BigDecimal(activity.getUser().getCostPerHour()); + BigDecimal converse = new BigDecimal(activity.getUser().getCostPerHour()); BigDecimal div = new BigDecimal( activity.getDuration()); - BigDecimal ret = div.multiply(converse); + BigDecimal ret = div.multiply(converse); total = total.add(ret.divide(new BigDecimal(60),2,BigDecimal.ROUND_HALF_UP));// += activity.getDuration() * activity.getUser().getCostPerHour()/ 60 ; } } diff --git a/tntconcept-core/src/main/java/com/autentia/tnt/dao/search/ProjectSearch.java b/tntconcept-core/src/main/java/com/autentia/tnt/dao/search/ProjectSearch.java index 17f9955f..3324571f 100755 --- a/tntconcept-core/src/main/java/com/autentia/tnt/dao/search/ProjectSearch.java +++ b/tntconcept-core/src/main/java/com/autentia/tnt/dao/search/ProjectSearch.java @@ -240,6 +240,16 @@ public String getHQL() { } } + + if( isEstimatedCostSet() ){ + ret.append( (ret.length()==0) ? "WHERE " : " AND " ); + if( getEstimatedCost()==null ){ + ret.append( "estimated cost is NULL" ); + } else { + ret.append( "estimated cost = :arg"+(iArgNum++) ); + } + } + if( isRolesSet() ){ ret.append( (ret.length()==0) ? "WHERE " : " AND " ); ret.append( "roles.id IN (:arg"+(iArgNum++)+")" ); @@ -340,6 +350,11 @@ public Object[] getArguments(){ if( isOfferSet() && getOffer()!=null ){ ret.add( offer ); } + + + if( isEstimatedCostSet() && getEstimatedCost()!=null ){ + ret.add( estimatedCost ); + } if( isRolesSet() ){ @@ -418,7 +433,8 @@ public void reset(){ unsetClient(); unsetOffer(); - + + unsetEstimatedCost(); unsetRoles(); @@ -565,8 +581,12 @@ public String toString() { ret.append( ")" ); } - - + + if( isEstimatedCostSet() ){ + ret.append( "(estimated cost" ); + ret.append( "="+estimatedCost ); + ret.append( ")" ); + } if( isRolesSet() ){ @@ -857,8 +877,25 @@ public void setOffer( Offer offer ){ public void unsetOffer(){ this.offerSet = false; } - - + + + + public boolean isEstimatedCostSet(){ + return estimatedCostSet; + } + public BigDecimal getEstimatedCost(){ + return estimatedCost; + } + public void setEstimatedCost( BigDecimal estimatedCost ){ + this.estimatedCost = estimatedCost; + this.estimatedCostSet = true; + } + public void unsetEstimatedCost(){ + this.estimatedCostSet = false; + } + + + public boolean isRolesSet(){ return rolesSet; } @@ -957,7 +994,10 @@ public void unsetCosts(){ private boolean offerSet; private Offer offer; - + + + private boolean estimatedCostSet; + private BigDecimal estimatedCost; private boolean rolesSet; @@ -971,7 +1011,7 @@ public void unsetCosts(){ // Returns if there are a search condition active public boolean isSearchActive() { - return customIsSearchActive()||startStartDateSet||endStartDateSet||startEndDateSet||endEndDateSet||openSet||nameSet||descriptionSet||billableSet||ownerIdSet||departmentIdSet||startInsertDateSet||endInsertDateSet||startUpdateDateSet||endUpdateDateSet||clientSet||rolesSet||costsSet||offerSet; + return customIsSearchActive()||startStartDateSet||endStartDateSet||startEndDateSet||endEndDateSet||openSet||nameSet||descriptionSet||billableSet||ownerIdSet||departmentIdSet||startInsertDateSet||endInsertDateSet||startUpdateDateSet||endUpdateDateSet||clientSet||rolesSet||costsSet||offerSet||estimatedCostSet; } diff --git a/tntconcept-core/src/main/resources/com/autentia/tnt/businessobject/config/Project.hbm.xml b/tntconcept-core/src/main/resources/com/autentia/tnt/businessobject/config/Project.hbm.xml index 3717b044..d5e0756e 100755 --- a/tntconcept-core/src/main/resources/com/autentia/tnt/businessobject/config/Project.hbm.xml +++ b/tntconcept-core/src/main/resources/com/autentia/tnt/businessobject/config/Project.hbm.xml @@ -45,5 +45,7 @@ + + diff --git a/tntconcept-web/src/main/java/com/autentia/tnt/bean/admin/ProjectBean.java b/tntconcept-web/src/main/java/com/autentia/tnt/bean/admin/ProjectBean.java index 3d2aae2d..905d0d21 100755 --- a/tntconcept-web/src/main/java/com/autentia/tnt/bean/admin/ProjectBean.java +++ b/tntconcept-web/src/main/java/com/autentia/tnt/bean/admin/ProjectBean.java @@ -60,6 +60,7 @@ public BigDecimal getTotalCost() { return project.getTotalCost(); } + /** * Go to edit page * @@ -871,6 +872,28 @@ public void setSearchClientValid(boolean val) { } } + public BigDecimal getSearchEstimatedCost() { + return search.getEstimatedCost(); + } + + public void setSearchEstimatedCost(BigDecimal val) { + if (search.isEstimatedCostSet()) { + search.setEstimatedCost(val); + } + } + + public boolean isSearchEstimatedCostValid() { + return search.isEstimatedCostSet(); + } + + public void setSearchEstimatedCostValid(boolean val) { + if (val) { + search.setEstimatedCost(search.getEstimatedCost()); + } else { + search.unsetEstimatedCost(); + } + } + public List getSearchRoles() { return search.getRoles(); @@ -1041,6 +1064,15 @@ public void setClient(Organization client) { } } + public BigDecimal getEstimatedCost() { + return project.getEstimatedCost(); + } + + public void setEstimatedCost(BigDecimal estimatedCost) { + project.setEstimatedCost(estimatedCost); + } + + public Set getRoles() { return project.getRoles(); @@ -1124,6 +1156,7 @@ public String getCostPerProject() { return totalCost; } + public HtmlInputText getOfferNumberInput() { return offerNumberInput; } diff --git a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_en.properties b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_en.properties index 9293e03c..86e030c5 100755 --- a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_en.properties +++ b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_en.properties @@ -69,6 +69,12 @@ error.disabledLogs=Logs disabled error.notAuthorized=Unauthorized access error.newPasswordEqualsOldPassword=New password can not be equals than current password +############################################################################################ +# Convert error messages +# +javax.faces.converter.BigDecimalConverter.DECIMAL=''{0}'' must be a signed decimal number. + + ############################################################################################ # Random password generation # @@ -413,6 +419,7 @@ project.updateDate=Insert update project.client=Organization project.roles=Roles project.costs=Costs +project.estimatedCost=Estimated Cost project.workedHours=Worked Hours project.costPerHour=Cost per Hour project.costPerProject=Cost per Project @@ -428,7 +435,7 @@ searchProject.title=Find Projects detailProject.location=Administration - Detail Project detailProject.title=Detail Project # project - generated by stajanov (do not edit/delete) -editProject.totalCost=Total estimated cost +editProject.totalCost=Auto-calculated Cost # idea - generated by stajanov (do not edit/delete) diff --git a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_es.properties b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_es.properties index 6c6eb461..77bc8a4f 100755 --- a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_es.properties +++ b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_es.properties @@ -70,6 +70,12 @@ error.enabledLogs=Trazas habilitadas error.disabledLogs=Trazas deshabilitadas error.notAuthorized=Acceso no autorizado. +############################################################################################ +# Converter error messages +# +javax.faces.converter.BigDecimalConverter.DECIMAL=''{0}'' no es un n\u00FAmero decimal. + + error.newPasswordEqualsOldPassword=La nueva contrase\u00F1a no puede ser igual que la contrase\u00F1a actual ############################################################################################ @@ -416,6 +422,7 @@ project.updateDate=Fecha de inserci\u00F3n project.client=Organizaci\u00F3n project.roles=Roles project.costs=Costes +project.estimatedCost=Coste estimado project.workedHours=Horas Trabajadas project.costPerHour=Coste por Hora project.costPerProject=Coste del Proyecto @@ -426,12 +433,12 @@ projects.location=Administraci\u00F3n - Proyectos projects.title=Proyectos editProject.location=Administraci\u00F3n - Editar Proyectos editProject.title=Editar Proyectos -searchProject.location=Administraci\u00F3n - Buscar Proyectos +searchProject.location=Administraci\u00F3n - Buscar Proyectosf searchProject.title=Buscar Proyectos detailProject.location=Administraci\u00F3n - Detallar Proyectos detailProject.title=Detallar Proyectos # project - generated by stajanov (do not edit/delete) -editProject.totalCost=Coste total estimado +editProject.totalCost=Coste auto-calculado # idea - generated by stajanov (do not edit/delete) diff --git a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_pt.properties b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_pt.properties index a5c3061e..b32e3302 100755 --- a/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_pt.properties +++ b/tntconcept-web/src/main/resources/com/autentia/tnt/resources/messages_pt.properties @@ -64,6 +64,13 @@ error.enabledLogs=Logs habilitados error.disabledLogs=Logs desabilitados error.notAuthorized=Acesso não autorizado. error.newPasswordEqualsOldPassword=A nova senha não pode ser igual à senha atual + +############################################################################################ +# Convert error messages +# +javax.faces.converter.BigDecimalConverter.DECIMAL=''{0}'' deve ser um número decimal assinado. + + ############################################################################################ # Random password generation # @@ -379,6 +386,8 @@ project.updateDate=Data de inser project.client=Organização project.roles=Tarefas project.costs=custos +project.estimatedCost=Custo estimado +project.offer=Oferta project.workedHours=Horas trabalhadas project.costPerHour=Custo por Hora project.costPerProject=Custo Proyecto @@ -393,7 +402,7 @@ searchProject.title=Procurar Projetos detailProject.location=Administração - Detalhar Projetos detailProject.title=Detalhar Prohectos # project - generated by stajanov (do not edit/delete) -editProject.totalCost=Custo total estimado +editProject.totalCost=Custo auto-calculado # idea - generated by stajanov (do not edit/delete) idea.id=Id idea.creationDate=Data diff --git a/tntconcept-web/src/main/webapp/pages/admin/editProject.jsp b/tntconcept-web/src/main/webapp/pages/admin/editProject.jsp index cf9f86c4..93c8f2a2 100755 --- a/tntconcept-web/src/main/webapp/pages/admin/editProject.jsp +++ b/tntconcept-web/src/main/webapp/pages/admin/editProject.jsp @@ -28,17 +28,17 @@ - + - + - - + + <%@include file="/inc/header.jsp" %> - + <%-- Header --%> @@ -82,7 +82,7 @@ @@ -101,11 +101,11 @@ - + <%-- Field: billable --%> ${msg['project.billable']}: - + @@ -163,7 +163,19 @@ - <%-- Field: roles --%> + <%-- Field: estimatedCost --%> + + ${msg['project.estimatedCost']}: + + + + + + + + + + <%-- Field: roles --%> ${msg['project.roles']}: @@ -191,14 +203,14 @@   - + <%-- Field: Horas trabajadas --%> ${msg['project.workedHours']} - + - - + + - + <%--Si el porcentaje es mayor de uno, es decir del 100% se pintará en rojo --%> - - - + + + - + ${msg['project.costPerProject']} - + - + - - + + - + <%--Si el porcentaje es mayor de uno, es decir del 100% se pintará en rojo --%> - + - - - + + + - + - +