Browse Source

started implementing listTimes – way to complicated

feature/document
Stephan Richter 4 months ago
parent
commit
a75c58932d
  1. 3
      backend/build.gradle.kts
  2. 3
      backend/src/main/java/de/srsoftware/umbrella/backend/Application.java
  3. 9
      core/src/main/java/de/srsoftware/umbrella/core/Constants.java
  4. 7
      core/src/main/java/de/srsoftware/umbrella/core/Util.java
  5. 15
      core/src/main/java/de/srsoftware/umbrella/core/api/TaskService.java
  6. 5
      core/src/main/java/de/srsoftware/umbrella/core/api/TimeService.java
  7. 5
      core/src/main/java/de/srsoftware/umbrella/core/model/Task.java
  8. 77
      core/src/main/java/de/srsoftware/umbrella/core/model/Time.java
  9. 15
      settings.gradle.kts
  10. 7
      task/src/main/java/de/srsoftware/umbrella/task/Constants.java
  11. 3
      task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java
  12. 30
      task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java
  13. 5
      time/build.gradle.kts
  14. 18
      time/src/main/java/de/srsoftware/umbrella/time/Constants.java
  15. 50
      time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java
  16. 11
      time/src/main/java/de/srsoftware/umbrella/time/TimeDb.java
  17. 92
      time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java

3
backend/build.gradle.kts

