Erweiterungen

This commit is contained in:
2025-09-16 10:04:53 +02:00
parent 2444574d35
commit 5d0b59c46f
4 changed files with 159 additions and 2 deletions

View File

@@ -15,9 +15,11 @@ import de.assecutor.votianlt.repository.PhotoRepository;
import de.assecutor.votianlt.repository.TaskRepository;
import de.assecutor.votianlt.repository.BarcodeRepository;
import de.assecutor.votianlt.repository.SignatureRepository;
import de.assecutor.votianlt.repository.CommentRepository;
import de.assecutor.votianlt.model.Photo;
import de.assecutor.votianlt.model.Barcode;
import de.assecutor.votianlt.model.Signature;
import de.assecutor.votianlt.model.Comment;
import de.assecutor.votianlt.service.JobHistoryService;
import de.assecutor.votianlt.service.EmailService;
import de.assecutor.votianlt.model.JobStatus;
@@ -59,13 +61,14 @@ public class MessageController {
private final PhotoRepository photoRepository;
private final BarcodeRepository barcodeRepository;
private final SignatureRepository signatureRepository;
private final CommentRepository commentRepository;
private final JobHistoryService jobHistoryService;
private final EmailService emailService;
public MessageController(MqttPublisher mqttPublisher, AppUserRepository appUserRepository,
AppUserService appUserService, JobRepository jobRepository, CargoItemRepository cargoItemRepository,
TaskRepository taskRepository, PhotoRepository photoRepository, BarcodeRepository barcodeRepository,
SignatureRepository signatureRepository, JobHistoryService jobHistoryService, EmailService emailService) {
SignatureRepository signatureRepository, CommentRepository commentRepository, JobHistoryService jobHistoryService, EmailService emailService) {
this.mqttPublisher = mqttPublisher;
this.appUserRepository = appUserRepository;
this.appUserService = appUserService;
@@ -75,6 +78,7 @@ public class MessageController {
this.photoRepository = photoRepository;
this.barcodeRepository = barcodeRepository;
this.signatureRepository = signatureRepository;
this.commentRepository = commentRepository;
this.jobHistoryService = jobHistoryService;
this.emailService = emailService;
}
@@ -245,6 +249,9 @@ public class MessageController {
case "BARCODE" -> {
processBarcodeTaskCompletion(payload);
}
case "COMMENT" -> {
processCommentTaskCompletion(payload);
}
default -> {
log.info("ERROR: handleTaskCompleted called with taskType={}, data: {}", taskType, payload);
}
@@ -413,6 +420,45 @@ public class MessageController {
}
}
private void processCommentTaskCompletion(Map<String, Object> payload) {
Object taskId = payload.get("taskId");
try {
var opt = taskRepository.findById(new ObjectId(taskId.toString()));
if (opt.isEmpty()) {
log.warn("Task not found for comment completion. taskId={}", taskId);
return;
}
BaseTask task = opt.get();
String extraDataSummary = null;
Object extra = payload.get("extraData");
if (extra instanceof Map<?, ?> extraData) {
Object commentTextObj = extraData.get("commentText");
if (commentTextObj instanceof String commentText && !commentText.isBlank()) {
// Save comment to database
String completedBy = task.getCompletedBy() != null ? task.getCompletedBy() : "Unknown";
Comment commentEntry = new Comment(new ObjectId(taskId.toString()), commentText, completedBy);
commentRepository.save(commentEntry);
extraDataSummary = "Kommentar: " + commentText;
log.info("Comment saved for taskId={}: {}", taskId, commentText);
} else {
extraDataSummary = "Kommentar abgegeben (leer)";
}
} else {
extraDataSummary = "Kommentar abgegeben";
log.warn("extraData is not a Map for comment task completion, taskId={}", taskId);
}
// Finally, mark the task as completed with history logging
completeTaskWithHistory(taskId, extraDataSummary);
} catch (IllegalArgumentException ex) {
log.error("Invalid taskId format for comment completion: {}", taskId);
} catch (Exception ex) {
log.error("Error while processing comment task completion (taskId={}): {}", taskId, ex.getMessage(), ex);
}
}
private void completeTask(Object tid) {
completeTaskWithHistory(tid, null);
}

View File

@@ -0,0 +1,38 @@
package de.assecutor.votianlt.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@Document(collection = "comments")
public class Comment {
@Id
private ObjectId id;
@Field("task_id")
private ObjectId taskId;
@Field("comment_text")
private String commentText;
@Field("completed_by")
private String completedBy;
@Field("created_at")
private LocalDateTime createdAt;
public Comment(ObjectId taskId, String commentText, String completedBy) {
this.taskId = taskId;
this.commentText = commentText;
this.completedBy = completedBy;
this.createdAt = LocalDateTime.now();
}
}

View File

@@ -35,9 +35,11 @@ import de.assecutor.votianlt.repository.TaskRepository;
import de.assecutor.votianlt.repository.SignatureRepository;
import de.assecutor.votianlt.repository.BarcodeRepository;
import de.assecutor.votianlt.repository.PhotoRepository;
import de.assecutor.votianlt.repository.CommentRepository;
import de.assecutor.votianlt.model.Signature;
import de.assecutor.votianlt.model.Barcode;
import de.assecutor.votianlt.model.Photo;
import de.assecutor.votianlt.model.Comment;
import de.assecutor.votianlt.pages.service.AppUserService;
import jakarta.annotation.security.RolesAllowed;
import org.bson.types.ObjectId;
@@ -59,6 +61,7 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
private final SignatureRepository signatureRepository;
private final BarcodeRepository barcodeRepository;
private final PhotoRepository photoRepository;
private final CommentRepository commentRepository;
private final AppUserService appUserService;
private final VerticalLayout content;
@@ -66,13 +69,14 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
public JobSummaryView(JobRepository jobRepository, CargoItemRepository cargoItemRepository,
TaskRepository taskRepository, SignatureRepository signatureRepository, BarcodeRepository barcodeRepository,
PhotoRepository photoRepository, AppUserService appUserService) {
PhotoRepository photoRepository, CommentRepository commentRepository, AppUserService appUserService) {
this.jobRepository = jobRepository;
this.cargoItemRepository = cargoItemRepository;
this.taskRepository = taskRepository;
this.signatureRepository = signatureRepository;
this.barcodeRepository = barcodeRepository;
this.photoRepository = photoRepository;
this.commentRepository = commentRepository;
this.appUserService = appUserService;
setSizeFull();
@@ -590,6 +594,36 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
if (commentTask.isRequired()) {
content.add(new Span("Pflichtfeld"));
}
// Show comments if task is completed
if (task.isCompleted()) {
try {
ObjectId taskId = new ObjectId(task.getIdAsString());
List<Comment> comments = commentRepository.findByTaskIdOrderByCreatedAtDesc(taskId);
if (!comments.isEmpty()) {
content.add(new Span("Abgegebene Kommentare (" + comments.size() + "):"));
for (Comment comment : comments) {
Div commentContainer = new Div();
commentContainer.getStyle()
.set("background-color", "#f5f5f5")
.set("border", "1px solid #ddd")
.set("border-radius", "4px")
.set("padding", "8px")
.set("margin", "4px 0")
.set("font-family", "monospace")
.set("white-space", "pre-wrap");
Span commentText = new Span(comment.getCommentText());
commentContainer.add(commentText);
content.add(commentContainer);
}
}
} catch (Exception e) {
log.debug("Failed to load comments for task {}: {}", task.getId(), e.getMessage());
}
}
}
}

View File

@@ -0,0 +1,39 @@
package de.assecutor.votianlt.repository;
import de.assecutor.votianlt.model.Comment;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CommentRepository extends MongoRepository<Comment, ObjectId> {
/**
* Find all comments for a specific task, ordered by creation time descending
* (newest first)
*/
List<Comment> findByTaskIdOrderByCreatedAtDesc(ObjectId taskId);
/**
* Find all comments for a specific task, ordered by creation time ascending
* (oldest first)
*/
List<Comment> findByTaskIdOrderByCreatedAtAsc(ObjectId taskId);
/**
* Find comments by who completed them
*/
List<Comment> findByCompletedByOrderByCreatedAtDesc(String completedBy);
/**
* Count comments for a specific task
*/
long countByTaskId(ObjectId taskId);
/**
* Delete all comments for a specific task
*/
void deleteByTaskId(ObjectId taskId);
}