started implementing listTimes – way to complicated
This commit is contained in:
@@ -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
Normal file
50
time/src/main/java/de/srsoftware/umbrella/time/SqliteDb.java
Normal file
@@ -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
Normal file
11
time/src/main/java/de/srsoftware/umbrella/time/TimeDb.java
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user