update work packages

This commit is contained in:
Jörg Henke
2026-01-15 11:30:27 +01:00
parent cb8de9b119
commit f8290cdbb6
5 changed files with 144 additions and 14 deletions

View File

@@ -3,8 +3,11 @@ package de.jottyfan.timetrack.modules.projectmanagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import de.jottyfan.timetrack.modules.CommonController;
import de.jottyfan.timetrack.modules.projectmanagement.model.ProjectBean;
@@ -49,4 +52,16 @@ public class ProjectmanagementController extends CommonController {
model.addAttribute("bean", WorkpackageBean.of(fkProject));
return "/projectmanagement/workpackage/item";
}
@RolesAllowed("timetrack_user")
@PostMapping("/projectmanagement/project/{fkProject}/update")
public String updateWorkpackage(@PathVariable("fkProject") Integer fkProject,
@ModelAttribute("bean") WorkpackageBean bean, BindingResult bindingResult, final Model model) {
if (bindingResult.hasErrors()) {
return "/projectmanagement/workpackage/item";
}
bean.setFkProject(fkProject);
service.updateWorkpackage(bean);
return "redirect:/projectmanagement";
}
}

View File

@@ -9,6 +9,7 @@ import java.util.List;
import java.util.Map;
import org.jooq.DSLContext;
import org.jooq.UpdateConditionStep;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@@ -51,4 +52,19 @@ public class ProjectmanagementRepository {
return jooq.selectFrom(T_WORKPACKAGE).where(T_WORKPACKAGE.PK_WORKPACKAGE.eq(pkWorkpackage)).fetchOneInto(WorkpackageBean.class);
}
public void updateWorkpackage(WorkpackageBean bean) {
UpdateConditionStep<TWorkpackageRecord> sql = jooq
// @formatter:off
.update(T_WORKPACKAGE)
.set(T_WORKPACKAGE.FK_PROJECT, bean.getFkProject())
.set(T_WORKPACKAGE.NAME, bean.getName())
.set(T_WORKPACKAGE.DESCRIPTION, bean.getDescription())
.set(T_WORKPACKAGE.MILESTONE_URL, bean.getMilestoneUrl())
.set(T_WORKPACKAGE.CONTRACT_URL, bean.getContractUrl())
.set(T_WORKPACKAGE.PLANNED_DUEDATE, bean.getPlannedDuedate())
.where(T_WORKPACKAGE.PK_WORKPACKAGE.eq(bean.getPkWorkpackage()));
// @formatter:on
sql.execute();
}
}

View File

@@ -37,4 +37,13 @@ public class ProjectmanagementService {
public WorkpackageBean getWorkpackage(Integer pkWorkpackage) {
return repository.getWorkpackage(pkWorkpackage);
}
/**
* update the workpackage
*
* @param bean the bean
*/
public void updateWorkpackage(WorkpackageBean bean) {
repository.updateWorkpackage(bean);
}
}

View File

@@ -1,6 +1,7 @@
package de.jottyfan.timetrack.modules.projectmanagement.model;
import java.io.Serializable;
import java.time.LocalDate;
import de.jottyfan.timetrack.db.project.tables.records.TWorkpackageRecord;
@@ -13,14 +14,22 @@ public class WorkpackageBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer pkWorkpackage;
private String name;
private Integer fkProject;
private String name;
private String description;
private String milestoneUrl;
private String contractUrl;
private LocalDate plannedDuedate;
public static final WorkpackageBean of(TWorkpackageRecord r) {
WorkpackageBean bean = new WorkpackageBean();
bean.setPkWorkpackage(r.getPkWorkpackage());
bean.setName(r.getName());
bean.setFkProject(r.getFkProject());
bean.setName(r.getName());
bean.setDescription(r.getDescription());
bean.setMilestoneUrl(r.getMilestoneUrl());
bean.setContractUrl(r.getContractUrl());
bean.setPlannedDuedate(r.getPlannedDuedate());
return bean;
}
@@ -71,4 +80,60 @@ public class WorkpackageBean implements Serializable {
public void setFkProject(Integer fkProject) {
this.fkProject = fkProject;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the milestoneUrl
*/
public String getMilestoneUrl() {
return milestoneUrl;
}
/**
* @param milestoneUrl the milestoneUrl to set
*/
public void setMilestoneUrl(String milestoneUrl) {
this.milestoneUrl = milestoneUrl;
}
/**
* @return the contractUrl
*/
public String getContractUrl() {
return contractUrl;
}
/**
* @param contractUrl the contractUrl to set
*/
public void setContractUrl(String contractUrl) {
this.contractUrl = contractUrl;
}
/**
* @return the plannedDuedate
*/
public LocalDate getPlannedDuedate() {
return plannedDuedate;
}
/**
* @param plannedDuedate the plannedDuedate to set
*/
public void setPlannedDuedate(LocalDate plannedDuedate) {
this.plannedDuedate = plannedDuedate;
}
}

View File

@@ -16,15 +16,40 @@
TODO: Maske zum Anlegen eines neuen Workpackages für Projekt <span th:text="${bean.fkProject}"></span>
</div>
<div th:if="${bean.pkWorkpackage}">
<div class="container m-2">
<div class="row g-2">
<div class="col-2">ID</div>
<div class="col-10"><span class="form-control" th:text="${bean.pkWorkpackage}"></span></div>
<div class="col-2">Name</div>
<div class="col-10"><span class="form-control" th:text="${bean.name}"></span></div>
<form th:action="@{/projectmanagement/project/{p}/update(p=${bean.fkProject})}" method="post" th:object="${bean}">
<div class="container m-2">
<div class="row g-2">
<div class="col-2">ID</div>
<div class="col-10">
<input type="text" class="form-control" th:field="*{pkWorkpackage}" readonly="readonly" />
</div>
<div class="col-2">Name</div>
<div class="col-10">
<input type="text" class="form-control" th:field="*{name}" />
</div>
<div class="col-2">Beschreibung</div>
<div class="col-10">
<textarea class="form-control" th:field="*{description}"></textarea>
</div>
<div class="col-2">Milestone-URL</div>
<div class="col-10">
<input type="text" class="form-control" th:field="*{milestoneUrl}" />
</div>
<div class="col-2">Auftragsdokument</div>
<div class="col-10">
<input type="text" class="form-control" th:field="*{contractUrl}" />
</div>
<div class="col-2">geplante Fertigstellung</div>
<div class="col-10">
<input type="text" class="form-control" th:field="*{plannedDuedate}" />
</div>
<div class="col-2"></div>
<div class="col-10">
<input type="submit" class="btn btn-primary" value="Speichern">
</div>
</div>
</div>
</div>
TODO: Maske zum Bearbeiten eines bestehenden Workpackages
</form>
</div>
</div>
</main>