Erweiterungen
This commit is contained in:
@@ -15,9 +15,11 @@ import de.assecutor.votianlt.repository.PhotoRepository;
|
|||||||
import de.assecutor.votianlt.repository.TaskRepository;
|
import de.assecutor.votianlt.repository.TaskRepository;
|
||||||
import de.assecutor.votianlt.repository.BarcodeRepository;
|
import de.assecutor.votianlt.repository.BarcodeRepository;
|
||||||
import de.assecutor.votianlt.repository.SignatureRepository;
|
import de.assecutor.votianlt.repository.SignatureRepository;
|
||||||
|
import de.assecutor.votianlt.repository.CommentRepository;
|
||||||
import de.assecutor.votianlt.model.Photo;
|
import de.assecutor.votianlt.model.Photo;
|
||||||
import de.assecutor.votianlt.model.Barcode;
|
import de.assecutor.votianlt.model.Barcode;
|
||||||
import de.assecutor.votianlt.model.Signature;
|
import de.assecutor.votianlt.model.Signature;
|
||||||
|
import de.assecutor.votianlt.model.Comment;
|
||||||
import de.assecutor.votianlt.service.JobHistoryService;
|
import de.assecutor.votianlt.service.JobHistoryService;
|
||||||
import de.assecutor.votianlt.service.EmailService;
|
import de.assecutor.votianlt.service.EmailService;
|
||||||
import de.assecutor.votianlt.model.JobStatus;
|
import de.assecutor.votianlt.model.JobStatus;
|
||||||
@@ -59,13 +61,14 @@ public class MessageController {
|
|||||||
private final PhotoRepository photoRepository;
|
private final PhotoRepository photoRepository;
|
||||||
private final BarcodeRepository barcodeRepository;
|
private final BarcodeRepository barcodeRepository;
|
||||||
private final SignatureRepository signatureRepository;
|
private final SignatureRepository signatureRepository;
|
||||||
|
private final CommentRepository commentRepository;
|
||||||
private final JobHistoryService jobHistoryService;
|
private final JobHistoryService jobHistoryService;
|
||||||
private final EmailService emailService;
|
private final EmailService emailService;
|
||||||
|
|
||||||
public MessageController(MqttPublisher mqttPublisher, AppUserRepository appUserRepository,
|
public MessageController(MqttPublisher mqttPublisher, AppUserRepository appUserRepository,
|
||||||
AppUserService appUserService, JobRepository jobRepository, CargoItemRepository cargoItemRepository,
|
AppUserService appUserService, JobRepository jobRepository, CargoItemRepository cargoItemRepository,
|
||||||
TaskRepository taskRepository, PhotoRepository photoRepository, BarcodeRepository barcodeRepository,
|
TaskRepository taskRepository, PhotoRepository photoRepository, BarcodeRepository barcodeRepository,
|
||||||
SignatureRepository signatureRepository, JobHistoryService jobHistoryService, EmailService emailService) {
|
SignatureRepository signatureRepository, CommentRepository commentRepository, JobHistoryService jobHistoryService, EmailService emailService) {
|
||||||
this.mqttPublisher = mqttPublisher;
|
this.mqttPublisher = mqttPublisher;
|
||||||
this.appUserRepository = appUserRepository;
|
this.appUserRepository = appUserRepository;
|
||||||
this.appUserService = appUserService;
|
this.appUserService = appUserService;
|
||||||
@@ -75,6 +78,7 @@ public class MessageController {
|
|||||||
this.photoRepository = photoRepository;
|
this.photoRepository = photoRepository;
|
||||||
this.barcodeRepository = barcodeRepository;
|
this.barcodeRepository = barcodeRepository;
|
||||||
this.signatureRepository = signatureRepository;
|
this.signatureRepository = signatureRepository;
|
||||||
|
this.commentRepository = commentRepository;
|
||||||
this.jobHistoryService = jobHistoryService;
|
this.jobHistoryService = jobHistoryService;
|
||||||
this.emailService = emailService;
|
this.emailService = emailService;
|
||||||
}
|
}
|
||||||
@@ -245,6 +249,9 @@ public class MessageController {
|
|||||||
case "BARCODE" -> {
|
case "BARCODE" -> {
|
||||||
processBarcodeTaskCompletion(payload);
|
processBarcodeTaskCompletion(payload);
|
||||||
}
|
}
|
||||||
|
case "COMMENT" -> {
|
||||||
|
processCommentTaskCompletion(payload);
|
||||||
|
}
|
||||||
default -> {
|
default -> {
|
||||||
log.info("ERROR: handleTaskCompleted called with taskType={}, data: {}", taskType, payload);
|
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) {
|
private void completeTask(Object tid) {
|
||||||
completeTaskWithHistory(tid, null);
|
completeTaskWithHistory(tid, null);
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/main/java/de/assecutor/votianlt/model/Comment.java
Normal file
38
src/main/java/de/assecutor/votianlt/model/Comment.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,9 +35,11 @@ import de.assecutor.votianlt.repository.TaskRepository;
|
|||||||
import de.assecutor.votianlt.repository.SignatureRepository;
|
import de.assecutor.votianlt.repository.SignatureRepository;
|
||||||
import de.assecutor.votianlt.repository.BarcodeRepository;
|
import de.assecutor.votianlt.repository.BarcodeRepository;
|
||||||
import de.assecutor.votianlt.repository.PhotoRepository;
|
import de.assecutor.votianlt.repository.PhotoRepository;
|
||||||
|
import de.assecutor.votianlt.repository.CommentRepository;
|
||||||
import de.assecutor.votianlt.model.Signature;
|
import de.assecutor.votianlt.model.Signature;
|
||||||
import de.assecutor.votianlt.model.Barcode;
|
import de.assecutor.votianlt.model.Barcode;
|
||||||
import de.assecutor.votianlt.model.Photo;
|
import de.assecutor.votianlt.model.Photo;
|
||||||
|
import de.assecutor.votianlt.model.Comment;
|
||||||
import de.assecutor.votianlt.pages.service.AppUserService;
|
import de.assecutor.votianlt.pages.service.AppUserService;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
@@ -59,6 +61,7 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
private final SignatureRepository signatureRepository;
|
private final SignatureRepository signatureRepository;
|
||||||
private final BarcodeRepository barcodeRepository;
|
private final BarcodeRepository barcodeRepository;
|
||||||
private final PhotoRepository photoRepository;
|
private final PhotoRepository photoRepository;
|
||||||
|
private final CommentRepository commentRepository;
|
||||||
private final AppUserService appUserService;
|
private final AppUserService appUserService;
|
||||||
|
|
||||||
private final VerticalLayout content;
|
private final VerticalLayout content;
|
||||||
@@ -66,13 +69,14 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
|
|
||||||
public JobSummaryView(JobRepository jobRepository, CargoItemRepository cargoItemRepository,
|
public JobSummaryView(JobRepository jobRepository, CargoItemRepository cargoItemRepository,
|
||||||
TaskRepository taskRepository, SignatureRepository signatureRepository, BarcodeRepository barcodeRepository,
|
TaskRepository taskRepository, SignatureRepository signatureRepository, BarcodeRepository barcodeRepository,
|
||||||
PhotoRepository photoRepository, AppUserService appUserService) {
|
PhotoRepository photoRepository, CommentRepository commentRepository, AppUserService appUserService) {
|
||||||
this.jobRepository = jobRepository;
|
this.jobRepository = jobRepository;
|
||||||
this.cargoItemRepository = cargoItemRepository;
|
this.cargoItemRepository = cargoItemRepository;
|
||||||
this.taskRepository = taskRepository;
|
this.taskRepository = taskRepository;
|
||||||
this.signatureRepository = signatureRepository;
|
this.signatureRepository = signatureRepository;
|
||||||
this.barcodeRepository = barcodeRepository;
|
this.barcodeRepository = barcodeRepository;
|
||||||
this.photoRepository = photoRepository;
|
this.photoRepository = photoRepository;
|
||||||
|
this.commentRepository = commentRepository;
|
||||||
this.appUserService = appUserService;
|
this.appUserService = appUserService;
|
||||||
|
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
@@ -590,6 +594,36 @@ public class JobSummaryView extends Main implements HasUrlParameter<String> {
|
|||||||
if (commentTask.isRequired()) {
|
if (commentTask.isRequired()) {
|
||||||
content.add(new Span("Pflichtfeld"));
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user