Skip to content

Commit fab5bd5

Browse files
Bug #170 fixed: Active work is now instant shown in Report and added some Unit Tests for Calculations
1 parent cc804ea commit fab5bd5

3 files changed

Lines changed: 409 additions & 70 deletions

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package de.doubleslash.keeptime.controller.report;
2+
3+
import de.doubleslash.keeptime.common.DateFormatter;
4+
import de.doubleslash.keeptime.controller.Controller;
5+
import de.doubleslash.keeptime.model.Model;
6+
import de.doubleslash.keeptime.model.Project;
7+
import de.doubleslash.keeptime.model.Work;
8+
9+
import java.time.LocalDate;
10+
import java.util.*;
11+
import java.util.stream.Collectors;
12+
13+
public class Report {
14+
private final LocalDate date;
15+
private final Model model;
16+
private final Controller controller;
17+
private List<Work> workItems;
18+
private long workItemsSeconds;
19+
private SortedSet<Project> workedProjectsSet;
20+
private long presentTime;
21+
private long workTime;
22+
private Map<Long, Long> projectWorkSecondsMap;
23+
24+
public Report(LocalDate date, Model model, Controller controller) {
25+
this.date = date;
26+
this.model = model;
27+
this.controller = controller;
28+
29+
fetchWorkItems();
30+
31+
fetchProjects();
32+
33+
calculateSeconds();
34+
35+
}
36+
37+
public LocalDate getDate() {
38+
return date;
39+
}
40+
41+
public String getDateString() {
42+
return DateFormatter.toDayDateString(this.date);
43+
}
44+
45+
public List<Work> getWorkItems() {
46+
return workItems;
47+
}
48+
49+
public long getWorkItemsSeconds() {
50+
return workItemsSeconds;
51+
}
52+
53+
public SortedSet<Project> getWorkedProjectsSet() {
54+
return workedProjectsSet;
55+
}
56+
57+
public String getPresentTimeString() {
58+
return DateFormatter.secondsToHHMMSS(this.presentTime);
59+
}
60+
61+
public String getWorkTimeString() {
62+
return DateFormatter.secondsToHHMMSS(this.workTime);
63+
}
64+
65+
public Map<Long, Long> getProjectWorkSecondsMap() {
66+
return this.projectWorkSecondsMap;
67+
}
68+
69+
private void fetchWorkItems() {
70+
this.workItems = model.getWorkRepository().findByStartDateOrderByStartTimeAsc(date);
71+
72+
if (date.equals(LocalDate.now())) {
73+
Work activeWorkItem = model.activeWorkItem.get();
74+
if (activeWorkItem != null && !this.workItems.contains(activeWorkItem)) {
75+
this.workItems.add(activeWorkItem);
76+
}
77+
}
78+
}
79+
80+
private void fetchProjects() {
81+
this.workedProjectsSet = workItems.stream()
82+
.map(Work::getProject)
83+
.collect(Collectors.toCollection(
84+
() -> new TreeSet<>(Comparator.comparing(Project::getIndex))));
85+
}
86+
87+
private void calculateSeconds() {
88+
this.workItemsSeconds = this.controller.calcSeconds(this.workItems);
89+
90+
this.projectWorkSecondsMap = new HashMap<>();
91+
92+
for (final Project project : workedProjectsSet) {
93+
final List<Work> onlyCurrentProjectWork = workItems.stream()
94+
.filter(w -> w.getProject() == project)
95+
.collect(Collectors.toList());
96+
97+
final long projectWorkSeconds = this.controller.calcSeconds(onlyCurrentProjectWork);
98+
99+
projectWorkSecondsMap.put(project.getId(), projectWorkSeconds);
100+
101+
presentTime += projectWorkSeconds;
102+
if (project.isWork()) {
103+
workTime += projectWorkSeconds;
104+
}
105+
}
106+
}
107+
108+
}

src/main/java/de/doubleslash/keeptime/view/ReportController.java

Lines changed: 43 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,11 @@
1616

1717
package de.doubleslash.keeptime.view;
1818

