Add user and project rate editing across backend and frontend

This commit is contained in:
2026-05-21 13:43:17 +02:00
parent 38f1461d37
commit 1b420271c7
13 changed files with 623 additions and 40 deletions
@@ -2,6 +2,7 @@ package com.example.app.project;
import com.example.app.project.ProjectDtos.CreateProjectRequest;
import com.example.app.project.ProjectDtos.ProjectResponse;
import com.example.app.project.ProjectDtos.UpdateProjectRequest;
import jakarta.validation.Valid;
import java.util.List;
import org.springframework.http.HttpStatus;
@@ -27,4 +28,10 @@ public class ProjectController {
public ProjectResponse create(@Valid @RequestBody CreateProjectRequest req) {
return projectService.create(req);
}
@PutMapping("/{id}")
public ProjectResponse update(
@PathVariable Long id, @Valid @RequestBody UpdateProjectRequest req) {
return projectService.update(id, req);
}
}
@@ -12,6 +12,12 @@ public class ProjectDtos {
@PositiveOrZero int costBudgetCents,
@PositiveOrZero Integer hourlyRateCents) {}
public record UpdateProjectRequest(
@NotBlank String name,
@Min(1) int timeBudgetMinutes,
@PositiveOrZero int costBudgetCents,
@PositiveOrZero Integer hourlyRateCents) {}
public record ProjectResponse(
Long id,
String name,
@@ -2,7 +2,9 @@ package com.example.app.project;
import com.example.app.project.ProjectDtos.CreateProjectRequest;
import com.example.app.project.ProjectDtos.ProjectResponse;
import com.example.app.project.ProjectDtos.UpdateProjectRequest;
import com.example.app.time.TimeEntryRepository;
import jakarta.persistence.EntityNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -53,4 +55,29 @@ public class ProjectService {
Project saved = projectRepository.save(p);
return ProjectResponse.from(saved, 0, 0);
}
@Transactional
public ProjectResponse update(Long id, UpdateProjectRequest req) {
Project project =
projectRepository
.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Project not found: " + id));
project.setName(req.name());
project.setTimeBudgetMinutes(req.timeBudgetMinutes());
project.setCostBudgetCents(req.costBudgetCents());
project.setHourlyRateCents(req.hourlyRateCents());
Project saved = projectRepository.save(project);
long[] totals = new long[] {0, 0};
for (Object[] row : timeEntryRepository.aggregateAllByProject()) {
long projectId = ((Number) row[0]).longValue();
if (projectId == saved.getId()) {
totals[0] = ((Number) row[1]).longValue();
totals[1] = ((Number) row[2]).longValue();
break;
}
}
return ProjectResponse.from(saved, totals[0], totals[1]);
}
}