@ -19,8 +19,9 @@ dependencies{
implementation(project(":legacy")) implementation(project(":legacy"))
implementation(project(":markdown")) implementation(project(":markdown"))
implementation(project(":messages")) implementation(project(":messages"))
implementation(project(":task"))
implementation(project(":project")) implementation(project(":project"))
implementation(project(":task"))
implementation(project(":time"))
implementation(project(":translations")) implementation(project(":translations"))
implementation(project(":user")) implementation(project(":user"))
implementation(project(":web")) implementation(project(":web"))

3
backend/src/main/java/de/srsoftware/umbrella/backend/Application.java

@ -19,6 +19,7 @@ import de.srsoftware.umbrella.message.MessageApi;
import de.srsoftware.umbrella.message.MessageSystem; import de.srsoftware.umbrella.message.MessageSystem;
import de.srsoftware.umbrella.project.ProjectModule; import de.srsoftware.umbrella.project.ProjectModule;
import de.srsoftware.umbrella.task.TaskModule; import de.srsoftware.umbrella.task.TaskModule;
import de.srsoftware.umbrella.time.TimeModule;
import de.srsoftware.umbrella.translations.Translations; import de.srsoftware.umbrella.translations.Translations;
import de.srsoftware.umbrella.user.UserModule; import de.srsoftware.umbrella.user.UserModule;
import de.srsoftware.umbrella.web.WebHandler; import de.srsoftware.umbrella.web.WebHandler;
@ -66,6 +67,7 @@ public class Application {
var messageApi = new MessageApi(messageSystem); var messageApi = new MessageApi(messageSystem);
var projectModule = new ProjectModule(config,companyModule); var projectModule = new ProjectModule(config,companyModule);
var taskModule = new TaskModule(config,projectModule); var taskModule = new TaskModule(config,projectModule);
var timeModule = new TimeModule(config,taskModule);
var webHandler = new WebHandler(); var webHandler = new WebHandler();
documentApi .bindPath("/api/document") .on(server); documentApi .bindPath("/api/document") .on(server);
@ -74,6 +76,7 @@ public class Application {
messageApi .bindPath("/api/messages") .on(server); messageApi .bindPath("/api/messages") .on(server);
projectModule .bindPath("/api/project") .on(server); projectModule .bindPath("/api/project") .on(server);
taskModule .bindPath("/api/task") .on(server); taskModule .bindPath("/api/task") .on(server);
timeModule .bindPath("/api/times") .on(server);
translationModule.bindPath("/api/translations").on(server); translationModule.bindPath("/api/translations").on(server);
userModule .bindPath("/api/user") .on(server); userModule .bindPath("/api/user") .on(server);
legacyApi .bindPath("/legacy") .on(server); legacyApi .bindPath("/legacy") .on(server);

9
core/src/main/java/de/srsoftware/umbrella/core/Constants.java

@ -19,13 +19,17 @@ public class Constants {
public static final String DEFAULT_THEME = "winter"; public static final String DEFAULT_THEME = "winter";
public static final String DESCRIPTION = "description"; public static final String DESCRIPTION = "description";
public static final String DOMAIN = "domain"; public static final String DOMAIN = "domain";
public static final String DUE_DATE = "due_date";
public static final String EMAIL = "email"; public static final String EMAIL = "email";
public static final String END_TIME = "end_time";
public static final String ERROR_FAILED_CREATE_TABLE = "Failed to create \"{0}\" table!"; public static final String ERROR_FAILED_CREATE_TABLE = "Failed to create \"{0}\" table!";
public static final String ERROR_INVALID_FIELD = "Expected {0} to be {1}!"; public static final String ERROR_INVALID_FIELD = "Expected {0} to be {1}!";
public static final String ERROR_MISSING_CONFIG = "Config is missing value for {0}!"; public static final String ERROR_MISSING_CONFIG = "Config is missing value for {0}!";
public static final String ERROR_MISSING_FIELD = "Json is missing {0} field!"; public static final String ERROR_MISSING_FIELD = "Json is missing {0} field!";
public static final String ERROR_READ_TABLE = "Failed to read {0} from {1} table"; public static final String ERROR_READ_TABLE = "Failed to read {0} from {1} table";
public static final String EST_TIME = "est_time";
public static final String ESTIMATED_TIME = "estimated_time";
public static final String EXPIRATION = "expiration"; public static final String EXPIRATION = "expiration";
public static final String GET = "GET"; public static final String GET = "GET";
@ -37,11 +41,14 @@ public class Constants {
public static final String MESSAGES = "messages"; public static final String MESSAGES = "messages";
public static final String NAME = "name"; public static final String NAME = "name";
public static final String MIME = "mime"; public static final String MIME = "mime";
public static final String NO_INDEX = "no_index";
public static final String NUMBER = "number"; public static final String NUMBER = "number";
public static final String OPTIONAL = "optional"; public static final String OPTIONAL = "optional";
public static final String PARENT_TASK_ID = "parent_task_id";
public static final String PASS = "pass"; public static final String PASS = "pass";
public static final String PASSWORD = "password"; public static final String PASSWORD = "password";
public static final String POST = "POST"; public static final String POST = "POST";
public static final String PROJECT_ID = "project_id";
public static final String RECEIVERS = "receivers"; public static final String RECEIVERS = "receivers";
public static final String REDIRECT = "redirect"; public static final String REDIRECT = "redirect";
@ -50,6 +57,8 @@ public class Constants {
public static final String SETTINGS = "settings"; public static final String SETTINGS = "settings";
public static final String SHOW_CLOSED = "show_closed"; public static final String SHOW_CLOSED = "show_closed";
public static final String SOURCE = "source"; public static final String SOURCE = "source";
public static final String START_DATE = "start_date";
public static final String START_TIME = "start_time";
public static final String STATE = "state"; public static final String STATE = "state";
public static final String STATUS = "status"; public static final String STATUS = "status";
public static final String STATUS_CODE = "code"; public static final String STATUS_CODE = "code";

7
core/src/main/java/de/srsoftware/umbrella/core/Util.java

@ -15,6 +15,9 @@ import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.json.JSONObject; import org.json.JSONObject;
@ -140,4 +143,8 @@ public class Util {
LOG.log(INFO,"Using plantuml @ {0}",file.getAbsolutePath()); LOG.log(INFO,"Using plantuml @ {0}",file.getAbsolutePath());
plantumlJar = file; plantumlJar = file;
} }
public static LocalDateTime dateTimeOf(long epocSecs){
return LocalDateTime.ofInstant(Instant.ofEpochSecond(epocSecs), ZoneId.systemDefault());
}
} }

15
core/src/main/java/de/srsoftware/umbrella/core/api/TaskService.java

@ -0,0 +1,15 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.api;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Task;
import java.util.Collection;
public interface TaskService {
CompanyService companyService();
Collection<Task> listCompanyTasks(long companyId) throws UmbrellaException;
ProjectService projectService();
UserService userService();
}

5
core/src/main/java/de/srsoftware/umbrella/core/api/TimeService.java

@ -0,0 +1,5 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.api;
public interface TimeService {
}

5
task/src/main/java/de/srsoftware/umbrella/task/Task.java → core/src/main/java/de/srsoftware/umbrella/core/model/Task.java

@ -1,12 +1,9 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.task; package de.srsoftware.umbrella.core.model;
import static de.srsoftware.tools.Optionals.nullIfEmpty; import static de.srsoftware.tools.Optionals.nullIfEmpty;
import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Constants.SHOW_CLOSED;
import static de.srsoftware.umbrella.core.Constants.STATUS;
import static de.srsoftware.umbrella.core.Util.markdown; import static de.srsoftware.umbrella.core.Util.markdown;
import static de.srsoftware.umbrella.task.Constants.*;
import de.srsoftware.tools.Mappable; import de.srsoftware.tools.Mappable;
import java.sql.ResultSet; import java.sql.ResultSet;

77
core/src/main/java/de/srsoftware/umbrella/core/model/Time.java

@ -0,0 +1,77 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.model;
import de.srsoftware.tools.Mappable;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Util.dateTimeOf;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public record Time(long id, long userId, String subject, String description, LocalDateTime start, LocalDateTime end, State state, Set<Long> taskIds) implements Mappable {
public enum State{
Started(10),
Open(20),
Pending(40),
Complete(60),
Cancelled(100);
private int code;
State(int code){
this.code = code;
}
public int code(){
return code;
}
public static State of(int code){
return switch (code){
case 10 -> Started;
case 20 -> Open;
case 40 -> Pending;
case 60 -> Complete;
case 100 -> Cancelled;
default -> throw new IllegalArgumentException();
};
}
}
@Override
public Map<String, Object> toMap() {
var map = new HashMap<String,Object>();
map.put(ID,id);
map.put(USER_ID,userId);
map.put(SUBJECT,subject);
map.put(DESCRIPTION,description);
map.put(START_TIME,start);
map.put(END_TIME,end);
map.put(STATE,Map.of(STATUS_CODE,state.code,NAME,state.name()));
return map;
}
public static Time of(ResultSet rs) throws SQLException {
var startTimestamp = rs.getLong(START_TIME);
var start = startTimestamp == 0 ? null : dateTimeOf(startTimestamp);
var endTimestamp = rs.getLong(END_TIME);
var end = endTimestamp == 0 ? null : dateTimeOf(endTimestamp);
return new Time(
rs.getLong(ID),
rs.getLong(USER_ID),
rs.getString(SUBJECT),
rs.getString(DESCRIPTION),
start,
end,
State.of(rs.getInt(STATE)),
new HashSet<>()
);
}
}

15
settings.gradle.kts

@ -1,18 +1,17 @@
rootProject.name = "Umbrella25" rootProject.name = "Umbrella25"
include("backend") include("backend")
include("company")
include("contact")
include("core") include("core")
include("documents") include("documents")
include("legacy") include("legacy")
include("items")
include("messages") include("messages")
include("translations")
include("user")
include("web")
include("company")
include("contact")
include("markdown") include("markdown")
include("project") include("project")
include("items")
include("task") include("task")
include("time")
include("translations")
include("user")
include("web")

7
task/src/main/java/de/srsoftware/umbrella/task/Constants.java

@ -6,14 +6,7 @@ public class Constants {
public static final String CONFIG_DATABASE = "umbrella.modules.task.database"; public static final String CONFIG_DATABASE = "umbrella.modules.task.database";
public static final String CHILDREN = "children"; public static final String CHILDREN = "children";
public static final String DUE_DATE = "due_date";
public static final String ESTIMATED_TIMES = "estimated_times"; public static final String ESTIMATED_TIMES = "estimated_times";
public static final String ESTIMATED_TIME = "estimated_time";
public static final String EST_TIME = "est_time";
public static final String NO_INDEX = "no_index";
public static final String PARENT_TASK_ID = "parent_task_id";
public static final String PROJECT_ID = "project_id";
public static final String START_DATE = "start_date";
public static final String TABLE_TASKS = "tasks"; public static final String TABLE_TASKS = "tasks";
public static final String FIELD_TASKS = "tasks"; public static final String FIELD_TASKS = "tasks";
} }

3
task/src/main/java/de/srsoftware/umbrella/task/SqliteDb.java

@ -4,11 +4,12 @@ package de.srsoftware.umbrella.task;
import static de.srsoftware.tools.jdbc.Condition.in; import static de.srsoftware.tools.jdbc.Condition.in;
import static de.srsoftware.tools.jdbc.Query.select; import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.umbrella.core.Constants.PROJECT_ID;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR;
import static de.srsoftware.umbrella.task.Constants.PROJECT_ID;
import static de.srsoftware.umbrella.task.Constants.TABLE_TASKS; import static de.srsoftware.umbrella.task.Constants.TABLE_TASKS;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Task;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;

30
task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java

@ -4,10 +4,10 @@ package de.srsoftware.umbrella.task;
import static de.srsoftware.tools.Optionals.is0; import static de.srsoftware.tools.Optionals.is0;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.COMPANY_ID; import static de.srsoftware.umbrella.core.Constants.COMPANY_ID;
import static de.srsoftware.umbrella.core.Constants.PROJECT_ID;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.task.Constants.*; import static de.srsoftware.umbrella.task.Constants.*;
import static java.util.Objects.isNull;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
@ -17,16 +17,17 @@ import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.api.CompanyService; import de.srsoftware.umbrella.core.api.CompanyService;
import de.srsoftware.umbrella.core.api.ProjectService; import de.srsoftware.umbrella.core.api.ProjectService;
import de.srsoftware.umbrella.core.api.TaskService;
import de.srsoftware.umbrella.core.api.UserService; import de.srsoftware.umbrella.core.api.UserService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Project; import de.srsoftware.umbrella.core.model.Project;
import de.srsoftware.umbrella.core.model.Task;
import de.srsoftware.umbrella.core.model.Token; import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class TaskModule extends BaseHandler { public class TaskModule extends BaseHandler implements TaskService {
private final SqliteDb taskDb; private final SqliteDb taskDb;
private final ProjectService projects; private final ProjectService projects;
@ -41,7 +42,12 @@ public class TaskModule extends BaseHandler {
users = companies.userService(); users = companies.userService();
} }
@Override @Override
public CompanyService companyService() {
return companies;
}
@Override
public boolean doPost(Path path, HttpExchange ex) throws IOException { public boolean doPost(Path path, HttpExchange ex) throws IOException {
addCors(ex); addCors(ex);
try { try {
@ -81,6 +87,12 @@ public class TaskModule extends BaseHandler {
return sendContent(ex,result); return sendContent(ex,result);
} }
@Override
public Collection<Task> listCompanyTasks(long companyId) throws UmbrellaException {
var projectList = projects.listProjects(companyId,false);
return taskDb.listTasks(projectList.stream().map(Project::id).toList());
}
private Map<String,Object> placeInTree(Task task, HashMap<Long, Map<String,Object>> tree, Map<Long, Task> map) { private Map<String,Object> placeInTree(Task task, HashMap<Long, Map<String,Object>> tree, Map<Long, Task> map) {
var taskMap = task.toMap(); var taskMap = task.toMap();
if (task.parentTaskId() != null){ if (task.parentTaskId() != null){
@ -93,4 +105,14 @@ public class TaskModule extends BaseHandler {
tree.put(task.id(),taskMap); tree.put(task.id(),taskMap);
return taskMap; return taskMap;
} }
@Override
public ProjectService projectService() {
return projects;
}
@Override
public UserService userService() {
return users;
}
} }

5
time/build.gradle.kts

@ -0,0 +1,5 @@
description = "Umbrella : Timetracking"
dependencies{
implementation(project(":core"))
}

18
time/src/main/java/de/srsoftware/umbrella/time/Constants.java

@ -0,0 +1,18 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.time;
public class Constants {
private Constants(){}
public static final String CONFIG_DATABASE = "umbrella.modules.time.database";
public static final String TABLE_TASK_TIMES = "task_times";
public static final String TABLE_TIMES = "times";
public static final String TASK_ID = "task_id";
public static final String TASKS = "tasks";
public static final String TIME_ID = "time_id";
public static final String TIMES = "times";
public static final String CHILDREN = "children";
}

50
time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java

@ -0,0 +1,50 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.time;
import static de.srsoftware.tools.jdbc.Condition.in;
import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.umbrella.core.Constants.ID;
import static de.srsoftware.umbrella.time.Constants.*;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Time;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
public class SqliteDb implements TimeDb {
private final Connection db;
public SqliteDb(Connection connection) {
db = connection;
}
@Override
public Collection<Time> listTimes(Collection<Long> taskIds) throws UmbrellaException {
try {
var rs = select("*").from(TABLE_TASK_TIMES).where(TASK_ID,in(taskIds.toArray())).exec(db);
var mapFromTimesToTasks = new HashMap<Long,HashSet<Long>>();
while (rs.next()){
var timeId = rs.getLong(TIME_ID);
var taskId = rs.getLong(TASK_ID);
mapFromTimesToTasks.computeIfAbsent(timeId, k -> new HashSet<>()).add(taskId);
}
rs.close();
rs = select("*").from(TABLE_TIMES).where(ID,in(mapFromTimesToTasks.keySet().toArray())).exec(db);
var times = new HashSet<Time>();
while (rs.next()) {
var time = Time.of(rs);
time.taskIds().addAll(mapFromTimesToTasks.get(time.id()));
times.add(time);
}
rs.close();
return times;
} catch (SQLException e) {
throw new UmbrellaException("Failed to load times for task list");
}
}
}

11
time/src/main/java/de/srsoftware/umbrella/time/TimeDb.java

@ -0,0 +1,11 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.time;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Time;
import java.util.Collection;
import java.util.List;
public interface TimeDb {
Collection<Time> listTimes(Collection<Long> taskIds) throws UmbrellaException;
}

92
time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java

@ -0,0 +1,92 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.time;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.time.Constants.*;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.SessionToken;
import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.api.*;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.*;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class TimeModule extends BaseHandler implements TimeService {
private final UserService users;
private final TimeDb timeDb;
private final TaskService tasks;
private final CompanyService companies;
private final ProjectService projects;
public TimeModule(Configuration config, TaskService taskService) throws UmbrellaException {
companies = taskService.companyService();
projects = taskService.projectService();
tasks = taskService;
users = tasks.userService();
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE));
timeDb = new SqliteDb(connect(dbFile));
}
@Override
public boolean doPost(Path path, HttpExchange ex) throws IOException {
addCors(ex);
try {
Optional<Token> token = SessionToken.from(ex).map(Token::of);
var user = users.loadUser(token);
if (user.isEmpty()) return unauthorized(ex);
var head = path.pop();
return switch (head) {
case LIST -> listTimes(ex,user.get());
default -> super.doPost(path,ex);
};
} catch (UmbrellaException e){
return send(ex,e);
}
}
private boolean listTimes(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
var json = json(ex);
if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID);
long companyId = cid.longValue();
if (!companies.membership(companyId,user.id())) throw UmbrellaException.forbidden("You are not a member of compayn {0}",companyId);
var projectMap = projects.listProjects(companyId,false).stream().collect(Collectors.toMap(Project::id,p -> p));
var taskMap = tasks.listCompanyTasks(companyId).stream().collect(Collectors.toMap(Task::id,Task::toMap));
var timesList = timeDb.listTimes(taskMap.keySet());
var tasksWithTime = new HashMap<Long,Map<String,Object>>();
var tree = new HashMap<Long,Map<String,Object>>();
for (var time : timesList) {
if (time.state().code() >= 60) continue;
var timeMap = time.toMap();
for (var taskId : time.taskIds()) {
var task = tasksWithTime.computeIfAbsent(taskId, k -> taskMap.get(taskId));
@SuppressWarnings("unchecked")
HashMap<Long,Map<String, Object>> taskTimes = (HashMap<Long,Map<String, Object>>) task.computeIfAbsent(TIMES, k -> new HashMap<Long,Map<String, Object>>());
taskTimes.put(time.id(),timeMap);
while (task.get(PARENT_TASK_ID) instanceof Long parentTaskId){
var parentTask = taskMap.get(parentTaskId);
@SuppressWarnings("unchecked")
HashMap<Long,Map<String, Object>> children = (HashMap<Long,Map<String, Object>>) parentTask.computeIfAbsent(CHILDREN, k -> new HashMap<Long,Map<String, Object>>());
children.put(taskId,task);
task = parentTask;
taskId = parentTaskId;
}
if (task.get(PROJECT_ID) instanceof Long projectId){
var project = tree.computeIfAbsent(projectId,k -> new HashMap<>(projectMap.get(projectId).toMap()));
@SuppressWarnings("unchecked")
HashMap<Long,Map<String,Object>> projectTasks = (HashMap<Long,Map<String, Object>>) project.computeIfAbsent(TASKS, k -> new HashMap<Long,Map<String,Object>>());
projectTasks.put(taskId,task);
}
}
}
return sendContent(ex,tree);
}
}
Loading…
Cancel
Save