19-
import java.io.IOException;
20-
import java.time.LocalDate;
21-
import java.util.*;
22-
import java.util.stream.Collectors;
23-
24-
import org.slf4j.Logger;
25-
import org.slf4j.LoggerFactory;
26-
import org.springframework.stereotype.Component;
27-
28-
import de.doubleslash.keeptime.common.DateFormatter;
2919
import de.doubleslash.keeptime.common.Resources;
3020
import de.doubleslash.keeptime.common.Resources.RESOURCE;
3121
import de.doubleslash.keeptime.common.SvgNodeProvider;
3222
import de.doubleslash.keeptime.controller.Controller;
23+
import de.doubleslash.keeptime.controller.report.Report;
3324
import de.doubleslash.keeptime.exceptions.FXMLLoaderException;
3425
import de.doubleslash.keeptime.model.Model;
3526
import de.doubleslash.keeptime.model.Project;
@@ -57,6 +48,14 @@
5748
import javafx.scene.shape.Circle;
5849
import javafx.stage.Stage;
5950
import javafx.util.Callback;
51+
import org.slf4j.Logger;
52+
import org.slf4j.LoggerFactory;
53+
import org.springframework.stereotype.Component;
54+
55+
import java.io.IOException;
56+
import java.time.LocalDate;
57+
import java.util.List;
58+
import java.util.Optional;
6059

6160
@Component
6261
public class ReportController {
@@ -70,43 +69,29 @@ public class ReportController {
7069
private static final String FX_BACKGROUND_COLOR_WORKED = "-fx-background-color: #00a5e1;";
7170

7271
private static final String EDIT_WORK_DIALOG_TITLE = "Edit work";
73-
72+
private static final Logger LOG = LoggerFactory.getLogger(ReportController.class);
73+
private final Model model;
74+
private final Controller controller;
75+
private final TreeItem<TableRow> rootItem = new TreeItem<>();
7476
@FXML
7577
private BorderPane topBorderPane;
76-
7778
@FXML
7879
private Label currentDayLabel;
7980
@FXML
8081
private Label currentDayWorkTimeLabel;
8182
@FXML
8283
private Label currentDayTimeLabel;
83-
8484
@FXML
8585
private TreeTableView<TableRow> workTableTreeView;
86-
8786
@FXML
8887
private AnchorPane reportRoot;
89-
9088
@FXML
9189
private Canvas colorTimeLineCanvas;
92-
9390
@FXML
9491
private Button expandCollapseButton;
95-
96-
private static final Logger LOG = LoggerFactory.getLogger(ReportController.class);
97-
98-
private final Model model;
99-
100-
private final Controller controller;
101-
10292
private Stage stage;
103-
10493
private ColorTimeLine colorTimeLine;
105-
10694
private LocalDate currentReportDate;
107-
108-
private final TreeItem<TableRow> rootItem = new TreeItem<>();
109-
11095
private boolean expanded = true;
11196

11297
public ReportController(final Model model, final Controller controller) {
@@ -121,7 +106,7 @@ private void initialize() {
121106

122107
colorTimeLine = new ColorTimeLine(colorTimeLineCanvas);
123108

124-
expandCollapseButton.setOnMouseClicked(event ->toggleCollapseExpandReport());
109+
expandCollapseButton.setOnMouseClicked(event -> toggleCollapseExpandReport());
125110
initTableView();
126111
}
127112

@@ -211,74 +196,62 @@ protected void updateItem(TableRow workItem, boolean empty) {
211196
rootItem.setExpanded(true);
212197
}
213198

214-
private void toggleCollapseExpandReport(){
199+
private void toggleCollapseExpandReport() {
215200

216-
if(expanded){
201+
if (expanded) {
217202
expandAll(false);
218203
expandCollapseButton.setText("Expand");
219204

220-
}else {
205+
} else {
221206
expandAll(true);
222207
expandCollapseButton.setText("Collapse");
223208
}
224209
expanded = !expanded;
225210
}
226211

227-
private void expandAll(boolean expand){
228-
for (int i=0; i<rootItem.getChildren().size(); i++){
212+
private void expandAll(boolean expand) {
213+
for (int i = 0; i < rootItem.getChildren().size(); i++) {
229214
rootItem.getChildren().get(i).setExpanded(expand);
230215
}
231216
}
217+
232218
private void updateReport(final LocalDate dateToShow) {
219+
Report report = new Report(dateToShow, model, controller);
220+
233221
this.currentReportDate = dateToShow;
234222
rootItem.getChildren().clear();
235223
reportRoot.requestFocus();
236224

237-
this.currentDayLabel.setText(DateFormatter.toDayDateString(this.currentReportDate));
238-
final List<Work> currentWorkItems = model.getWorkRepository()
239-
.findByStartDateOrderByStartTimeAsc(this.currentReportDate);
240-
241-
colorTimeLine.update(currentWorkItems, controller.calcSeconds(currentWorkItems));
242-
243-
final SortedSet<Project> workedProjectsSet = currentWorkItems.stream()
244-
.map(Work::getProject)
245-
.collect(Collectors.toCollection(() -> new TreeSet<>(
246-
Comparator.comparing(Project::getIndex))));
247-
248-
long currentWorkSeconds = 0;
249-
long currentSeconds = 0;
225+
this.currentDayLabel.setText(report.getDateString());
250226

251-
for (final Project project : workedProjectsSet) {
252-
final List<Work> onlyCurrentProjectWork = currentWorkItems.stream()
253-
.filter(w -> w.getProject() == project)
254-
.collect(Collectors.toList());
227+
colorTimeLine.update(report.getWorkItems(), report.getWorkItemsSeconds());
255228

256-
final long projectWorkSeconds = controller.calcSeconds(onlyCurrentProjectWork);
257-
258-
currentSeconds += projectWorkSeconds;
259-
if (project.isWork()) {
260-
currentWorkSeconds += projectWorkSeconds;
261-
}
229+
for (Project project : report.getWorkedProjectsSet()) {
230+
final List<Work> projectWorks = report.getWorkItems()
231+
.stream()
232+
.filter(w -> w.getProject().getId() == project.getId())
233+
.toList();
262234

263235
final HBox projectButtonBox = new HBox();
264-
projectButtonBox.getChildren().add(createCopyProjectButton(onlyCurrentProjectWork));
265-
236+
projectButtonBox.getChildren().add(createCopyProjectButton(projectWorks));
266237
final TreeItem<TableRow> projectRow = new TreeItem<>(
267-
new ProjectTableRow(project, projectWorkSeconds, projectButtonBox));
238+
new ProjectTableRow(project, report.getProjectWorkSecondsMap().get(project.getId()), projectButtonBox));
268239

269-
for (final Work w : onlyCurrentProjectWork) {
240+
for (final Work work : projectWorks) {
270241
final HBox workButtonBox = new HBox(5.0);
271-
if(w.getId()==model.activeWorkItem.get().getId()){
242+
243+
if (work.getId() == model.activeWorkItem.get().getId() || work.getId() == 0) {
272244
Label label = new Label("Active Work");
273-
label.setTooltip(new Tooltip("The active work item cannot be edited as it is currently active. To edit it you need to switch to another work first."));
245+
label.setTooltip(new Tooltip(
246+
"The active work item cannot be edited as it is currently active. To edit it you need to switch to another work first."));
274247
label.setStyle("-fx-font-weight: bold");
275248
workButtonBox.getChildren().add(label);
276-
}else {
277-
workButtonBox.getChildren().add(createCopyWorkButton(w));
278-
workButtonBox.getChildren().add(createEditWorkButton(w));
279-
workButtonBox.getChildren().add(createDeleteWorkButton(w));
249+
} else {
250+
workButtonBox.getChildren().add(createCopyWorkButton(work));
251+
workButtonBox.getChildren().add(createEditWorkButton(work));
252+
workButtonBox.getChildren().add(createDeleteWorkButton(work));
280253
}
281-
final TreeItem<TableRow> workRow = new TreeItem<>(new WorkTableRow(w, workButtonBox));
254+
final TreeItem<TableRow> workRow = new TreeItem<>(new WorkTableRow(work, workButtonBox));
282255
projectRow.getChildren().add(workRow);
283256
}
284257

@@ -287,8 +260,8 @@ private void updateReport(final LocalDate dateToShow) {
287260

288261
}
289262

290-
this.currentDayTimeLabel.setText(DateFormatter.secondsToHHMMSS(currentSeconds));
291-
this.currentDayWorkTimeLabel.setText(DateFormatter.secondsToHHMMSS(currentWorkSeconds));
263+
this.currentDayTimeLabel.setText(report.getPresentTimeString());
264+
this.currentDayWorkTimeLabel.setText(report.getWorkTimeString());
292265

293266
loadCalenderWidget();
294267

0 commit comments

Comments
 (0)